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
.bj
/*is aliced*/;
21 // ////////////////////////////////////////////////////////////////////////// //
24 // http://burtleburtle.net/bob/rand/smallprng.html
27 // seeded with 0xdeadf00du
35 void randomize () @trusted {
37 import win32
.windef
, win32
.winbase
;
38 uint s0
= xyzzyPRNGHashU32(cast(uint)GetCurrentProcessId());
39 uint s1
= xyzzyPRNGHashU32(cast(uint)GetTickCount());
43 import core
.sys
.posix
.fcntl
;
44 import core
.sys
.posix
.unistd
;
45 uint s0
= 0xdeadf00du
;
46 int fd
= open("/dev/urandom", O_RDONLY
);
48 read(fd
, &s0
, s0
.sizeof
);
56 enum bool isUniformRandom
= true;
57 enum uint min
= uint.min
;
58 enum uint max
= uint.max
;
60 enum bool empty
= false;
61 @property uint front () const { pragma(inline
, true); return d
; }
62 alias popFront
= next
;
63 @property auto save () const { BJRng res
= void; res
.a
= this.a
; res
.b
= this.b
; res
.c
= this.c
; res
.d
= this.d
; return res
; }
65 this (uint aseed
) { pragma(inline
, true); seed(aseed
); }
67 void seed (uint seed
) {
70 foreach (immutable _
; 0..20) next
;
73 @property uint next () {
74 enum ROT(string var
, string cnt
) = `cast(uint)(((`~var
~`)<<(`~cnt
~`))|((`~var
~`)>>(32-(`~cnt
~`))))`;
77 e = a-BJPRNG_ROT(b, 27);
78 a = b^BJPRNG_ROT(c, 17);
83 /* better, but slower at least in idiotic m$vc */
84 e
= a
-mixin(ROT
!("b", "23"));
85 a
= b^
mixin(ROT
!("c", "16"));
86 b
= c
+mixin(ROT
!("d", "11"));
94 version(test_bj
) unittest {
95 static immutable uint[8] checkValues
= [
107 foreach (ulong v
; checkValues
) {
108 if (v
!= rng
.front
) assert(0);
109 //import std.stdio; writeln(rng.front, "u");
115 import std
.random
: uniform
;
117 foreach (immutable _
; 0..8) {
119 auto v
= uniform
!"[)"(0, 4, rng
);
126 // ////////////////////////////////////////////////////////////////////////// //
127 // One of the by George Marsaglia's prng generators.
128 // It is based on George Marsaglia's MWC (multiply with carry) generator.
129 // Although it is very simple, it passes Marsaglia's DIEHARD series of random
130 // number generator tests.
133 // These values are not magical, just the default values Marsaglia used.
134 // Any pair of unsigned integers should be fine.
135 enum uint DefaultW
= 521288629u;
136 enum uint DefaultZ
= 362436069u;
140 uint lastnum
= (DefaultZ
<<16)+DefaultW
;
144 void randomize () @trusted {
146 import win32
.windef
, win32
.winbase
;
147 w
= xyzzyPRNGHashU32(cast(uint)GetCurrentProcessId());
148 z
= xyzzyPRNGHashU32(cast(uint)GetTickCount());
151 import core
.sys
.posix
.fcntl
;
152 import core
.sys
.posix
.unistd
;
155 int fd
= open("/dev/urandom", O_RDONLY
);
157 read(fd
, &w
, w
.sizeof
);
158 read(fd
, &z
, z
.sizeof
);
165 enum bool isUniformRandom
= true;
166 enum uint min
= uint.min
;
167 enum uint max
= uint.max
;
169 enum bool empty
= false;
170 @property uint front () const { pragma(inline
, true); return lastnum
; }
171 alias popFront
= next
;
172 @property auto save () const { GMRngSeed64 res
= void; res
.w
= this.w
; res
.z
= this.z
; res
.lastnum
= this.lastnum
; return res
; }
174 this (ulong aseed
) { pragma(inline
, true); seed(aseed
); }
176 void seed (ulong seed
) {
177 z
= cast(uint)(seed
>>32);
178 w
= cast(uint)(seed
&0xffffffffu
);
179 if (w
== 0) w
= DefaultW
;
180 if (z
== 0) z
= DefaultZ
;
184 @property uint next () {
185 if (w
== 0) w
= DefaultW
;
186 if (z
== 0) z
= DefaultZ
;
187 z
= 36969*(z
&0xffff)+(z
>>16);
188 w
= 18000*(w
&0xffff)+(w
>>16);
189 return (lastnum
= (z
<<16)+w
);
193 version(test_gms64
) unittest {
194 static immutable uint[8] checkValues
= [
205 auto rng
= GMRngSeed64(0);
206 foreach (ulong v
; checkValues
) {
207 if (v
!= rng
.front
) assert(0);
208 //import std.stdio; writeln(rng.front, "u");
214 import std
.random
: uniform
;
215 auto rng
= GMRngSeed64(0);
216 foreach (immutable _
; 0..8) {
218 auto v
= uniform
!"[)"(0, 4, rng
);
225 // ////////////////////////////////////////////////////////////////////////// //
226 // one of the by George Marsaglia's prng generators, period about 2^160. fast.
229 // seeded with 0xdeadf00du
230 uint x
= 0xdeadf00du
;
231 uint y
= 0xe3324aa1u
;
232 uint z
= 0x7ed1c277u
;
233 uint w
= 0x89574524u
;
234 uint v
= 0x359c34a7u
;
235 uint lastnum
= 0x4d00381eu
; // almost arbitrary
239 void randomize () @trusted {
241 import win32
.windef
, win32
.winbase
;
243 s0
[0] = xyzzyPRNGHashU32(cast(uint)GetCurrentProcessId());
244 s0
[1] = xyzzyPRNGHashU32(cast(uint)GetTickCount());
248 import core
.sys
.posix
.fcntl
;
249 import core
.sys
.posix
.unistd
;
251 int fd
= open("/dev/urandom", O_RDONLY
);
253 read(fd
, s0
.ptr
, s0
.sizeof
);
261 enum bool isUniformRandom
= true;
262 enum uint min
= uint.min
;
263 enum uint max
= uint.max
;
265 enum bool empty
= false;
266 @property uint front () const { pragma(inline
, true); return lastnum
; }
267 alias popFront
= next
;
268 @property auto save () const { GMRng res
= void; res
.x
= this.x
; res
.y
= this.y
; res
.z
= this.z
; res
.w
= this.w
; res
.v
= this.v
; res
.lastnum
= this.lastnum
; return res
; }
270 this (uint aseed
) { pragma(inline
, true); seed(aseed
); }
272 void seed (uint seed
) {
273 x
= (seed ? seed
: 0xdeadf00du
);
274 y
= xyzzyPRNGHashU32(x
+1);
275 z
= xyzzyPRNGHashU32(y
+1);
276 w
= xyzzyPRNGHashU32(z
+1);
277 v
= xyzzyPRNGHashU32(w
+1);
281 void seed (uint s0
, uint s1
, uint s2
, uint s3
, uint s4
) {
287 if (x
== 0) x
= 0xdeadf00du
;
288 if (y
== 0) y
= xyzzyPRNGHashU32(x
+1);
289 if (z
== 0) z
= xyzzyPRNGHashU32(y
+1);
290 if (w
== 0) w
= xyzzyPRNGHashU32(z
+1);
291 if (v
== 0) v
= xyzzyPRNGHashU32(w
+1);
295 void seed (in uint[] seed
) {
296 x
= (seed
.length
> 0 ? seed
[0] : 0xdeadf00du
);
297 y
= (seed
.length
> 1 ? seed
[1] : xyzzyPRNGHashU32(x
+1));
298 z
= (seed
.length
> 2 ? seed
[2] : xyzzyPRNGHashU32(y
+1));
299 w
= (seed
.length
> 3 ? seed
[3] : xyzzyPRNGHashU32(z
+1));
300 v
= (seed
.length
> 4 ? seed
[4] : xyzzyPRNGHashU32(w
+1));
301 if (x
== 0) x
= 0xdeadf00du
;
302 if (y
== 0) y
= xyzzyPRNGHashU32(x
+1);
303 if (z
== 0) z
= xyzzyPRNGHashU32(y
+1);
304 if (w
== 0) w
= xyzzyPRNGHashU32(z
+1);
305 if (v
== 0) v
= xyzzyPRNGHashU32(w
+1);
309 @property uint next () {
316 v
= (v^
(v
<<6))^
(t^
(t
<<13));
317 return (lastnum
= (y
+y
+1)*v
);
321 version(test_gms
) unittest {
322 static immutable uint[8] checkValues
= [
334 foreach (ulong v
; checkValues
) {
335 if (v
!= rng
.front
) assert(0);
336 //import std.stdio; writeln(rng.front, "u");
342 import std
.random
: uniform
;
344 foreach (immutable _
; 0..8) {
346 auto v
= uniform
!"[)"(0, 4, rng
);
353 // ////////////////////////////////////////////////////////////////////////// //
354 version(test_prng
) unittest {
356 template checkRng(T
) {
357 static assert(isInfinite
!T
, T
.stringof
~" is not infinite range");
358 static assert(isInputRange
!T
, T
.stringof
~" is not inpute range");
359 static assert(isForwardRange
!T
, T
.stringof
~" is not forward range");
360 enum checkRng
= true;
362 static assert(checkRng
!BJRng
);
363 static assert(checkRng
!GMRngSeed64
);
364 static assert(checkRng
!GMRng
);
368 // ////////////////////////////////////////////////////////////////////////// //
369 private uint xyzzyPRNGHashU32() (uint a
) {