comparison lphobos/std/random.d @ 473:373489eeaf90

Applied downs' lphobos update
author Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
date Mon, 04 Aug 2008 19:28:49 +0200
parents
children 88e23f8c2354
comparison
equal deleted inserted replaced
472:15c804b6ce77 473:373489eeaf90
1 /**
2 * Macros:
3 * WIKI = Phobos/StdRandom
4 */
5
6 // random.d
7 // www.digitalmars.com
8
9 /* NOTE: This file has been patched from the original DMD distribution to
10 work with the GDC compiler.
11
12 Modified by David Friedman, September 2007
13 */
14
15 module std.random;
16
17 // Segments of the code in this file Copyright (c) 1997 by Rick Booth
18 // From "Inner Loops" by Rick Booth, Addison-Wesley
19
20 version (Win32)
21 {
22 extern(Windows) int QueryPerformanceCounter(ulong *count);
23 }
24 else version (Unix)
25 {
26 version(linux) import std.c.linux.linux;
27 else private import std.c.unix.unix;
28 }
29
30 /* ===================== Random ========================= */
31
32 // BUG: not multithreaded
33
34 private uint seed; // starting seed
35 private uint index; // ith random number
36
37 /**
38 * The random number generator is seeded at program startup with a random value.
39 This ensures that each program generates a different sequence of random
40 numbers. To generate a repeatable sequence, use rand_seed() to start the
41 sequence. seed and index start it, and each successive value increments index.
42 This means that the $(I n)th random number of the sequence can be directly
43 generated
44 by passing index + $(I n) to rand_seed().
45
46 Note: This is more random, but slower, than C's rand() function.
47 To use C's rand() instead, import std.c.stdlib.
48 */
49
50 void rand_seed(uint seed, uint index)
51 {
52 .seed = seed;
53 .index = index;
54 }
55
56 /**
57 * Get the next random number in sequence.
58 * BUGS: shares a global single state, not multithreaded
59 */
60
61 uint rand()
62 {
63 static uint xormix1[20] =
64 [
65 0xbaa96887, 0x1e17d32c, 0x03bcdc3c, 0x0f33d1b2,
66 0x76a6491d, 0xc570d85d, 0xe382b1e3, 0x78db4362,
67 0x7439a9d4, 0x9cea8ac5, 0x89537c5c, 0x2588f55d,
68 0x415b5e1d, 0x216e3d95, 0x85c662e7, 0x5e8ab368,
69 0x3ea5cc8c, 0xd26a0f74, 0xf3a9222b, 0x48aad7e4
70 ];
71
72 static uint xormix2[20] =
73 [
74 0x4b0f3b58, 0xe874f0c3, 0x6955c5a6, 0x55a7ca46,
75 0x4d9a9d86, 0xfe28a195, 0xb1ca7865, 0x6b235751,
76 0x9a997a61, 0xaa6e95c8, 0xaaa98ee1, 0x5af9154c,
77 0xfc8e2263, 0x390f5e8c, 0x58ffd802, 0xac0a5eba,
78 0xac4874f6, 0xa9df0913, 0x86be4c74, 0xed2c123b
79 ];
80
81 uint hiword, loword, hihold, temp, itmpl, itmph, i;
82
83 loword = seed;
84 hiword = index++;
85 for (i = 0; i < 4; i++) // loop limit can be 2..20, we choose 4
86 {
87 hihold = hiword; // save hiword for later
88 temp = hihold ^ xormix1[i]; // mix up bits of hiword
89 itmpl = temp & 0xffff; // decompose to hi & lo
90 itmph = temp >> 16; // 16-bit words
91 temp = itmpl * itmpl + ~(itmph * itmph); // do a multiplicative mix
92 temp = (temp >> 16) | (temp << 16); // swap hi and lo halves
93 hiword = loword ^ ((temp ^ xormix2[i]) + itmpl * itmph); //loword mix
94 loword = hihold; // old hiword is loword
95 }
96 return hiword;
97 }
98
99 static this()
100 {
101 ulong s;
102
103 version(Win32)
104 {
105 QueryPerformanceCounter(&s);
106 }
107 else version(Unix)
108 {
109 // time.h
110 // sys/time.h
111
112 timeval tv;
113
114 if (gettimeofday(&tv, null))
115 { // Some error happened - try time() instead
116 s = time(null);
117 }
118 else
119 {
120 s = cast(ulong)((cast(long)tv.tv_sec << 32) + tv.tv_usec);
121 }
122 }
123 else version(NoSystem)
124 {
125 // nothing
126 }
127 else
128 static assert(false);
129 rand_seed(cast(uint) s, cast(uint)(s >> 32));
130 }
131
132
133 unittest
134 {
135 static uint results[10] =
136 [
137 0x8c0188cb,
138 0xb161200c,
139 0xfc904ac5,
140 0x2702e049,
141 0x9705a923,
142 0x1c139d89,
143 0x346b6d1f,
144 0xf8c33e32,
145 0xdb9fef76,
146 0xa97fcb3f
147 ];
148 int i;
149 uint seedsave = seed;
150 uint indexsave = index;
151
152 rand_seed(1234, 5678);
153 for (i = 0; i < 10; i++)
154 { uint r = rand();
155 //printf("0x%x,\n", rand());
156 assert(r == results[i]);
157 }
158
159 seed = seedsave;
160 index = indexsave;
161 }