wmbattery: use CPPFLAGS for defining preprocessor macros.
[dockapps.git] / wmMatrix / yarandom.c
blob571b8acb80e6d5e09d0f82cd405fb6ffff6a5816
1 #define HAVE_UNISTD_H 1
2 #define GETTIMEOFDAY_TWO_ARGS 1
3 /* yarandom.c -- Yet Another Random Number Generator.
5 The unportable mess that is rand(), random(), drand48() and friends led me
6 to ask Phil Karlton <karlton@netscape.com> what the Right Thing to Do was.
7 He responded with this. It is non-cryptographically secure, reasonably
8 random (more so than anything that is in any C library), and very fast.
10 I don't understand how it works at all, but he says "look at Knuth,
11 Vol. 2 (original edition), page 26, Algorithm A. In this case n=55,
12 k=20 and m=2^32."
14 So there you have it.
16 ---------------------------
17 Note: xlockmore 4.03a10 uses this very simple RNG:
19 if ((seed = seed % 44488 * 48271 - seed / 44488 * 3399) < 0)
20 seed += 2147483647;
21 return seed-1;
23 of which it says
25 ``Dr. Park's algorithm published in the Oct. '88 ACM "Random Number
26 Generators: Good Ones Are Hard To Find" His version available at
27 ftp://cs.wm.edu/pub/rngs.tar Present form by many authors.''
29 Karlton says: ``the usual problem with that kind of RNG turns out to
30 be unexepected short cycles for some word lengths.''
32 Karlton's RNG is faster, since it does three adds and two stores, while the
33 xlockmore RNG does two multiplies, two divides, three adds, and one store.
35 Compiler optimizations make a big difference here:
36 gcc -O: difference is 1.2x.
37 gcc -O2: difference is 1.4x.
38 gcc -O3: difference is 1.5x.
39 SGI cc -O: difference is 2.4x.
40 SGI cc -O2: difference is 2.4x.
41 SGI cc -O3: difference is 5.1x.
42 Irix 6.2; Indy r5k; SGI cc version 6; gcc version 2.7.2.1.
45 #ifdef HAVE_UNISTD_H
46 #include <unistd.h> /* for getpid() */
47 #endif
48 #include <sys/time.h> /* for gettimeofday() */
50 #include "yarandom.h"
52 /* The following 'random' numbers are taken from CRC, 18th Edition, page 622.
53 Each array element was taken from the corresponding line in the table,
54 except that a[0] was from line 100. 8s and 9s in the table were simply
55 skipped. The high order digit was taken mod 4.
57 #define VectorSize 55
58 static unsigned int a[VectorSize] = {
59 035340171546, 010401501101, 022364657325, 024130436022, 002167303062, /* 5 */
60 037570375137, 037210607110, 016272055420, 023011770546, 017143426366, /* 10 */
61 014753657433, 021657231332, 023553406142, 004236526362, 010365611275, /* 14 */
62 007117336710, 011051276551, 002362132524, 001011540233, 012162531646, /* 20 */
63 007056762337, 006631245521, 014164542224, 032633236305, 023342700176, /* 25 */
64 002433062234, 015257225043, 026762051606, 000742573230, 005366042132, /* 30 */
65 012126416411, 000520471171, 000725646277, 020116577576, 025765742604, /* 35 */
66 007633473735, 015674255275, 017555634041, 006503154145, 021576344247, /* 40 */
67 014577627653, 002707523333, 034146376720, 030060227734, 013765414060, /* 45 */
68 036072251540, 007255221037, 024364674123, 006200353166, 010126373326, /* 50 */
69 015664104320, 016401041535, 016215305520, 033115351014, 017411670323 /* 55 */
72 static int i1, i2;
74 unsigned int ya_random(void)
76 register int ret = a[i1] + a[i2];
77 a[i1] = ret;
78 if (++i1 >= VectorSize)
79 i1 = 0;
80 if (++i2 >= VectorSize)
81 i2 = 0;
82 return ret;
85 void ya_rand_init(unsigned int seed)
87 int i;
88 if (seed == 0) {
89 struct timeval tp;
90 #ifdef GETTIMEOFDAY_TWO_ARGS
91 struct timezone tzp;
92 gettimeofday(&tp, &tzp);
93 #else
94 gettimeofday(&tp);
95 #endif
96 /* ignore overflow */
97 seed = (999 * tp.tv_sec) + (1001 * tp.tv_usec) + (1003 * getpid());
100 a[0] += seed;
101 for (i = 1; i < VectorSize; i++) {
102 seed = a[i - 1] * 1001 + seed * 999;
103 a[i] += seed;
106 i1 = a[0] % VectorSize;
107 i2 = (i1 + 024) % VectorSize;