summaryrefslogtreecommitdiffstats
path: root/util.c
diff options
context:
space:
mode:
authorTavian Barnes <tavianator@tavianator.com>2014-08-04 14:04:08 -0400
committerTavian Barnes <tavianator@tavianator.com>2014-08-04 14:04:08 -0400
commit25d1e5341b34db0855c2dd2823a2f2af94093803 (patch)
tree487a4e288212e577c9ad8f2214fd0185d11ba6f5 /util.c
parenta04e2f811d094f6641db4197388c267dff889b5c (diff)
downloadkd-forest-25d1e5341b34db0855c2dd2823a2f2af94093803.tar.xz
Use a repeatable cross-platform PRNG.
Diffstat (limited to 'util.c')
-rw-r--r--util.c33
1 files changed, 33 insertions, 0 deletions
diff --git a/util.c b/util.c
index 3c61cde..a2573a4 100644
--- a/util.c
+++ b/util.c
@@ -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;
+}