/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 |