Raymond Toy pushed to branch rtoy-xoro at cmucl / cmucl

Commits:

1 changed file:

Changes:

  • src/code/rand-xoroshiro.lisp
    ... ... @@ -22,6 +22,28 @@
    22 22
     
    
    23 23
     (sys:register-lisp-feature :random-xoroshiro)
    
    24 24
     
    
    25
    +(defun generate-seed (&optional (nwords 1))
    
    26
    +  ;; On some systems (as reported by Ole Rohne on cmucl-imp),
    
    27
    +  ;; /dev/urandom isn't what we think it is, so if it doesn't work,
    
    28
    +  ;; silently generate the seed from the current time.
    
    29
    +  (or (ignore-errors
    
    30
    +	(let ((words (make-array nwords :element-type '(unsigned-byte 32))))
    
    31
    +	  (with-open-file (rand "/dev/urandom"
    
    32
    +				:direction :input
    
    33
    +				:element-type '(unsigned-byte 32))
    
    34
    +	    (read-sequence words rand))
    
    35
    +	  (if (= nwords 1)
    
    36
    +	      (aref words 0)
    
    37
    +	      (let ((vec (make-array (floor nwords 2) :element-type '(unsigned-byte 64))))
    
    38
    +		(do ((k 0 (+ k 1))
    
    39
    +		     (j 0 (+ j 2)))
    
    40
    +		    ((>= k (length vec))
    
    41
    +		     vec)
    
    42
    +		  (setf (aref vec k)
    
    43
    +			(logior (ash (aref words j) 32)
    
    44
    +				(aref words (+ j 1)))))))))
    
    45
    +      (logand (get-universal-time) #xffffffff)))
    
    46
    +
    
    25 47
     (defun int-init-xoro-state (&optional (seed 5772156649015328606) state)
    
    26 48
       (let ((state (or state (make-array 2 :element-type 'double-float)))
    
    27 49
     	(splitmix-state (ldb (byte 64 0) seed)))
    
    ... ... @@ -51,16 +73,18 @@
    51 73
     	   state))))
    
    52 74
     
    
    53 75
     (defun vec-init-xoro-state (key &optional state)
    
    54
    -  (declare (type (array (unsigned-byte 32) (4)) key)
    
    76
    +  (declare (type (array (unsigned-byte 64) (2)) key)
    
    55 77
     	   (type (simple-array double-float (2)) state))
    
    56
    -  (flet ((make-double (hi lo)
    
    57
    -	   (kernel:make-double-float
    
    58
    -		(if (< hi #x80000000)
    
    59
    -		    hi
    
    60
    -		    (- hi #x100000000))
    
    61
    -		lo)))
    
    62
    -    (setf (aref state 0) (make-double (aref key 0) (aref key 1))
    
    63
    -	  (aref state 1) (make-double (aref key 2) (aref key 3)))
    
    78
    +  (flet ((make-double (x)
    
    79
    +	   (let ((hi (ldb (byte 32 32) x))
    
    80
    +		 (lo (ldb (byte 32 0) x)))
    
    81
    +	     (kernel:make-double-float
    
    82
    +	      (if (< hi #x80000000)
    
    83
    +		  hi
    
    84
    +		  (- hi #x100000000))
    
    85
    +	      lo))))
    
    86
    +    (setf (aref state 0) (make-double (aref key 0))
    
    87
    +	  (aref state 1) (make-double (aref key 1)))
    
    64 88
         state))
    
    65 89
       
    
    66 90
       
    
    ... ... @@ -68,13 +92,13 @@
    68 92
       "Generate an random state vector from the given SEED.  The seed can be
    
    69 93
       either an integer or a vector of (unsigned-byte 32)"
    
    70 94
       (declare (type (or null integer
    
    71
    -		     (array (unsigned-byte 32) (*)))
    
    95
    +		     (array (unsigned-byte 64) (*)))
    
    72 96
     		 seed))
    
    73 97
       (let ((state (or state (make-array 2 :element-type 'double-float))))
    
    74 98
         (etypecase seed
    
    75 99
           (integer
    
    76 100
            (int-init-xoro-state (ldb (byte 64 0) seed) state))
    
    77
    -      ((array (unsigned-byte 32) (4))
    
    101
    +      ((array (unsigned-byte 64) (2))
    
    78 102
            (vec-init-xoro-state seed state)))))
    
    79 103
     
    
    80 104
     (defstruct (xoro-random-state
    
    ... ... @@ -113,14 +137,15 @@
    113 137
           (pprint-logical-block (stream nil :prefix "#.(" :suffix ")")
    
    114 138
     	(prin1 'init-xoro-state stream)
    
    115 139
     	(write-char #\space stream)
    
    116
    -	(prin1 (make-array 4 :element-type '(unsigned-byte 32)
    
    117
    -			 :initial-contents (list (ldb (byte 32 0)
    
    118
    -						      (double-float-high-bits (aref state 0)))
    
    119
    -						 (double-float-low-bits (aref state 0))
    
    120
    -						 (ldb (byte 32 0)
    
    121
    -						      (double-float-high-bits (aref state 1)))
    
    122
    -						 (double-float-low-bits (aref state 1))))
    
    123
    -	       stream))
    
    140
    +	(flet ((c (x)
    
    141
    +		 (multiple-value-bind (hi lo)
    
    142
    +		     (double-float-bits x)
    
    143
    +		   (logior (ash (ldb (byte 32 0) hi) 32)
    
    144
    +			   lo))))
    
    145
    +	  (prin1 (make-array 2 :element-type '(unsigned-byte 64)
    
    146
    +			     :initial-contents (list (c (aref state 0))
    
    147
    +						     (c (aref state 1))))
    
    148
    +		 stream)))
    
    124 149
           (write-char #\space stream)
    
    125 150
           (pprint-newline :linear stream)
    
    126 151