sq3: cosmetic upgrades
[iv.d.git] / prng / old.d
blob21458beee6be635017332ee40e53c8d22b21c70c
1 /* Invisible Vector Library
2 * coded by Ketmar // Invisible Vector <ketmar@ketmar.no-ip.org>
3 * Understanding is not required. Only obedience.
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, version 3 of the License ONLY.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 module iv.prng.old /*is aliced*/;
18 import iv.alice;
21 private uint xyzzyPRNGHashU32() (uint a) {
22 a -= (a<<6);
23 a ^= (a>>17);
24 a -= (a<<9);
25 a ^= (a<<4);
26 a -= (a<<3);
27 a ^= (a<<10);
28 a ^= (a>>15);
29 return a;
33 // ////////////////////////////////////////////////////////////////////////// //
34 // by Bob Jenkins
35 // public domain
36 // http://burtleburtle.net/bob/rand/smallprng.html
37 struct BJRng {
38 private:
39 // seeded with 0xdeadf00du
40 uint a = 0xe5595c3bu;
41 uint b = 0xe60c3611u;
42 uint c = 0x1ceca1b1u;
43 uint d = 0x32744417u;
45 nothrow: @nogc:
46 public:
47 void randomize () @trusted {
48 version(Windows) {
49 import win32.windef, win32.winbase;
50 uint s0 = xyzzyPRNGHashU32(cast(uint)GetCurrentProcessId());
51 uint s1 = xyzzyPRNGHashU32(cast(uint)GetTickCount());
52 seed(s0^s1);
53 } else {
54 // assume POSIX
55 import core.sys.posix.fcntl;
56 import core.sys.posix.unistd;
57 uint s0 = 0xdeadf00du;
58 int fd = open("/dev/urandom", O_RDONLY);
59 if (fd >= 0) {
60 read(fd, &s0, s0.sizeof);
61 close(fd);
63 seed(s0);
67 @safe:
68 enum empty = false;
69 @property uint front () const => d;
70 alias popFront = next;
71 @property auto save () inout => this;
73 this (uint aseed) => seed(aseed);
75 void seed (uint seed) {
76 a = 0xf1ea5eed;
77 b = c = d = seed;
78 foreach (; 0..20) next;
81 @property uint next () {
82 enum ROT(string var, string cnt) = `cast(uint)(((`~var~`)<<(`~cnt~`))|((`~var~`)>>(32-(`~cnt~`))))`;
83 uint e;
84 /* original:
85 e = a-BJPRNG_ROT(b, 27);
86 a = b^BJPRNG_ROT(c, 17);
87 b = c+d;
88 c = d+e;
89 d = e+a;
91 /* better, but slower at least in idiotic m$vc */
92 e = a-mixin(ROT!("b", "23"));
93 a = b^mixin(ROT!("c", "16"));
94 b = c+mixin(ROT!("d", "11"));
95 c = d+e;
96 d = e+a;
97 return d;
102 // ////////////////////////////////////////////////////////////////////////// //
103 // One of the by George Marsaglia's prng generators.
104 // It is based on George Marsaglia's MWC (multiply with carry) generator.
105 // Although it is very simple, it passes Marsaglia's DIEHARD series of random
106 // number generator tests.
107 struct GMRngSeed64 {
108 private:
109 // These values are not magical, just the default values Marsaglia used.
110 // Any pair of unsigned integers should be fine.
111 enum uint DefaultW = 521288629u;
112 enum uint DefaultZ = 362436069u;
114 uint w = DefaultW;
115 uint z = DefaultZ;
116 uint lastnum = (DefaultZ<<16)+DefaultW;
118 nothrow: @nogc:
119 public:
120 void randomize () @trusted {
121 version(Windows) {
122 import win32.windef, win32.winbase;
123 w = xyzzyPRNGHashU32(cast(uint)GetCurrentProcessId());
124 z = xyzzyPRNGHashU32(cast(uint)GetTickCount());
125 } else {
126 // assume POSIX
127 import core.sys.posix.fcntl;
128 import core.sys.posix.unistd;
129 w = DefaultW;
130 z = DefaultZ;
131 int fd = open("/dev/urandom", O_RDONLY);
132 if (fd >= 0) {
133 read(fd, &w, w.sizeof);
134 read(fd, &z, z.sizeof);
135 close(fd);
140 @safe:
141 enum empty = false;
142 @property uint front () const => lastnum;
143 alias popFront = next;
144 @property auto save () inout => this;
146 this (ulong aseed) => seed(aseed);
148 void seed (ulong seed) {
149 z = cast(uint)(seed>>32);
150 w = cast(uint)(seed&0xffffffffu);
151 if (w == 0) w = DefaultW;
152 if (z == 0) z = DefaultZ;
153 lastnum = (z<<16)+w;
156 @property uint next () {
157 if (w == 0) w = DefaultW;
158 if (z == 0) z = DefaultZ;
159 z = 36969*(z&0xffff)+(z>>16);
160 w = 18000*(w&0xffff)+(w>>16);
161 return (lastnum = (z<<16)+w);
166 // ////////////////////////////////////////////////////////////////////////// //
167 // one of the by George Marsaglia's prng generators, period about 2^160. fast.
168 struct GMRng {
169 private:
170 // seeded with 0xdeadf00du
171 uint x = 0xdeadf00du;
172 uint y = 0xe3324aa1u;
173 uint z = 0x7ed1c277u;
174 uint w = 0x89574524u;
175 uint v = 0x359c34a7u;
176 uint lastnum = 0x4d00381eu; // almost arbitrary
178 nothrow: @nogc:
179 public:
180 void randomize () @trusted {
181 version(Windows) {
182 import win32.windef, win32.winbase;
183 uint[5] s0;
184 s0[0] = xyzzyPRNGHashU32(cast(uint)GetCurrentProcessId());
185 s0[1] = xyzzyPRNGHashU32(cast(uint)GetTickCount());
186 seed(s0[]);
187 } else {
188 // assume POSIX
189 import core.sys.posix.fcntl;
190 import core.sys.posix.unistd;
191 uint[5] s0;
192 int fd = open("/dev/urandom", O_RDONLY);
193 if (fd >= 0) {
194 read(fd, s0.ptr, s0.sizeof);
195 close(fd);
197 seed(s0[]);
201 @safe:
202 enum empty = false;
203 @property uint front () const => lastnum;
204 alias popFront = next;
205 @property auto save () inout => this;
207 this (uint aseed) => seed(aseed);
209 void seed (uint seed) {
210 x = (seed ? seed : 0xdeadf00du);
211 y = xyzzyPRNGHashU32(x+1);
212 z = xyzzyPRNGHashU32(y+1);
213 w = xyzzyPRNGHashU32(z+1);
214 v = xyzzyPRNGHashU32(w+1);
215 next;
218 void seed (uint s0, uint s1, uint s2, uint s3, uint s4) {
219 x = s0;
220 y = s1;
221 z = s2;
222 w = s3;
223 v = s4;
224 if (x == 0) x = 0xdeadf00du;
225 if (y == 0) y = xyzzyPRNGHashU32(x+1);
226 if (z == 0) z = xyzzyPRNGHashU32(y+1);
227 if (w == 0) w = xyzzyPRNGHashU32(z+1);
228 if (v == 0) v = xyzzyPRNGHashU32(w+1);
229 next;
232 void seed (in uint[] seed) {
233 x = (seed.length > 0 ? seed[0] : 0xdeadf00du);
234 y = (seed.length > 1 ? seed[1] : xyzzyPRNGHashU32(x+1));
235 z = (seed.length > 2 ? seed[2] : xyzzyPRNGHashU32(y+1));
236 w = (seed.length > 3 ? seed[3] : xyzzyPRNGHashU32(z+1));
237 v = (seed.length > 4 ? seed[4] : xyzzyPRNGHashU32(w+1));
238 if (x == 0) x = 0xdeadf00du;
239 if (y == 0) y = xyzzyPRNGHashU32(x+1);
240 if (z == 0) z = xyzzyPRNGHashU32(y+1);
241 if (w == 0) w = xyzzyPRNGHashU32(z+1);
242 if (v == 0) v = xyzzyPRNGHashU32(w+1);
243 next;
246 @property uint next () {
247 uint t;
248 t = (x^(x>>7));
249 x = y;
250 y = z;
251 z = w;
252 w = v;
253 v = (v^(v<<6))^(t^(t<<13));
254 return (lastnum = (y+y+1)*v);
259 version(test_prng)
260 unittest {
261 import std.range;
262 template checkRng(T) {
263 static assert(isInfinite!T, T.stringof~" is not infinite range");
264 static assert(isInputRange!T, T.stringof~" is not inpute range");
265 static assert(isForwardRange!T, T.stringof~" is not forward range");
266 enum checkRng = true;
268 static assert(checkRng!BJRng);
269 static assert(checkRng!GMRngSeed64);
270 static assert(checkRng!GMRng);
272 import iv.writer;
275 BJRng r;
276 r.seed(0xdeadf00du);
277 writefln!" uint a = 0x%08xu;"(r.a);
278 writefln!" uint b = 0x%08xu;"(r.b);
279 writefln!" uint c = 0x%08xu;"(r.c);
280 writefln!" uint d = 0x%08xu;"(r.d);
285 GMRngSeed64 r;
286 r.seed(0xdeadf00d_fee1deadul);
287 writefln!" uint w = 0x%08xu;"(r.w);
288 writefln!" uint z = 0x%08xu;"(r.z);
293 GMRng r;
294 r.seed(0xdeadf00du);
295 writefln!" uint x = 0x%08xu;"(r.x);
296 writefln!" uint y = 0x%08xu;"(r.y);
297 writefln!" uint z = 0x%08xu;"(r.z);
298 writefln!" uint w = 0x%08xu;"(r.w);
299 writefln!" uint v = 0x%08xu;"(r.v);
303 BJRng r;
304 r.randomize();
305 writefln!"0x%08x"(r.next);
308 GMRngSeed64 r;
309 r.randomize();
310 writefln!"0x%08x"(r.next);
313 GMRng r;
314 r.randomize();
315 writefln!"0x%08x"(r.next);