| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| |
|
| | #ifndef __PRNG_H__ |
| | #define __PRNG_H__ |
| |
|
| | #include <inttypes.h> |
| | #include <stdint.h> |
| | #include <stdio.h> |
| | #include <stdlib.h> |
| |
|
| | #define LAG1 (UINT16_C(24)) |
| | #define LAG2 (UINT16_C(55)) |
| | #define RAND_SSIZE ((UINT16_C(1)) << 6) |
| | #define RAND_SMASK (RAND_SSIZE - 1) |
| | #define RAND_EXHAUST_LIMIT LAG2 |
| | |
| | #define RAND_REFILL_COUNT ((LAG2 * 10) - RAND_EXHAUST_LIMIT) |
| | struct prng_rand_t |
| | { |
| | uint64_t s[RAND_SSIZE]; |
| | uint_fast16_t i; |
| | uint_fast16_t c; |
| | }; |
| |
|
| | #define PRNG_RAND_MAX UINT64_MAX |
| |
|
| | static inline uint64_t prng_rand(struct prng_rand_t* state) |
| | { |
| | uint_fast16_t i; |
| | uint_fast16_t r, new_rands = 0; |
| |
|
| | if (!state->c) |
| | { |
| | new_rands += RAND_REFILL_COUNT + 1; |
| | state->c = RAND_EXHAUST_LIMIT - 1; |
| | } |
| | else |
| | { |
| | new_rands = 1; |
| | state->c--; |
| | } |
| |
|
| | for (r = 0; r < new_rands; r++) |
| | { |
| | i = state->i; |
| | state->s[i & RAND_SMASK] = state->s[(i + RAND_SSIZE - LAG1) & RAND_SMASK] |
| | + state->s[(i + RAND_SSIZE - LAG2) & RAND_SMASK]; |
| | state->i++; |
| | } |
| | return state->s[i & RAND_SMASK]; |
| | } |
| |
|
| | static inline void prng_srand(uint64_t seed, struct prng_rand_t* state) |
| | { |
| | uint_fast16_t i; |
| | |
| | state->c = RAND_EXHAUST_LIMIT; |
| | state->i = 0; |
| |
|
| | state->s[0] = seed; |
| | for (i = 1; i < RAND_SSIZE; i++) |
| | { |
| | |
| | |
| | state->s[i] = i * (UINT64_C(2147483647)) + seed; |
| | } |
| |
|
| | |
| | for (i = 0; i < 10000; i++) |
| | { |
| | prng_rand(state); |
| | } |
| | } |
| |
|
| | |
| | #undef LAG1 |
| | #undef LAG2 |
| | #undef RAND_SSIZE |
| | #undef RAND_SMASK |
| | #undef RAND_EXHAUST_LIMIT |
| | #undef RAND_REFILL_COUNT |
| |
|
| | |
| |
|
| | #endif |
| |
|