Browse files

(strong-random): support floats as well as integers; do not accept ne…

…gative integers
  • Loading branch information...
1 parent cfccd64 commit 9c094f3508668ce142545f64c3e9e66af3667b8d @eadmund committed Mar 3, 2012
Showing with 18 additions and 17 deletions.
  1. +18 −17 src/prng/prng.lisp
View
35 src/prng/prng.lisp
@@ -31,14 +31,6 @@
(t (error "SEED must be an octet vector, pathname indicator, :random or :urandom")))
prng))
-(defmethod make-prng ((name (eql :fortuna)) &key seed)
- (make-instance 'fortuna-prng))
-
-;; FIXME: this is more than a little ugly; maybe there should be a
-;; prng-registry or something?
-(defmethod make-prng ((name (eql 'fortuna)) &key seed)
- (make-instance 'fortuna-prng))
-
(defgeneric random-data (pseudo-random-number-generator num-bytes)
(:documentation "Generate NUM-BYTES bytes using
PSEUDO-RANDOM-NUMBER-GENERATOR"))
@@ -52,15 +44,24 @@
(defun strong-random (pseudo-random-number-generator limit)
"Return a strong random number from 0 to limit-1 inclusive. A drop-in
replacement for COMMON-LISP:RANDOM."
- (let* ((log-limit (log limit 2))
- (num-bytes (ceiling log-limit 8))
- (mask (1- (expt 2 (ceiling log-limit)))))
- (loop for random = (logand (ironclad:octets-to-integer
- (random-data pseudo-random-number-generator
- num-bytes))
- mask)
- until (< random limit)
- finally (return random))))
+ (assert (plusp limit))
+ (etypecase limit
+ (integer
+ (let* ((log-limit (log limit 2))
+ (num-bytes (ceiling log-limit 8))
+ (mask (1- (expt 2 (ceiling log-limit)))))
+ (loop for random = (logand (ironclad:octets-to-integer
+ (random-data pseudo-random-number-generator
+ num-bytes))
+ mask)
+ until (< random limit)
+ finally (return random))))
+ (float
+ (float (let ((floor (floor 1 long-float-epsilon)))
+ (* limit
+ (/ (strong-random pseudo-random-number-generator floor)
+ floor)))))))
+
(defun os-random-seed (source num-bytes)
#+unix(let ((path (cond

0 comments on commit 9c094f3

Please sign in to comment.