1
1
// //////////////////////////////////////////////////////////////////////////////
2
2
//
3
- // X128PP.hh : xoshiro128++ PRNG (uniform random bit generator )
3
+ // X128PP.hh : xoshiro128++ (std::uniform_random_bit_generator )
4
4
//
5
- // Copyright (c) 2022 Brett Hale.
5
+ // Copyright (c) 2024 Brett Hale.
6
6
// SPDX-License-Identifier: BSD-2-Clause
7
7
//
8
8
// //////////////////////////////////////////////////////////////////////////////
16
16
#include < array>
17
17
18
18
#include < random>
19
- #include < limits>
20
-
21
- static_assert (__cplusplus >= 201703L ); // (C++17)
22
19
23
20
24
21
// //////////////////////////////////////////////////////////////////////////////
@@ -49,19 +46,19 @@ public:
49
46
static constexpr auto clamp (result_type u) {
50
47
return (u & result_max); }
51
48
52
- static constexpr auto rotl (result_type u, int k) {
53
- u = clamp (u); // idiomatic rotate:
54
- return clamp ((u << (k & 31 )) | (u >> (( - k) & 31 )) );
49
+ static constexpr auto rol (result_type u, unsigned k) {
50
+ u = clamp (u), k %= 32 ; // idiomatic rotate:
51
+ return (k) ? clamp ((u << k) | (u >> (32 - k))) : (u );
55
52
}
56
53
57
54
// xoshiro128++ generator function:
58
55
59
56
result_type operator () () noexcept {
60
- auto r = rotl (state[0 ] + state[3 ], (7 )) + state[0 ];
57
+ auto r = rol (state[0 ] + state[3 ], (7 )) + state[0 ];
61
58
auto t = clamp (state[1 ] << (9 ));
62
59
state[2 ] ^= state[0 ], state[3 ] ^= state[1 ];
63
60
state[1 ] ^= state[2 ], state[0 ] ^= state[3 ];
64
- state[2 ] ^= t, state[3 ] = rotl (state[3 ], (11 ));
61
+ state[2 ] ^= t, state[3 ] = rol (state[3 ], (11 ));
65
62
return clamp (r);
66
63
}
67
64
@@ -84,21 +81,28 @@ public:
84
81
return (u ^ (u >> 14 ));
85
82
}
86
83
87
- // (re)initialize the PRNG with a 32- bit seed:
84
+ // (re)initialize the PRNG with a 32 bit seed:
88
85
89
- constexpr X128PP (result_type s = 0 ) noexcept
90
- : state {} { seed (s ); }
86
+ constexpr X128PP (result_type seed = 0 ) noexcept
87
+ : state {} { init (seed ); }
91
88
92
- constexpr void seed (result_type s ) noexcept {
89
+ constexpr void init (result_type seed ) noexcept {
93
90
for (auto & si : state) // splitmix:
94
- si = mix (s = clamp (s + UINT32_C (0x9e3779b9 ) ));
91
+ si = mix (seed += UINT32_C (0x9e3779b9 ));
95
92
}
96
93
97
- // reinitialize the PRNG with a 128 bit state IV , generated
94
+ // (re)initialize the PRNG with a 128 bit state, generated
98
95
// using a std::random_device:
99
96
100
- void init (std::random_device &);
97
+ X128PP (std::random_device & rdev)
98
+ : state {} { init (rdev); }
101
99
100
+ void init (std::random_device & rdev) {
101
+ decltype (state) rbuf;
102
+ std::uniform_int_distribution<result_type> d {0 , max ()};
103
+ for (auto & ri : rbuf) ri = d (rdev);
104
+ state = rbuf;
105
+ }
102
106
};
103
107
104
108
@@ -165,40 +169,6 @@ X128PP::long_jump () noexcept
165
169
}
166
170
167
171
168
- // //////////////////////////////////////////////////////////////////////////////
169
- //
170
- // X128PP init function implementations:
171
-
172
-
173
- inline void
174
- X128PP::init (std::random_device & rdev)
175
- {
176
- decltype (state) rbuf;
177
-
178
- if (std::numeric_limits<decltype (rdev ())>::digits < (32 ))
179
- {
180
- for (auto & ri : rbuf)
181
- {
182
- auto lo = static_cast <result_type>(rdev ());
183
- auto hi = static_cast <result_type>(rdev ());
184
-
185
- ri = clamp ((hi << (16 )) | (lo & (0xffff )));
186
- }
187
- }
188
- else
189
- {
190
- for (auto & ri : rbuf)
191
- ri = clamp (static_cast <result_type>(rdev ()));
192
- }
193
-
194
- // note: it shouldn't be necessary to hash values generated
195
- // using a conforming std::random_device - furthermore, hash
196
- // functions are not bijective, excluding possible states.
197
-
198
- state = rbuf;
199
- }
200
-
201
-
202
172
// //////////////////////////////////////////////////////////////////////////////
203
173
204
174
0 commit comments