| ... |
... |
@@ -412,15 +412,41 @@ |
|
412
|
412
|
(inst pop k)
|
|
413
|
413
|
(inst ret))
|
|
414
|
414
|
|
|
415
|
|
-
|
|
416
|
|
-#+(and random-xoroshiro assembler)
|
|
|
415
|
+;;; Support for the xoroshiro128** generator. See
|
|
|
416
|
+;;; https://prng.di.unimi.it/xoroshiro128starstar.c for the official
|
|
|
417
|
+;;; code.
|
|
|
418
|
+;;;
|
|
|
419
|
+;;; This is what we're implementing, where s[] is our state vector.
|
|
|
420
|
+;;;
|
|
|
421
|
+;;; static uint64_t s[2];
|
|
|
422
|
+;;; static inline uint64_t rotl(const uint64_t x, int k) {
|
|
|
423
|
+;;; return (x << k) | (x >> (64 - k));
|
|
|
424
|
+;;; }
|
|
|
425
|
+;;;
|
|
|
426
|
+;;; uint64_t next(void) {
|
|
|
427
|
+;;; const uint64_t s0 = s[0];
|
|
|
428
|
+;;; uint64_t s1 = s[1];
|
|
|
429
|
+;;; const uint64_t result = rotl(s0 * 5, 7) * 9;
|
|
|
430
|
+;;;
|
|
|
431
|
+;;; s1 ^= s0;
|
|
|
432
|
+;;; s[0] = rotl(s0, 24) ^ s1 ^ (s1 << 16); // a, b
|
|
|
433
|
+;;; s[1] = rotl(s1, 37); // c
|
|
|
434
|
+;;;
|
|
|
435
|
+;;; return result;
|
|
|
436
|
+;;; }
|
|
|
437
|
+;;;
|
|
|
438
|
+;;; A VOP is also generated to call this assembly routine. This
|
|
|
439
|
+;;; routine computes a new 64-bit random number and also updates the
|
|
|
440
|
+;;; state, which is (simple-array (double-float) (2)).
|
|
|
441
|
+#+random-xoroshiro
|
|
417
|
442
|
(define-assembly-routine
|
|
418
|
443
|
(xoroshiro-update
|
|
419
|
|
- (:translate kernel::xoroshiro-update)
|
|
|
444
|
+ (:translate kernel::random-xoroshiro-update)
|
|
420
|
445
|
(:return-style :raw)
|
|
421
|
446
|
(:cost 30)
|
|
422
|
|
- (:policy :safe)
|
|
423
|
|
- (:save-p t))
|
|
|
447
|
+ (:policy :fast-safe)
|
|
|
448
|
+ (:arg-types simple-array-double-float)
|
|
|
449
|
+ (:result-types unsigned-num unsigned-num))
|
|
424
|
450
|
((:arg state descriptor-reg eax-offset)
|
|
425
|
451
|
(:res r1 unsigned-reg edx-offset)
|
|
426
|
452
|
(:res r0 unsigned-reg ebx-offset)
|
| ... |
... |
@@ -428,26 +454,6 @@ |
|
428
|
454
|
(:temp s1 double-reg xmm1-offset)
|
|
429
|
455
|
(:temp t0 double-reg xmm2-offset)
|
|
430
|
456
|
(:temp t1 double-reg xmm3-offset))
|
|
431
|
|
- ;; See https://prng.di.unimi.it/xoroshiro128starstar.c for the official code.
|
|
432
|
|
- ;;
|
|
433
|
|
- ;; This is what we're implementing, where s[] is our state vector.
|
|
434
|
|
- ;;
|
|
435
|
|
- ;; static uint64_t s[2];
|
|
436
|
|
- ;; static inline uint64_t rotl(const uint64_t x, int k) {
|
|
437
|
|
- ;; return (x << k) | (x >> (64 - k));
|
|
438
|
|
- ;; }
|
|
439
|
|
- ;;
|
|
440
|
|
- ;; uint64_t next(void) {
|
|
441
|
|
- ;; const uint64_t s0 = s[0];
|
|
442
|
|
- ;; uint64_t s1 = s[1];
|
|
443
|
|
- ;; const uint64_t result = rotl(s0 * 5, 7) * 9;
|
|
444
|
|
- ;;
|
|
445
|
|
- ;; s1 ^= s0;
|
|
446
|
|
- ;; s[0] = rotl(s0, 24) ^ s1 ^ (s1 << 16); // a, b
|
|
447
|
|
- ;; s[1] = rotl(s1, 37); // c
|
|
448
|
|
- ;;
|
|
449
|
|
- ;; return result;
|
|
450
|
|
- ;; }
|
|
451
|
457
|
|
|
452
|
458
|
;; s0 = state[0]
|
|
453
|
459
|
(inst movsd s0 (make-ea :dword :base state
|
| ... |
... |
@@ -522,5 +528,4 @@ |
|
522
|
528
|
vm:word-bytes)
|
|
523
|
529
|
(* 8 1))
|
|
524
|
530
|
vm:other-pointer-type))
|
|
525
|
|
- s1)
|
|
526
|
|
- (inst ret)) |
|
|
531
|
+ s1)) |