... |
... |
@@ -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 |