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

Commits:

1 changed file:

Changes:

  • src/code/rand-xoroshiro.lisp
    ... ... @@ -18,7 +18,7 @@
    18 18
     	  make-xoro-random-state))
    
    19 19
     
    
    20 20
     (in-package "KERNEL")
    
    21
    -(export '(%xorohiro-single-float %xorohiro-double-float xoroshiro-chunk init-xoro-state))
    
    21
    +(export '(%xoroshiro-single-float %xoroshiro-double-float xoroshiro-chunk init-xoro-state))
    
    22 22
     
    
    23 23
     (sys:register-lisp-feature :random-xoroshiro)
    
    24 24
     
    
    ... ... @@ -95,7 +95,8 @@
    95 95
       ;; generate a new 64-bit result.
    
    96 96
       (cached-p nil :type (member t nil)))
    
    97 97
     
    
    98
    -(defvar *xoro-random-state*)
    
    98
    +(defvar *xoro-random-state*
    
    99
    +  (make-xoroshiro-object))
    
    99 100
     
    
    100 101
     (defun make-xoro-random-state (&optional state)
    
    101 102
       (flet ((copy-random-state (state)
    
    ... ... @@ -120,16 +121,23 @@
    120 121
     
    
    121 122
     ;;;; Random entries:
    
    122 123
     
    
    124
    +(declaim (ext:start-block xoroshiro-gen xoroshiro-chunk
    
    125
    +			  %xoroshiro-single-float %xoroshiro-double-float
    
    126
    +			  %xoroshiro-integer
    
    127
    +			  #+double-double
    
    128
    +			  %xoroshiro-double-double-float))
    
    129
    +;;#+x86
    
    130
    +;;(declaim (inline xoroshiro-next))
    
    123 131
     #+x86
    
    124
    -(declaim (inline xoroshiro-next))
    
    125
    -#+x86
    
    126
    -(defun xoroshiro-next (state)
    
    127
    -  (declare (type (simple-array double-float (2)) state))
    
    132
    +(defun xoroshiro-gen (state)
    
    133
    +  (declare (type (simple-array double-float (2)) state)
    
    134
    +	   (optimize (speed 3) (safety 0)))
    
    128 135
       (vm::xoroshiro-next state))
    
    129 136
     
    
    130 137
     #-x86
    
    131
    -(defun xoroshiro-next (state)
    
    132
    -  (declare (type (simple-array double-float (2)) state))
    
    138
    +(defun xoroshiro-gen (state)
    
    139
    +  (declare (type (simple-array double-float (2)) state)
    
    140
    +	   (optimize (speed 3) (safety 0)))
    
    133 141
       (flet ((rotl-55 (x1 x0)
    
    134 142
     	   (declare (type (unsigned-byte 32) x0 x1)
    
    135 143
     		    (optimize (speed 3) (safety 0)))
    
    ... ... @@ -228,7 +236,7 @@
    228 236
     	   (let ((s (xoro-random-state-state rng-state)))
    
    229 237
     	     (declare (type (simple-array double-float (2)) s))
    
    230 238
     	     (multiple-value-bind (r1 r0)
    
    231
    -		 (xoroshiro-next s)
    
    239
    +		 (xoroshiro-gen s)
    
    232 240
     	       (setf (xoro-random-state-rand rng-state) r0)
    
    233 241
     	       (setf (xoro-random-state-cached-p rng-state) t)
    
    234 242
     	       r1))))))
    
    ... ... @@ -240,14 +248,14 @@
    240 248
     ;;; between 0.0 and 1.0 by clobbering the significand of 1.0 with random bits,
    
    241 249
     ;;; then subtracting 1.0.  This hides the fact that we have a hidden bit.
    
    242 250
     ;;;
    
    243
    -(declaim (inline %xorohiro-single-float %xorohiro-double-float))
    
    244
    -(declaim (ftype (function ((single-float (0f0)) random-state)
    
    251
    +(declaim (inline %xoroshiro-single-float %xoroshiro-double-float))
    
    252
    +(declaim (ftype (function ((single-float (0f0)) xoro-random-state)
    
    245 253
     			  (single-float 0f0))
    
    246
    -		%xorohiro-single-float))
    
    254
    +		%xoroshiro-single-float))
    
    247 255
     ;;;
    
    248
    -(defun %xorohiro-single-float (arg state)
    
    256
    +(defun %xoroshiro-single-float (arg state)
    
    249 257
       (declare (type (single-float (0f0)) arg)
    
    250
    -	   (type random-state state))
    
    258
    +	   (type xoro-random-state state))
    
    251 259
       (* arg
    
    252 260
          (- (make-single-float
    
    253 261
     	 (dpb (ash (xoroshiro-chunk state)
    
    ... ... @@ -256,15 +264,15 @@
    256 264
     	      (single-float-bits 1.0)))
    
    257 265
     	1.0)))
    
    258 266
     ;;;
    
    259
    -(declaim (ftype (function ((double-float (0d0)) random-state)
    
    267
    +(declaim (ftype (function ((double-float (0d0)) xoro-random-state)
    
    260 268
     			  (double-float 0d0))
    
    261
    -		%xorohiro-double-float))
    
    269
    +		%xoroshiro-double-float))
    
    262 270
     ;;;
    
    263 271
     ;;; 53bit version.
    
    264 272
     ;;;
    
    265
    -(defun %xorohiro-double-float (arg state)
    
    273
    +(defun %xoroshiro-double-float (arg state)
    
    266 274
       (declare (type (double-float (0d0)) arg)
    
    267
    -	   (type random-state state))
    
    275
    +	   (type xoro-random-state state))
    
    268 276
       (* arg
    
    269 277
          (- (lisp::make-double-float
    
    270 278
     	 (dpb (ash (xoroshiro-chunk state)
    
    ... ... @@ -311,11 +319,12 @@
    311 319
     
    
    312 320
     ;;; %RANDOM-INTEGER  --  Internal
    
    313 321
     ;;;
    
    314
    -(defun %xorohiro-integer (arg state)
    
    315
    -  (declare (type (integer 1) arg) (type random-state state))
    
    322
    +(defun %xoroshiro-integer (arg state)
    
    323
    +  (declare (type (integer 1) arg)
    
    324
    +	   (type xoro-random-state state))
    
    316 325
       (let ((shift (- random-chunk-length random-integer-overlap)))
    
    317
    -    (do ((bits (random-chunk state)
    
    318
    -	       (logxor (ash bits shift) (random-chunk state)))
    
    326
    +    (do ((bits (xoroshiro-chunk state)
    
    327
    +	       (logxor (ash bits shift) (xoroshiro-chunk state)))
    
    319 328
     	 (count (+ (integer-length arg)
    
    320 329
     		   (- random-integer-extra-bits shift))
    
    321 330
     		(- count shift)))
    
    ... ... @@ -323,30 +332,75 @@
    323 332
     	 (rem bits arg))
    
    324 333
           (declare (fixnum count)))))
    
    325 334
     
    
    326
    -(defun xoro-random (arg &optional (state *random-state*))
    
    335
    +(declaim (ext:end-block))
    
    336
    +
    
    337
    +(defun xoro-random (arg &optional (state *xoro-random-state*))
    
    327 338
       "Generate a uniformly distributed pseudo-random number between zero
    
    328 339
       and Arg.  State, if supplied, is the random state to use."
    
    329
    -  (declare (inline %xorohiro-single-float %xorohiro-double-float
    
    340
    +  (declare (inline %xoroshiro-single-float %xoroshiro-double-float
    
    330 341
     		   #+long-float %long-float))
    
    331 342
       (cond
    
    332 343
         ((typep arg '(integer 1 #x100000000))
    
    333 344
          ;; Let the compiler deftransform take care of this case.
    
    334
    -     (random arg state))
    
    345
    +     (%xoroshiro-integer arg state))
    
    335 346
         ((and (typep arg 'single-float) (> arg 0.0F0))
    
    336
    -     (%xorohiro-single-float arg state))
    
    347
    +     (%xoroshiro-single-float arg state))
    
    337 348
         ((and (typep arg 'double-float) (> arg 0.0D0))
    
    338
    -     (%xorohiro-double-float arg state))
    
    349
    +     (%xoroshiro-double-float arg state))
    
    339 350
         #+long-float
    
    340 351
         ((and (typep arg 'long-float) (> arg 0.0L0))
    
    341
    -     (%xorohiro-long-float arg state))
    
    352
    +     (%xoroshiro-long-float arg state))
    
    342 353
         #+double-double
    
    343 354
         ((and (typep arg 'double-double-float) (> arg 0.0w0))
    
    344
    -     (%xorohiro-double-double-float arg state))
    
    355
    +     (%xoroshiro-double-double-float arg state))
    
    345 356
         ((and (integerp arg) (> arg 0))
    
    346
    -     (%xorohiro-integer arg state))
    
    357
    +     (%xoroshiro-integer arg state))
    
    347 358
         (t
    
    348 359
          (error 'simple-type-error
    
    349 360
     	    :expected-type '(or (integer 1) (float (0.0))) :datum arg
    
    350 361
     	    :format-control (intl:gettext "Argument is not a positive integer or a positive float: ~S")
    
    351 362
     	    :format-arguments (list arg)))))
    
    352 363
     
    
    364
    +(defun xoroshiro-jump (rng-state)
    
    365
    +  (declare (type xoro-random-state rng-state))
    
    366
    +  (let ((state (xoro-random-state-state rng-state))
    
    367
    +	(s0-0 0)
    
    368
    +	(s0-1 0)
    
    369
    +	(s1-0 0)
    
    370
    +	(s1-1 0))
    
    371
    +    (declare (type (unsigned-byte 32) s0-0 s0-1 s1-0 s1-1)
    
    372
    +	     (optimize (speed 3) (safety 0)))
    
    373
    +    (dolist (jump '(#xbeac0467eba5facb #xd86b048b86aa9922))
    
    374
    +      (declare (type (unsigned-byte 64) jump))
    
    375
    +      (dotimes (b 64)
    
    376
    +	(declare (fixnum b))
    
    377
    +	(when (logbitp b jump)
    
    378
    +	  (multiple-value-bind (x1 x0)
    
    379
    +	      (kernel:double-float-bits (aref state 0))
    
    380
    +	    (setf s0-1 (logxor s0-1 (ldb (byte 32 0) x1))
    
    381
    +		  s0-0 (logxor s0-0 x0)))
    
    382
    +	  
    
    383
    +	  (multiple-value-bind (x1 x0)
    
    384
    +	      (kernel:double-float-bits (aref state 1))
    
    385
    +	    (setf s1-1 (logxor s1-1 (ldb (byte 32 0) x1))
    
    386
    +		  s1-0 (logxor s1-0 x0))))
    
    387
    +	(format t "jump: ~D s0, s1 = ~X~8,'0X  ~X~8,'0X~%" b s0-1 s0-0 s1-1 s1-0)
    
    388
    +	(xoroshiro-next state)))
    
    389
    +
    
    390
    +    (flet ((convert (x1 x0)
    
    391
    +	     (declare (type (unsigned-byte 32) x1 x0))
    
    392
    +	     (kernel:make-double-float
    
    393
    +	      (if (< x1 #x80000000) x1 (- x1 #x100000000))
    
    394
    +	      x0)))
    
    395
    +      (setf (aref state 0) (convert s0-1 s0-0))
    
    396
    +      (setf (aref state 1) (convert s1-1 s1-0)))
    
    397
    +      rng-state))
    
    398
    +
    
    399
    +(defun print-xoro-state (rng-state)
    
    400
    +  (let ((state (xoro-random-state-state rng-state)))
    
    401
    +    (flet ((v (x)
    
    402
    +	     (multiple-value-bind (hi lo)
    
    403
    +		 (kernel:double-float-bits x)
    
    404
    +	       (logior (ash (ldb (byte 32 0) hi) 32)
    
    405
    +		       lo))))
    
    406
    +      (format t "~16,'0x ~16,'0x" (v (aref state 0)) (v (aref state 1))))))
    \ No newline at end of file