diff options
author | Tavian Barnes <tavianator@tavianator.com> | 2014-08-04 14:04:08 -0400 |
---|---|---|
committer | Tavian Barnes <tavianator@tavianator.com> | 2014-08-04 14:04:08 -0400 |
commit | 25d1e5341b34db0855c2dd2823a2f2af94093803 (patch) | |
tree | 487a4e288212e577c9ad8f2214fd0185d11ba6f5 /util.c | |
parent | a04e2f811d094f6641db4197388c267dff889b5c (diff) | |
download | kd-forest-25d1e5341b34db0855c2dd2823a2f2af94093803.tar.xz |
Use a repeatable cross-platform PRNG.
Diffstat (limited to 'util.c')
-rw-r--r-- | util.c | 33 |
1 files changed, 33 insertions, 0 deletions
@@ -31,3 +31,36 @@ xrealloc(void *ptr, size_t size) } return ret; } + +// Based on sample rand() implementation from POSIX.1-2001 + +static unsigned long xrand_next = 0; + +void xsrand(unsigned int seed) { + xrand_next = seed; +} + +static unsigned int xrand_simple(void) { + xrand_next = xrand_next*1103515245 + 12345; + return (unsigned int)(xrand_next/65536)%32768; +} + +static unsigned int xrand_full(void) { + unsigned int low = xrand_simple(); + unsigned int high = xrand_simple(); + return low | (high << 15); +} + +#define XRAND_RANGE 1073741824U + +unsigned int +xrand(unsigned int range) +{ + // Compensate for bias if XRAND_RANGE isn't a multiple of range + unsigned int limit = XRAND_RANGE - XRAND_RANGE%range; + unsigned int res; + do { + res = xrand_full(); + } while (res >= limit); + return res%range; +} |