/src/mcl/include/cybozu/xorshift.hpp
Line  | Count  | Source (jump to first uncovered line)  | 
1  |  | #pragma once  | 
2  |  | /**  | 
3  |  |   @file  | 
4  |  |   @brief XorShift  | 
5  |  |  | 
6  |  |   @author MITSUNARI Shigeo(@herumi)  | 
7  |  |   @author MITSUNARI Shigeo  | 
8  |  | */  | 
9  |  | #include <cybozu/inttype.hpp>  | 
10  |  | #include <assert.h>  | 
11  |  |  | 
12  |  | namespace cybozu { | 
13  |  |  | 
14  |  | namespace xorshift_local { | 
15  |  |  | 
16  |  | /*  | 
17  |  |   U is uint32_t or uint64_t  | 
18  |  | */  | 
19  |  | template<class U, class Gen>  | 
20  |  | void read_local(void *p, size_t n, Gen& gen, U (Gen::*f)())  | 
21  | 0  | { | 
22  | 0  |   uint8_t *dst = static_cast<uint8_t*>(p);  | 
23  | 0  |   const size_t uSize = sizeof(U);  | 
24  | 0  |   assert(uSize == 4 || uSize == 8);  | 
25  | 0  |   union ua { | 
26  | 0  |     U u;  | 
27  | 0  |     uint8_t a[uSize];  | 
28  | 0  |   };  | 
29  |  | 
  | 
30  | 0  |   while (n >= uSize) { | 
31  | 0  |     ua ua;  | 
32  | 0  |     ua.u = (gen.*f)();  | 
33  | 0  |     for (size_t i = 0; i < uSize; i++) { | 
34  | 0  |       dst[i] = ua.a[i];  | 
35  | 0  |     }  | 
36  | 0  |     dst += uSize;  | 
37  | 0  |     n -= uSize;  | 
38  | 0  |   }  | 
39  | 0  |   assert(n < uSize);  | 
40  | 0  |   if (n > 0) { | 
41  | 0  |     ua ua;  | 
42  | 0  |     ua.u = (gen.*f)();  | 
43  | 0  |     for (size_t i = 0; i < n; i++) { | 
44  | 0  |       dst[i] = ua.a[i];  | 
45  | 0  |     }  | 
46  | 0  |   }  | 
47  | 0  | }  | 
48  |  |  | 
49  |  | } // xorshift_local  | 
50  |  |  | 
51  |  | class XorShift { | 
52  |  |   uint32_t x_, y_, z_, w_;  | 
53  |  | public:  | 
54  |  |   explicit XorShift(uint32_t x = 0, uint32_t y = 0, uint32_t z = 0, uint32_t w = 0)  | 
55  | 0  |   { | 
56  | 0  |     init(x, y, z, w);  | 
57  | 0  |   }  | 
58  |  |   void init(uint32_t x = 0, uint32_t y = 0, uint32_t z = 0, uint32_t w = 0)  | 
59  | 0  |   { | 
60  | 0  |     x_ = x ? x : 123456789;  | 
61  | 0  |     y_ = y ? y : 362436069;  | 
62  | 0  |     z_ = z ? z : 521288629;  | 
63  | 0  |     w_ = w ? w : 88675123;  | 
64  | 0  |   }  | 
65  |  |   uint32_t get32()  | 
66  | 0  |   { | 
67  | 0  |     unsigned int t = x_ ^ (x_ << 11);  | 
68  | 0  |     x_ = y_; y_ = z_; z_ = w_;  | 
69  | 0  |     return w_ = (w_ ^ (w_ >> 19)) ^ (t ^ (t >> 8));  | 
70  | 0  |   }  | 
71  | 0  |   uint32_t operator()() { return get32(); } | 
72  |  |   uint64_t get64()  | 
73  | 0  |   { | 
74  | 0  |     uint32_t a = get32();  | 
75  | 0  |     uint32_t b = get32();  | 
76  | 0  |     return (uint64_t(a) << 32) | b;  | 
77  | 0  |   }  | 
78  |  |   template<class T>  | 
79  |  |   void read(bool *pb, T *p, size_t n)  | 
80  | 0  |   { | 
81  | 0  |     xorshift_local::read_local(p, n * sizeof(T), *this, &XorShift::get32);  | 
82  | 0  |     *pb = true;  | 
83  | 0  |   }  | 
84  |  |   template<class T>  | 
85  |  |   size_t read(T *p, size_t n)  | 
86  |  |   { | 
87  |  |     bool b;  | 
88  |  |     read(&b, p, n);  | 
89  |  |     (void)b;  | 
90  |  |     return n;  | 
91  |  |   }  | 
92  |  | };  | 
93  |  |  | 
94  |  | // see http://xorshift.di.unimi.it/xorshift128plus.c  | 
95  |  | class XorShift128Plus { | 
96  |  |   uint64_t s_[2];  | 
97  |  |   static const uint64_t seed0 = 123456789;  | 
98  |  |   static const uint64_t seed1 = 987654321;  | 
99  |  | public:  | 
100  |  |   explicit XorShift128Plus(uint64_t s0 = seed0, uint64_t s1 = seed1)  | 
101  | 0  |   { | 
102  | 0  |     init(s0, s1);  | 
103  | 0  |   }  | 
104  |  |   void init(uint64_t s0 = seed0, uint64_t s1 = seed1)  | 
105  | 0  |   { | 
106  | 0  |     s_[0] = s0;  | 
107  | 0  |     s_[1] = s1;  | 
108  | 0  |   }  | 
109  |  |   uint32_t get32()  | 
110  | 0  |   { | 
111  | 0  |     return static_cast<uint32_t>(get64());  | 
112  | 0  |   }  | 
113  | 0  |   uint64_t operator()() { return get64(); } | 
114  |  |   uint64_t get64()  | 
115  | 0  |   { | 
116  | 0  |     uint64_t s1 = s_[0];  | 
117  | 0  |     const uint64_t s0 = s_[1];  | 
118  | 0  |     s_[0] = s0;  | 
119  | 0  |     s1 ^= s1 << 23;  | 
120  | 0  |     s_[1] = s1 ^ s0 ^ (s1 >> 18) ^ (s0 >> 5);  | 
121  | 0  |     return s_[1] + s0;  | 
122  | 0  |   }  | 
123  |  |   template<class T>  | 
124  |  |   void read(bool *pb, T *p, size_t n)  | 
125  |  |   { | 
126  |  |     xorshift_local::read_local(p, n * sizeof(T), *this, &XorShift128Plus::get64);  | 
127  |  |     *pb = true;  | 
128  |  |   }  | 
129  |  |   template<class T>  | 
130  |  |   size_t read(T *p, size_t n)  | 
131  |  |   { | 
132  |  |     bool b;  | 
133  |  |     read(&b, p, n);  | 
134  |  |     (void)b;  | 
135  |  |     return n;  | 
136  |  |   }  | 
137  |  | };  | 
138  |  |  | 
139  |  | // see http://xoroshiro.di.unimi.it/xoroshiro128plus.c  | 
140  |  | class Xoroshiro128Plus { | 
141  |  |   uint64_t s_[2];  | 
142  |  |   static const uint64_t seed0 = 123456789;  | 
143  |  |   static const uint64_t seed1 = 987654321;  | 
144  |  |   uint64_t rotl(uint64_t x, unsigned int k) const  | 
145  | 0  |   { | 
146  | 0  |     return (x << k) | (x >> (64 - k));  | 
147  | 0  |   }  | 
148  |  | public:  | 
149  |  |   explicit Xoroshiro128Plus(uint64_t s0 = seed0, uint64_t s1 = seed1)  | 
150  | 0  |   { | 
151  | 0  |     init(s0, s1);  | 
152  | 0  |   }  | 
153  |  |   void init(uint64_t s0 = seed0, uint64_t s1 = seed1)  | 
154  | 0  |   { | 
155  | 0  |     s_[0] = s0;  | 
156  | 0  |     s_[1] = s1;  | 
157  | 0  |   }  | 
158  |  |   uint32_t get32()  | 
159  | 0  |   { | 
160  | 0  |     return static_cast<uint32_t>(get64());  | 
161  | 0  |   }  | 
162  | 0  |   uint64_t operator()() { return get64(); } | 
163  |  |   uint64_t get64()  | 
164  | 0  |   { | 
165  | 0  |     uint64_t s0 = s_[0];  | 
166  | 0  |     uint64_t s1 = s_[1];  | 
167  | 0  |     uint64_t result = s0 + s1;  | 
168  | 0  |     s1 ^= s0;  | 
169  | 0  |     s_[0] = rotl(s0, 55) ^ s1 ^ (s1 << 14);  | 
170  | 0  |     s_[1] = rotl(s1, 36);  | 
171  | 0  |     return result;  | 
172  | 0  |   }  | 
173  |  |   template<class T>  | 
174  |  |   void read(bool *pb, T *p, size_t n)  | 
175  |  |   { | 
176  |  |     xorshift_local::read_local(p, n * sizeof(T), *this, &Xoroshiro128Plus::get64);  | 
177  |  |     *pb = true;  | 
178  |  |   }  | 
179  |  |   template<class T>  | 
180  |  |   size_t read(T *p, size_t n)  | 
181  |  |   { | 
182  |  |     bool b;  | 
183  |  |     read(&b, p, n);  | 
184  |  |     (void)b;  | 
185  |  |     return n;  | 
186  |  |   }  | 
187  |  | };  | 
188  |  |  | 
189  |  | } // cybozu  |