0.9.16.6: better circularity detection in fasl dumper
[sbcl.git] / src / code / target-random.lisp
index 46b33d7..f0b740f 100644 (file)
 \f
 ;;;; RANDOM-STATEs
 
-(def!method make-load-form ((random-state random-state) &optional environment) 
+(def!method make-load-form ((random-state random-state) &optional environment)
   (make-load-form-saving-slots random-state :environment environment))
 
+(def!method print-object ((state random-state) stream)
+  (if (and *print-readably* (not *read-eval*))
+      (error 'print-not-readable :object state)
+      (format stream "#S(~S ~S #.~S)"
+              'random-state
+              ':state
+              `(make-array 627
+                :element-type
+                '(unsigned-byte 32)
+                :initial-contents
+                ',(coerce (random-state-state state) 'list)))))
+
 ;;; The state is stored in a (simple-array (unsigned-byte 32) (627))
 ;;; wrapped in a random-state structure:
 ;;;
     (setf (aref state 2) 1)
     (setf (aref state 3) seed)
     (do ((k 1 (1+ k)))
-       ((>= k 624))
+        ((>= k 624))
       (declare (type (mod 625) k))
       (setf (aref state (+ 3 k))
-           (logand (* 69069 (aref state (+ 3 (1- k)))) #xffffffff)))
+            (logand (* 69069 (aref state (+ 3 (1- k)))) #xffffffff)))
     state))
 
 (defvar *random-state*)
   of the default random state. If STATE is a random state, then return a
   copy of it. If STATE is T then return a random state generated from
   the universal time."
+  (/show0 "entering MAKE-RANDOM-STATE")
   (flet ((copy-random-state (state)
-          (let ((state (random-state-state state))
-                (new-state
-                 (make-array 627 :element-type '(unsigned-byte 32))))
-            (dotimes (i 627)
-              (setf (aref new-state i) (aref state i)))
-            (%make-random-state :state new-state))))
-    (cond ((not state) (copy-random-state *random-state*))
-         ((random-state-p state) (copy-random-state state))
-         ((eq state t)
-          (%make-random-state :state (init-random-state
-                                      (logand (get-universal-time)
-                                              #xffffffff))))
-         ;; FIXME: should be TYPE-ERROR?
-         (t (error "Argument is not a RANDOM-STATE, T or NIL: ~S" state)))))
+           (/show0 "entering COPY-RANDOM-STATE")
+           (let ((state (random-state-state state))
+                 (new-state
+                  (make-array 627 :element-type '(unsigned-byte 32))))
+             (/show0 "made NEW-STATE, about to DOTIMES")
+             (dotimes (i 627)
+               (setf (aref new-state i) (aref state i)))
+             (/show0 "falling through to %MAKE-RANDOM-STATE")
+             (%make-random-state :state new-state))))
+    (/show0 "at head of ETYPECASE in MAKE-RANDOM-STATE")
+    (etypecase state
+      (null
+       (/show0 "NULL case")
+       (copy-random-state *random-state*))
+      (random-state
+       (/show0 "RANDOM-STATE-P clause")
+       (copy-random-state state))
+      ((member t)
+       (/show0 "T clause")
+       (%make-random-state :state (init-random-state
+                                   (logand (get-universal-time)
+                                           #xffffffff)))))))
 \f
 ;;;; random entries
 
 #!-x86
 (defun random-mt19937-update (state)
   (declare (type (simple-array (unsigned-byte 32) (627)) state)
-          (optimize (speed 3) (safety 0)))
+           (optimize (speed 3) (safety 0)))
   (let ((y 0))
     (declare (type (unsigned-byte 32) y))
     (do ((kk 3 (1+ kk)))
-       ((>= kk (+ 3 (- mt19937-n mt19937-m))))
+        ((>= kk (+ 3 (- mt19937-n mt19937-m))))
       (declare (type (mod 628) kk))
       (setf y (logior (logand (aref state kk) mt19937-upper-mask)
-                     (logand (aref state (1+ kk)) mt19937-lower-mask)))
+                      (logand (aref state (1+ kk)) mt19937-lower-mask)))
       (setf (aref state kk) (logxor (aref state (+ kk mt19937-m))
-                                   (ash y -1) (aref state (logand y 1)))))
+                                    (ash y -1) (aref state (logand y 1)))))
     (do ((kk (+ (- mt19937-n mt19937-m) 3) (1+ kk)))
-       ((>= kk (+ (1- mt19937-n) 3)))
+        ((>= kk (+ (1- mt19937-n) 3)))
       (declare (type (mod 628) kk))
       (setf y (logior (logand (aref state kk) mt19937-upper-mask)
-                     (logand (aref state (1+ kk)) mt19937-lower-mask)))
+                      (logand (aref state (1+ kk)) mt19937-lower-mask)))
       (setf (aref state kk) (logxor (aref state (+ kk (- mt19937-m mt19937-n)))
-                                   (ash y -1) (aref state (logand y 1)))))
+                                    (ash y -1) (aref state (logand y 1)))))
     (setf y (logior (logand (aref state (+ 3 (1- mt19937-n)))
-                           mt19937-upper-mask)
-                   (logand (aref state 3) mt19937-lower-mask)))
+                            mt19937-upper-mask)
+                    (logand (aref state 3) mt19937-lower-mask)))
     (setf (aref state (+ 3 (1- mt19937-n)))
-         (logxor (aref state (+ 3 (1- mt19937-m)))
-                 (ash y -1) (aref state (logand y 1)))))
+          (logxor (aref state (+ 3 (1- mt19937-m)))
+                  (ash y -1) (aref state (logand y 1)))))
   (values))
 #!-x86
 (defun random-chunk (state)
   (declare (type random-state state))
   (let* ((state (random-state-state state))
-        (k (aref state 2)))
+         (k (aref state 2)))
     (declare (type (mod 628) k))
     (when (= k mt19937-n)
       (random-mt19937-update state)
 (defun random-chunk (state)
   (declare (type random-state state))
   (sb!vm::random-mt19937 (random-state-state state)))
+
+#!-sb-fluid (declaim (inline big-random-chunk))
+(defun big-random-chunk (state)
+  (declare (type random-state state))
+  (logand (1- (expt 2 64))
+          (logior (ash (random-chunk state) 32)
+                  (random-chunk state))))
 \f
 ;;; Handle the single or double float case of RANDOM. We generate a
 ;;; float between 0.0 and 1.0 by clobbering the significand of 1.0
 ;;; we have a hidden bit.
 #!-sb-fluid (declaim (inline %random-single-float %random-double-float))
 (declaim (ftype (function ((single-float (0f0)) random-state)
-                         (single-float 0f0))
-               %random-single-float))
+                          (single-float 0f0))
+                %random-single-float))
 (defun %random-single-float (arg state)
   (declare (type (single-float (0f0)) arg)
-          (type random-state state))
+           (type random-state state))
   (* arg
      (- (make-single-float
-        (dpb (ash (random-chunk state)
-                  (- sb!vm:single-float-digits random-chunk-length))
-             sb!vm:single-float-significand-byte
-             (single-float-bits 1.0)))
-       1.0)))
+         (dpb (ash (random-chunk state)
+                   (- sb!vm:single-float-digits random-chunk-length))
+              sb!vm:single-float-significand-byte
+              (single-float-bits 1.0)))
+        1.0)))
 (declaim (ftype (function ((double-float (0d0)) random-state)
-                         (double-float 0d0))
-               %random-double-float))
+                          (double-float 0d0))
+                %random-double-float))
 
 ;;; 32-bit version
 #!+nil
 (defun %random-double-float (arg state)
   (declare (type (double-float (0d0)) arg)
-          (type random-state state))
+           (type random-state state))
   (* (float (random-chunk state) 1d0) (/ 1d0 (expt 2 32))))
 
 ;;; 53-bit version
 #!-x86
 (defun %random-double-float (arg state)
   (declare (type (double-float (0d0)) arg)
-          (type random-state state))
+           (type random-state state))
   (* arg
      (- (sb!impl::make-double-float
-        (dpb (ash (random-chunk state)
-                  (- sb!vm:double-float-digits random-chunk-length
-                     sb!vm:word-bits))
-             sb!vm:double-float-significand-byte
-             (sb!impl::double-float-high-bits 1d0))
-        (random-chunk state))
-       1d0)))
+         (dpb (ash (random-chunk state)
+                   (- sb!vm:double-float-digits random-chunk-length 32))
+              sb!vm:double-float-significand-byte
+              (sb!impl::double-float-high-bits 1d0))
+         (random-chunk state))
+        1d0)))
 
 ;;; using a faster inline VOP
 #!+x86
 (defun %random-double-float (arg state)
   (declare (type (double-float (0d0)) arg)
-          (type random-state state))
+           (type random-state state))
   (let ((state-vector (random-state-state state)))
     (* arg
        (- (sb!impl::make-double-float
-          (dpb (ash (sb!vm::random-mt19937 state-vector)
-                    (- sb!vm:double-float-digits random-chunk-length
-                       sb!vm:word-bits))
-               sb!vm:double-float-significand-byte
-               (sb!impl::double-float-high-bits 1d0))
-          (sb!vm::random-mt19937 state-vector))
-         1d0))))
+           (dpb (ash (sb!vm::random-mt19937 state-vector)
+                     (- sb!vm:double-float-digits random-chunk-length
+                        sb!vm:n-word-bits))
+                sb!vm:double-float-significand-byte
+                (sb!impl::double-float-high-bits 1d0))
+           (sb!vm::random-mt19937 state-vector))
+          1d0))))
 
-#!+long-float
-(declaim #!-sb-fluid (inline %random-long-float))
-#!+long-float
-(declaim (ftype (function ((long-float (0l0)) random-state) (long-float 0l0))
-               %random-long-float))
-
-;;; using a faster inline VOP
-#!+(and long-float x86)
-(defun %random-long-float (arg state)
-  (declare (type (long-float (0l0)) arg)
-          (type random-state state))
-  (let ((state-vector (random-state-state state)))
-    (* arg
-       (- (sb!impl::make-long-float
-          (sb!impl::long-float-exp-bits 1l0)
-          (logior (sb!vm::random-mt19937 state-vector)
-                  sb!vm:long-float-hidden-bit)
-          (sb!vm::random-mt19937 state-vector))
-         1l0))))
-
-#!+(and long-float sparc)
-(defun %random-long-float (arg state)
-  (declare (type (long-float (0l0)) arg)
-          (type random-state state))
-  (* arg
-     (- (sb!impl::make-long-float
-        (sb!impl::long-float-exp-bits 1l0)     ; X needs more work
-        (random-chunk state) (random-chunk state) (random-chunk state))
-       1l0)))
 \f
 ;;;; random integers
 
   (declare (type (integer 1) arg) (type random-state state))
   (let ((shift (- random-chunk-length random-integer-overlap)))
     (do ((bits (random-chunk state)
-              (logxor (ash bits shift) (random-chunk state)))
-        (count (+ (integer-length arg)
-                  (- random-integer-extra-bits shift))
-               (- count shift)))
-       ((minusp count)
-        (rem bits arg))
+               (logxor (ash bits shift) (random-chunk state)))
+         (count (+ (integer-length arg)
+                   (- random-integer-extra-bits shift))
+                (- count shift)))
+        ((minusp count)
+         (rem bits arg))
       (declare (fixnum count)))))
 
 (defun random (arg &optional (state *random-state*))
   (declare (inline %random-single-float %random-double-float
-                  #!+long-float %long-float))
+                   #!+long-float %random-long-float))
   (cond
     ((and (fixnump arg) (<= arg random-fixnum-max) (> arg 0))
      (rem (random-chunk state) arg))
-    ((and (typep arg 'single-float) (> arg 0.0S0))
+    ((and (typep arg 'single-float) (> arg 0.0f0))
      (%random-single-float arg state))
-    ((and (typep arg 'double-float) (> arg 0.0D0))
+    ((and (typep arg 'double-float) (> arg 0.0d0))
      (%random-double-float arg state))
     #!+long-float
-    ((and (typep arg 'long-float) (> arg 0.0L0))
+    ((and (typep arg 'long-float) (> arg 0.0l0))
      (%random-long-float arg state))
     ((and (integerp arg) (> arg 0))
      (%random-integer arg state))
     (t
      (error 'simple-type-error
-           :expected-type '(or (integer 1) (float (0))) :datum arg
-           :format-control "~@<Argument is neither a positive integer nor a ~
+            :expected-type '(or (integer 1) (float (0))) :datum arg
+            :format-control "~@<Argument is neither a positive integer nor a ~
                              positive float: ~2I~_~S~:>"
-           :format-arguments (list arg)))))
+            :format-arguments (list arg)))))