aboutsummaryrefslogtreecommitdiff
path: root/src/lib9/lrand.c
diff options
context:
space:
mode:
authorrsc <devnull@localhost>2004-12-28 20:01:58 +0000
committerrsc <devnull@localhost>2004-12-28 20:01:58 +0000
commitb37396bd1173964d5a3e40cc3e35aad5fef854c5 (patch)
tree84b536a73e343c2663079803ab30ab6fb7c8d8a5 /src/lib9/lrand.c
parent4dd07e012c124921328df5d91c272c63e015bdd5 (diff)
downloadplan9port-b37396bd1173964d5a3e40cc3e35aad5fef854c5.tar.gz
plan9port-b37396bd1173964d5a3e40cc3e35aad5fef854c5.tar.bz2
plan9port-b37396bd1173964d5a3e40cc3e35aad5fef854c5.zip
make these files look like plan 9's
Diffstat (limited to 'src/lib9/lrand.c')
-rw-r--r--src/lib9/lrand.c77
1 files changed, 76 insertions, 1 deletions
diff --git a/src/lib9/lrand.c b/src/lib9/lrand.c
index 47c331d9..2ebb3962 100644
--- a/src/lib9/lrand.c
+++ b/src/lib9/lrand.c
@@ -1,8 +1,83 @@
#include <u.h>
#include <libc.h>
+/*
+ * algorithm by
+ * D. P. Mitchell & J. A. Reeds
+ */
+
+#define LEN 607
+#define TAP 273
+#define MASK 0x7fffffffL
+#define A 48271
+#define M 2147483647
+#define Q 44488
+#define R 3399
+#define NORM (1.0/(1.0+MASK))
+
+static ulong rng_vec[LEN];
+static ulong* rng_tap = rng_vec;
+static ulong* rng_feed = 0;
+static Lock lk;
+
+static void
+isrand(long seed)
+{
+ long lo, hi, x;
+ int i;
+
+ rng_tap = rng_vec;
+ rng_feed = rng_vec+LEN-TAP;
+ seed = seed%M;
+ if(seed < 0)
+ seed += M;
+ if(seed == 0)
+ seed = 89482311;
+ x = seed;
+ /*
+ * Initialize by x[n+1] = 48271 * x[n] mod (2**31 - 1)
+ */
+ for(i = -20; i < LEN; i++) {
+ hi = x / Q;
+ lo = x % Q;
+ x = A*lo - R*hi;
+ if(x < 0)
+ x += M;
+ if(i >= 0)
+ rng_vec[i] = x;
+ }
+}
+
+void
+srand(long seed)
+{
+ lock(&lk);
+ isrand(seed);
+ unlock(&lk);
+}
+
long
lrand(void)
{
- return ((rand()<<16)^rand()) & 0x7FFFFFFF;
+ ulong x;
+
+ lock(&lk);
+
+ rng_tap--;
+ if(rng_tap < rng_vec) {
+ if(rng_feed == 0) {
+ isrand(1);
+ rng_tap--;
+ }
+ rng_tap += LEN;
+ }
+ rng_feed--;
+ if(rng_feed < rng_vec)
+ rng_feed += LEN;
+ x = (*rng_feed + *rng_tap) & MASK;
+ *rng_feed = x;
+
+ unlock(&lk);
+
+ return x;
}