| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| #include <config.h> |
|
|
| #include "rand-isaac.h" |
|
|
| #include <limits.h> |
| #include <string.h> |
|
|
| |
| |
| #undef ATTRIBUTE_NO_WARN_SANITIZE_UNDEFINED |
| #if !(_STRING_ARCH_unaligned || _STRING_INLINE_unaligned) \ |
| || __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 9) |
| # define ATTRIBUTE_NO_WARN_SANITIZE_UNDEFINED |
| #else |
| # define ATTRIBUTE_NO_WARN_SANITIZE_UNDEFINED \ |
| __attribute__ ((__no_sanitize_undefined__)) |
| #endif |
|
|
| |
| |
| |
| #define IF32(a, b) (ISAAC_BITS == 32 ? (a) : (b)) |
|
|
| |
| |
| |
| static inline isaac_word |
| just (isaac_word a) |
| { |
| isaac_word desired_bits = ((isaac_word) 1 << 1 << (ISAAC_BITS - 1)) - 1; |
| return a & desired_bits; |
| } |
|
|
| |
| static inline isaac_word |
| ind (isaac_word const *m, isaac_word x) |
| { |
| if (sizeof *m * CHAR_BIT == ISAAC_BITS) |
| { |
| |
| |
| |
| void const *void_m = m; |
| char const *base_p = void_m; |
| void const *word_p = base_p + (x & ((ISAAC_WORDS - 1) * sizeof *m)); |
| isaac_word const *p = word_p; |
| return *p; |
| } |
| else |
| { |
| |
| return m[(x / (ISAAC_BITS / CHAR_BIT)) & (ISAAC_WORDS - 1)]; |
| } |
| } |
|
|
| |
| void ATTRIBUTE_NO_WARN_SANITIZE_UNDEFINED |
| isaac_refill (struct isaac_state *s, isaac_word result[ISAAC_WORDS]) |
| { |
| |
| isaac_word a = s->a; |
| isaac_word b = s->b + (++s->c); |
|
|
| |
| isaac_word *m = s->m; |
| isaac_word *r = result; |
|
|
| enum { HALF = ISAAC_WORDS / 2 }; |
|
|
| |
| |
| |
| |
| |
| #define ISAAC_STEP(i, off, mix) \ |
| { \ |
| isaac_word x, y; \ |
| a = (IF32 (a, 0) ^ (mix)) + m[off + (i)]; \ |
| x = m[i]; \ |
| m[i] = y = ind (s->m, x) + a + b; \ |
| r[i] = b = just (ind (s->m, y >> ISAAC_WORDS_LOG) + x); \ |
| } |
|
|
| do |
| { |
| ISAAC_STEP (0, HALF, IF32 ( a << 13, ~ (a ^ (a << 21)))); |
| ISAAC_STEP (1, HALF, IF32 (just (a) >> 6, a ^ (just (a) >> 5))); |
| ISAAC_STEP (2, HALF, IF32 ( a << 2, a ^ ( a << 12))); |
| ISAAC_STEP (3, HALF, IF32 (just (a) >> 16, a ^ (just (a) >> 33))); |
| r += 4; |
| } |
| while ((m += 4) < s->m + HALF); |
|
|
| do |
| { |
| ISAAC_STEP (0, -HALF, IF32 ( a << 13, ~ (a ^ (a << 21)))); |
| ISAAC_STEP (1, -HALF, IF32 (just (a) >> 6, a ^ (just (a) >> 5))); |
| ISAAC_STEP (2, -HALF, IF32 ( a << 2, a ^ ( a << 12))); |
| ISAAC_STEP (3, -HALF, IF32 (just (a) >> 16, a ^ (just (a) >> 33))); |
| r += 4; |
| } |
| while ((m += 4) < s->m + ISAAC_WORDS); |
|
|
| s->a = a; |
| s->b = b; |
| } |
|
|
| |
| |
| |
| |
| #if ISAAC_BITS == 32 |
| #define mix(a, b, c, d, e, f, g, h) \ |
| { \ |
| a ^= b << 11; d += a; \ |
| b += c; b ^= just (c) >> 2; e += b; \ |
| c += d; c ^= d << 8; f += c; \ |
| d += e; d ^= just (e) >> 16; g += d; \ |
| e += f; e ^= f << 10; h += e; \ |
| f += g; f ^= just (g) >> 4; a += f; \ |
| g += h; g ^= h << 8; b += g; \ |
| h += a; h ^= just (a) >> 9; c += h; \ |
| a += b; \ |
| } |
| #else |
| #define mix(a, b, c, d, e, f, g, h) \ |
| { \ |
| a -= e; f ^= just (h) >> 9; h += a; \ |
| b -= f; g ^= a << 9; a += b; \ |
| c -= g; h ^= just (b) >> 23; b += c; \ |
| d -= h; a ^= c << 15; c += d; \ |
| e -= a; b ^= just (d) >> 14; d += e; \ |
| f -= b; c ^= e << 20; e += f; \ |
| g -= c; d ^= just (f) >> 17; f += g; \ |
| h -= d; e ^= g << 14; g += h; \ |
| } |
| #endif |
|
|
|
|
| |
| #define ISAAC_MIX(s, a, b, c, d, e, f, g, h, seed) \ |
| { \ |
| int i; \ |
| \ |
| for (i = 0; i < ISAAC_WORDS; i += 8) \ |
| { \ |
| a += seed[i]; \ |
| b += seed[i + 1]; \ |
| c += seed[i + 2]; \ |
| d += seed[i + 3]; \ |
| e += seed[i + 4]; \ |
| f += seed[i + 5]; \ |
| g += seed[i + 6]; \ |
| h += seed[i + 7]; \ |
| mix (a, b, c, d, e, f, g, h); \ |
| s->m[i] = a; \ |
| s->m[i + 1] = b; \ |
| s->m[i + 2] = c; \ |
| s->m[i + 3] = d; \ |
| s->m[i + 4] = e; \ |
| s->m[i + 5] = f; \ |
| s->m[i + 6] = g; \ |
| s->m[i + 7] = h; \ |
| } \ |
| } |
|
|
| #if 0 |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| static void |
| isaac_init (struct isaac_state *s, isaac_word const *seed, size_t seedsize) |
| { |
| isaac_word a, b, c, d, e, f, g, h; |
|
|
| a = b = c = d = e = f = g = h = |
| IF32 (UINT32_C (0x9e3779b9), UINT64_C (0x9e3779b97f4a7c13)); |
| for (int i = 0; i < 4; i++) |
| mix (a, b, c, d, e, f, g, h); |
| s->a = s->b = s->c = 0; |
|
|
| if (seedsize) |
| { |
| |
| ISAAC_MIX (s, a, b, c, d, e, f, g, h, seed); |
| |
| while (seedsize -= ISAAC_BYTES) |
| { |
| seed += ISAAC_WORDS; |
| for (i = 0; i < ISAAC_WORDS; i++) |
| s->m[i] += seed[i]; |
| ISAAC_MIX (s, a, b, c, d, e, f, g, h, s->m); |
| } |
| } |
| else |
| { |
| |
| for (i = 0; i < ISAAC_WORDS; i++) |
| s->m[i] = 0; |
| } |
|
|
| |
| ISAAC_MIX (s, a, b, c, d, e, f, g, h, s->m); |
| } |
| #endif |
|
|
| |
| |
| void |
| isaac_seed (struct isaac_state *s) |
| { |
| isaac_word a = IF32 (UINT32_C (0x1367df5a), UINT64_C (0x647c4677a2884b7c)); |
| isaac_word b = IF32 (UINT32_C (0x95d90059), UINT64_C (0xb9f8b322c73ac862)); |
| isaac_word c = IF32 (UINT32_C (0xc3163e4b), UINT64_C (0x8c0ea5053d4712a0)); |
| isaac_word d = IF32 (UINT32_C (0x0f421ad8), UINT64_C (0xb29b2e824a595524)); |
| isaac_word e = IF32 (UINT32_C (0xd92a4a78), UINT64_C (0x82f053db8355e0ce)); |
| isaac_word f = IF32 (UINT32_C (0xa51a3c49), UINT64_C (0x48fe4a0fa5a09315)); |
| isaac_word g = IF32 (UINT32_C (0xc4efea1b), UINT64_C (0xae985bf2cbfc89ed)); |
| isaac_word h = IF32 (UINT32_C (0x30609119), UINT64_C (0x98f5704f6c44c0ab)); |
|
|
| #if 0 |
| |
| a = b = c = d = e = f = g = h = |
| IF32 (UINT32_C (0x9e3779b9), UINT64_C (0x9e3779b97f4a7c13)); |
| for (int i = 0; i < 4; i++) |
| mix (a, b, c, d, e, f, g, h); |
| #endif |
|
|
| |
| |
| ISAAC_MIX (s, a, b, c, d, e, f, g, h, s->m); |
| ISAAC_MIX (s, a, b, c, d, e, f, g, h, s->m); |
|
|
| s->a = s->b = s->c = 0; |
| } |
|
|