|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#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 |
|
|