Mercurial > projects > ldc
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 } |