egra: checkbox fixes
[iv.d.git] / prng / pcg32.d
blob7a7785c7b69b2d741f299b3ba45d59f3b4d794fc
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 // PCG32 / (c) 2014 M.E. O'Neill / pcg-random.org
18 // Original code: Licensed under Apache License 2.0 (NO WARRANTY, etc. see website)
19 module iv.prng.pcg32 /*is aliced*/;
20 import iv.alice;
23 struct PCG32 {
24 private:
25 // for 0x29a, 42
26 // state
27 ulong state = 0x83a6d64d022268cdUL; // current state: PCG32 iterates through all 2^^64 possible internal states
28 ulong inc = 0x00000055UL; // sequence constant: a value that defines which of 2^^63 possible random sequences the current state is iterating through; it holds the same value over the lifetime of the PCG32
29 // current value
30 uint s = 0xe1ad5be5UL;
32 public:
33 pure nothrow @trusted @nogc:
34 enum bool isUniformRandom = true;
35 enum uint min = 0;
36 enum uint max = 0xffff_ffffu; // 32 bits
38 enum bool empty = false;
40 // seed the rng: specified in two parts, state initializer and a sequence selection constant (a.k.a. stream id)
41 this (ulong initstate, ulong initseq=42) { pragma(inline, true); seed(initstate, initseq); }
43 private this() (in auto ref PCG32 src) { pragma(inline, true); state = src.state; inc = src.inc; s = src.s; }
45 @property uint front () const { pragma(inline, true); return s; }
47 auto save () const { pragma(inline, true); return PCG32(this); }
49 void popFront () {
50 immutable ulong oldstate = state;
51 // advance internal state
52 state = oldstate*6364136223846793005UL+(inc|1);
53 // calculate output function (XSH RR), uses old state for max ILP
54 immutable uint xorshifted = cast(uint)(((oldstate>>18u)^oldstate)>>27u);
55 immutable uint rot = oldstate>>59u;
56 s = (xorshifted>>rot)|(xorshifted<<((-rot)&31));
59 // seed the rng: specified in two parts, state initializer and a sequence selection constant (a.k.a. stream id)
60 void seed (ulong initstate, ulong initseq) {
61 state = 0u;
62 inc = (initseq<<1u)|1u;
63 popFront();
64 state += initstate;
65 popFront();
66 // and current value
67 popFront();
72 version(test_pcg32) unittest {
73 static immutable uint[8] checkValues = [
74 1062842430u,
75 3170867712u,
76 3675510485u,
77 1618657033u,
78 1785850257u,
79 269545398u,
80 2793572921u,
81 3477214955u,
85 auto rng = PCG32(0x29a);
86 import std.stdio;
87 writefln("ulong state = 0x%08xUL;", rng.state);
88 writefln("ulong inc = 0x%08xUL;", rng.inc);
89 writefln("uint s = 0x%08xUL;", rng.s);
93 auto rng = PCG32(0);
94 foreach (uint v; checkValues) {
95 if (v != rng.front) assert(0);
96 //import std.stdio; writeln(rng.front, "u,");
97 rng.popFront();
100 // std.random test
102 import std.random : uniform;
103 auto rng = PCG32(0);
104 foreach (immutable _; 0..8) {
105 import std.stdio;
106 auto v = uniform!"[)"(0, 4, rng);
107 writeln(v, "uL");
114 // *Really* minimal PCG32 code / (c) 2014 M.E. O'Neill / pcg-random.org
115 // Licensed under Apache License 2.0 (NO WARRANTY, etc. see website)
117 struct pcg32_random_t { ulong state, inc; }
119 uint pcg32_random_r (ref pcg32_random_t rng) {
120 ulong oldstate = rng.state;
121 // advance internal state
122 rng.state = oldstate*6364136223846793005UL+(rng.inc|1);
123 // calculate output function (XSH RR), uses old state for max ILP
124 immutable uint xorshifted = ((oldstate>>18u)^oldstate)>>27u;
125 immutable uint rot = oldstate>>59u;
126 return (xorshifted>>rot)|(xorshifted<<((-rot)&31));
129 // pcg32_srandom_r(rng, initstate, initseq):
130 // Seed the rng. Specified in two parts, state initializer and a
131 // sequence selection constant (a.k.a. stream id)
132 void pcg32_srandom_r (ref pcg32_random_t rng, ulong initstate, ulong initseq) {
133 rng.state = 0U;
134 rng.inc = (initseq<<1u)|1u;
135 pcg32_random_r(rng);
136 rng.state += initstate;
137 pcg32_random_r(rng);