Raymond Toy pushed to branch issue-276-xoroshiro128starstar at cmucl / cmucl
Commits:
-
52a08e62
by Raymond Toy at 2024-02-13T18:52:07-08:00
-
1b1c57ad
by Raymond Toy at 2024-02-13T18:57:20-08:00
2 changed files:
Changes:
| ... | ... | @@ -48,28 +48,31 @@ |
| 48 | 48 | (assert-equal 0 (kernel::random-state-rand *test-state*))
|
| 49 | 49 | (assert-equal nil (kernel::random-state-cached-p *test-state*))
|
| 50 | 50 | |
| 51 | - (dolist (item #-x86
|
|
| 52 | - '((#x18d5f05c086e0086 (#x228f4926843b364d #x74dfe78e715c81be))
|
|
| 53 | - (#x976f30b4f597b80b (#x5b6bd4558bd96a68 #x567b7f35650aea8f))
|
|
| 54 | - (#xb1e7538af0e454f7 (#x13e5253e242fac52 #xed380e70d10ab60e))
|
|
| 55 | - (#x011d33aef53a6260 (#x9d0764952ca00d8a #x5251a5cfedd2b4ef))
|
|
| 56 | - (#xef590a651a72c279 (#xba4ef2b425bda963 #x172b965cf56c15ac))
|
|
| 57 | - (#xd17a89111b29bf0f (#x458277a5e5f0a21b #xd1bccfad6564e8d))
|
|
| 58 | - (#x529e44a0bc46f0a8 (#x2becb68d5a7194c7 #x3a6ec964899bb5f3))
|
|
| 59 | - (#x665b7ff1e40d4aba (#xededfd481d0a19fe #x3ea213411827fe9d))
|
|
| 60 | - (#x2c9010893532189b (#xd7bb59bcd8fba26f #x52de763d34fee090))
|
|
| 61 | - (#x2a99cffa0dfa82ff (#xf96e892c62d6ff2e #xc0542ff85652f81e)))
|
|
| 62 | - #+x86
|
|
| 63 | - '((#x41db14eb317141fe (#x16dfbf3d760d0fa4 #xe9bfcf1ce2b9037c))
|
|
| 64 | - (#xaa4ee6e025dfec01 (#xb237e99a3c7ad367 #x96819b1fec0e0432))
|
|
| 65 | - (#xea080e50cb948fa5 (#xcc0fd8226093e0bc #x0e9aeaa496ce50ba))
|
|
| 66 | - (#x647f057cff408a6e (#xd273573bfa97bfde #xcbb600d852a650de))
|
|
| 67 | - (#x232ac586565d037e (#x75dc686d99e39c57 #x063de00338aafc75))
|
|
| 68 | - (#xdf2da206813da6d6 (#x9616cabb961ebc4a #x292c044e7c310dd4))
|
|
| 69 | - (#x00d17cb1b38c852f (#xca593a661127a754 #x45f633d7e759debd))
|
|
| 70 | - (#xd7a1f881fc34e641 (#xe00fd868db5d20d3 #xcfcf3d31f5e1363e))
|
|
| 71 | - (#x64853747af628d30 (#xa24296c5ebb11935 #xd782dda5f81cab25))
|
|
| 72 | - (#xda40653710b7293d (#xfb4be9d4941ff086 #x75b6420eb8096c02))))
|
|
| 51 | + (dolist (item
|
|
| 52 | + ;; Results for xoroshiro128+
|
|
| 53 | + #-x86
|
|
| 54 | + '((#x18d5f05c086e0086 (#x228f4926843b364d #x74dfe78e715c81be))
|
|
| 55 | + (#x976f30b4f597b80b (#x5b6bd4558bd96a68 #x567b7f35650aea8f))
|
|
| 56 | + (#xb1e7538af0e454f7 (#x13e5253e242fac52 #xed380e70d10ab60e))
|
|
| 57 | + (#x011d33aef53a6260 (#x9d0764952ca00d8a #x5251a5cfedd2b4ef))
|
|
| 58 | + (#xef590a651a72c279 (#xba4ef2b425bda963 #x172b965cf56c15ac))
|
|
| 59 | + (#xd17a89111b29bf0f (#x458277a5e5f0a21b #xd1bccfad6564e8d))
|
|
| 60 | + (#x529e44a0bc46f0a8 (#x2becb68d5a7194c7 #x3a6ec964899bb5f3))
|
|
| 61 | + (#x665b7ff1e40d4aba (#xededfd481d0a19fe #x3ea213411827fe9d))
|
|
| 62 | + (#x2c9010893532189b (#xd7bb59bcd8fba26f #x52de763d34fee090))
|
|
| 63 | + (#x2a99cffa0dfa82ff (#xf96e892c62d6ff2e #xc0542ff85652f81e)))
|
|
| 64 | + ;; Results for xoroshiro128**
|
|
| 65 | + #+x86
|
|
| 66 | + '((#x41db14eb317141fe (#x16dfbf3d760d0fa4 #xe9bfcf1ce2b9037c))
|
|
| 67 | + (#xaa4ee6e025dfec01 (#xb237e99a3c7ad367 #x96819b1fec0e0432))
|
|
| 68 | + (#xea080e50cb948fa5 (#xcc0fd8226093e0bc #x0e9aeaa496ce50ba))
|
|
| 69 | + (#x647f057cff408a6e (#xd273573bfa97bfde #xcbb600d852a650de))
|
|
| 70 | + (#x232ac586565d037e (#x75dc686d99e39c57 #x063de00338aafc75))
|
|
| 71 | + (#xdf2da206813da6d6 (#x9616cabb961ebc4a #x292c044e7c310dd4))
|
|
| 72 | + (#x00d17cb1b38c852f (#xca593a661127a754 #x45f633d7e759debd))
|
|
| 73 | + (#xd7a1f881fc34e641 (#xe00fd868db5d20d3 #xcfcf3d31f5e1363e))
|
|
| 74 | + (#x64853747af628d30 (#xa24296c5ebb11935 #xd782dda5f81cab25))
|
|
| 75 | + (#xda40653710b7293d (#xfb4be9d4941ff086 #x75b6420eb8096c02))))
|
|
| 73 | 76 | (destructuring-bind (value state)
|
| 74 | 77 | item
|
| 75 | 78 | (assert-equal value (64-bit-value *test-state*))
|
| ... | ... | @@ -82,10 +85,12 @@ |
| 82 | 85 | :rand 0
|
| 83 | 86 | :cached-p nil))
|
| 84 | 87 | (dolist (result
|
| 88 | + ;; Results for xoroshiro128+ jump function
|
|
| 85 | 89 | #-x86 '((#x291ddf8e6f6a7b67 #x1f9018a12f9e031f)
|
| 86 | 90 | (#x88a7aa12158558d0 #xe264d785ab1472d9)
|
| 87 | 91 | (#x207e16f73c51e7ba #x999c8a0a9a8d87c0)
|
| 88 | 92 | (#x28f8959d3bcf5ff1 #x38091e563ab6eb98))
|
| 93 | + ;; Results for xoroshiro128** jump function
|
|
| 89 | 94 | #+x86 '((#x19a22191480b0a4e #x43b3d7ee592dd4cf)
|
| 90 | 95 | (#x76cb87035d0b6e99 #xb6827bcf2ef8267c)
|
| 91 | 96 | (#x5125201dbdf76860 #x8984c075043869e2)
|
| 1 | +/* Written in 2018 by David Blackman and Sebastiano Vigna (vigna@acm.org)
|
|
| 2 | + |
|
| 3 | +To the extent possible under law, the author has dedicated all copyright
|
|
| 4 | +and related and neighboring rights to this software to the public domain
|
|
| 5 | +worldwide. This software is distributed without any warranty.
|
|
| 6 | + |
|
| 7 | +See <http://creativecommons.org/publicdomain/zero/1.0/>. */
|
|
| 8 | + |
|
| 9 | +#include <stdint.h>
|
|
| 10 | + |
|
| 11 | +/* This is xoroshiro128** 1.0, one of our all-purpose, rock-solid,
|
|
| 12 | + small-state generators. It is extremely (sub-ns) fast and it passes all
|
|
| 13 | + tests we are aware of, but its state space is large enough only for
|
|
| 14 | + mild parallelism.
|
|
| 15 | + |
|
| 16 | + For generating just floating-point numbers, xoroshiro128+ is even
|
|
| 17 | + faster (but it has a very mild bias, see notes in the comments).
|
|
| 18 | + |
|
| 19 | + The state must be seeded so that it is not everywhere zero. If you have
|
|
| 20 | + a 64-bit seed, we suggest to seed a splitmix64 generator and use its
|
|
| 21 | + output to fill s. */
|
|
| 22 | + |
|
| 23 | + |
|
| 24 | +static inline uint64_t rotl(const uint64_t x, int k) {
|
|
| 25 | + return (x << k) | (x >> (64 - k));
|
|
| 26 | +}
|
|
| 27 | + |
|
| 28 | + |
|
| 29 | +static uint64_t s[2];
|
|
| 30 | + |
|
| 31 | +uint64_t next(void) {
|
|
| 32 | + const uint64_t s0 = s[0];
|
|
| 33 | + uint64_t s1 = s[1];
|
|
| 34 | + const uint64_t result = rotl(s0 * 5, 7) * 9;
|
|
| 35 | + |
|
| 36 | + s1 ^= s0;
|
|
| 37 | + s[0] = rotl(s0, 24) ^ s1 ^ (s1 << 16); // a, b
|
|
| 38 | + s[1] = rotl(s1, 37); // c
|
|
| 39 | + |
|
| 40 | + return result;
|
|
| 41 | +}
|
|
| 42 | + |
|
| 43 | + |
|
| 44 | +/* This is the jump function for the generator. It is equivalent
|
|
| 45 | + to 2^64 calls to next(); it can be used to generate 2^64
|
|
| 46 | + non-overlapping subsequences for parallel computations. */
|
|
| 47 | + |
|
| 48 | +void jump(void) {
|
|
| 49 | + static const uint64_t JUMP[] = { 0xdf900294d8f554a5, 0x170865df4b3201fc };
|
|
| 50 | + |
|
| 51 | + uint64_t s0 = 0;
|
|
| 52 | + uint64_t s1 = 0;
|
|
| 53 | + for(int i = 0; i < sizeof JUMP / sizeof *JUMP; i++)
|
|
| 54 | + for(int b = 0; b < 64; b++) {
|
|
| 55 | + if (JUMP[i] & UINT64_C(1) << b) {
|
|
| 56 | + s0 ^= s[0];
|
|
| 57 | + s1 ^= s[1];
|
|
| 58 | + }
|
|
| 59 | + next();
|
|
| 60 | + }
|
|
| 61 | + |
|
| 62 | + s[0] = s0;
|
|
| 63 | + s[1] = s1;
|
|
| 64 | +}
|
|
| 65 | + |
|
| 66 | + |
|
| 67 | +/* This is the long-jump function for the generator. It is equivalent to
|
|
| 68 | + 2^96 calls to next(); it can be used to generate 2^32 starting points,
|
|
| 69 | + from each of which jump() will generate 2^32 non-overlapping
|
|
| 70 | + subsequences for parallel distributed computations. */
|
|
| 71 | + |
|
| 72 | +void long_jump(void) {
|
|
| 73 | + static const uint64_t LONG_JUMP[] = { 0xd2a98b26625eee7b, 0xdddf9b1090aa7ac1 };
|
|
| 74 | + |
|
| 75 | + uint64_t s0 = 0;
|
|
| 76 | + uint64_t s1 = 0;
|
|
| 77 | + for(int i = 0; i < sizeof LONG_JUMP / sizeof *LONG_JUMP; i++)
|
|
| 78 | + for(int b = 0; b < 64; b++) {
|
|
| 79 | + if (LONG_JUMP[i] & UINT64_C(1) << b) {
|
|
| 80 | + s0 ^= s[0];
|
|
| 81 | + s1 ^= s[1];
|
|
| 82 | + }
|
|
| 83 | + next();
|
|
| 84 | + }
|
|
| 85 | + |
|
| 86 | + s[0] = s0;
|
|
| 87 | + s[1] = s1;
|
|
| 88 | +}
|
|
| 89 | + |
|
| 90 | +/*********************************************************************/
|
|
| 91 | + |
|
| 92 | +#include <stdio.h>
|
|
| 93 | + |
|
| 94 | +/*
|
|
| 95 | + * Print out the first 10 random numbers from the generator. This is
|
|
| 96 | + * used for the expected results in the rng unit test.
|
|
| 97 | + */
|
|
| 98 | +void
|
|
| 99 | +test_rng()
|
|
| 100 | +{
|
|
| 101 | + int k;
|
|
| 102 | + uint64_t r;
|
|
| 103 | +
|
|
| 104 | +
|
|
| 105 | + s[0] = 0x38f1dc39d1906b6full;
|
|
| 106 | + s[1] = 0xdfe4142236dd9517ull;
|
|
| 107 | + |
|
| 108 | + printf(";; First 10 outputs\n");
|
|
| 109 | + |
|
| 110 | + for (k = 0; k < 10; ++k) {
|
|
| 111 | + r = next();
|
|
| 112 | + printf("%2d: #x%016llx (#x%016llx #x%016llx)\n", k, r, s[0], s[1]);
|
|
| 113 | + }
|
|
| 114 | +}
|
|
| 115 | + |
|
| 116 | +/*
|
|
| 117 | + * Print out the first 4 states from jumping generator by 2^64 steps.
|
|
| 118 | + * This is used for the expected results in the rng unit test.
|
|
| 119 | + */
|
|
| 120 | +void
|
|
| 121 | +test_jump()
|
|
| 122 | +{
|
|
| 123 | + int k;
|
|
| 124 | + |
|
| 125 | + s[0] = 0x38f1dc39d1906b6full;
|
|
| 126 | + s[1] = 0xdfe4142236dd9517ull;
|
|
| 127 | + |
|
| 128 | + printf(";; First 4 jumps\n");
|
|
| 129 | + for (k = 0; k < 4; ++k) {
|
|
| 130 | + jump();
|
|
| 131 | + printf("%2d: #x%016llx #x%016llx\n", k, s[0], s[1]);
|
|
| 132 | + }
|
|
| 133 | +}
|
|
| 134 | + |
|
| 135 | + |
|
| 136 | +int
|
|
| 137 | +main()
|
|
| 138 | +{
|
|
| 139 | + test_rng();
|
|
| 140 | + test_jump();
|
|
| 141 | +
|
|
| 142 | + return 0;
|
|
| 143 | +} |