Skip to content

Commit ed8fe6c

Browse files
authored
Add files via upload
1 parent 9632a8f commit ed8fe6c

File tree

1 file changed

+180
-0
lines changed

1 file changed

+180
-0
lines changed

X256PP.hh

+180
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,180 @@
1+
////////////////////////////////////////////////////////////////////////////////
2+
//
3+
// X256PP.hh : xoshiro256++ (std::uniform_random_bit_generator)
4+
//
5+
// Copyright (c) 2024 Brett Hale.
6+
// SPDX-License-Identifier: BSD-2-Clause
7+
//
8+
////////////////////////////////////////////////////////////////////////////////
9+
10+
11+
#ifndef X256PP_HH_
12+
#define X256PP_HH_
13+
14+
15+
#include <cstdint>
16+
#include <array>
17+
18+
#include <random>
19+
20+
21+
////////////////////////////////////////////////////////////////////////////////
22+
//
23+
// X256PP class:
24+
25+
26+
class X256PP
27+
{
28+
public:
29+
30+
// xoshiro256++ PRNG (satisfies: UniformRandomBitGenerator)
31+
32+
// based on the 'xoshiro256plusplus.c' implementation by
33+
// David Blackman and Sebastiano Vigna: prng.di.unimi.it
34+
35+
using result_type = std::uint_fast64_t;
36+
37+
static constexpr result_type result_max =
38+
static_cast<result_type>(UINT64_C(0xffffffffffffffff));
39+
40+
static constexpr result_type min () { return (0); }
41+
static constexpr result_type max () { return result_max; }
42+
43+
44+
std::array<result_type, 4> state; // (256 bits)
45+
46+
static constexpr auto clamp (result_type u) {
47+
return (u & result_max); }
48+
49+
static constexpr auto rol (result_type u, unsigned k) {
50+
u = clamp(u), k %= 64; // idiomatic rotate:
51+
return (k) ? clamp((u << k) | (u >> (64 - k))) : (u);
52+
}
53+
54+
// xoshiro256++ generator function:
55+
56+
result_type operator () () noexcept {
57+
auto r = rol(state[0] + state[3], (23)) + state[0];
58+
auto t = clamp(state[1] << (17));
59+
state[2] ^= state[0], state[3] ^= state[1];
60+
state[1] ^= state[2], state[0] ^= state[3];
61+
state[2] ^= t, state[3] = rol(state[3], (45));
62+
return clamp(r);
63+
}
64+
65+
// equivalent to (2^128) calls to generator:
66+
67+
constexpr void jump () noexcept;
68+
69+
// equivalent to (2^192) calls to generator:
70+
71+
constexpr void long_jump () noexcept;
72+
73+
74+
// Stafford's Mix13 variant:
75+
76+
static constexpr auto mix (result_type u) {
77+
u = clamp(u); u ^= (u >> 30);
78+
u *= UINT64_C(0xbf58476d1ce4e5b9);
79+
u = clamp(u); u ^= (u >> 27);
80+
u *= UINT64_C(0x94d049bb133111eb);
81+
u = clamp(u); u ^= (u >> 31);
82+
return u;
83+
}
84+
85+
// (re)initialize the PRNG with a 64 bit seed:
86+
87+
constexpr X256PP (result_type seed = 0) noexcept
88+
: state {} { init(seed); }
89+
90+
constexpr void init (result_type seed) noexcept {
91+
for (auto & si : state) // splitmix:
92+
si = mix(seed += UINT64_C(0x9e3779b97f4a7c15));
93+
}
94+
95+
// (re)initialize the PRNG with a 256 bit state, generated
96+
// using a std::random_device:
97+
98+
X256PP (std::random_device & rdev)
99+
: state {} { init(rdev); }
100+
101+
void init (std::random_device & rdev) {
102+
decltype(state) rbuf;
103+
std::uniform_int_distribution<result_type> d {0, max()};
104+
for (auto & ri : rbuf) ri = d(rdev);
105+
state = rbuf;
106+
}
107+
};
108+
109+
110+
////////////////////////////////////////////////////////////////////////////////
111+
//
112+
// X256PP jump function implementations:
113+
114+
115+
constexpr auto
116+
jump (const X256PP & prng) noexcept
117+
{
118+
auto jrng {prng}; jrng.jump(); return jrng;
119+
}
120+
121+
122+
constexpr void
123+
X256PP::jump () noexcept
124+
{
125+
decltype(state) jbuf {};
126+
127+
constexpr decltype(state) jtab {
128+
UINT64_C(0x180ec6d33cfd0aba), UINT64_C(0xd5a61266f0c9392c),
129+
UINT64_C(0xa9582618e03fc9aa), UINT64_C(0x39abdc4529b1661c)
130+
};
131+
132+
for (auto j : jtab)
133+
{
134+
for (int b = 0; b < (64); operator () (), b++)
135+
{
136+
if (j & (UINT64_C(1) << b))
137+
for (unsigned int i = 0; i < jbuf.size(); i++)
138+
jbuf[i] ^= state[i];
139+
}
140+
}
141+
142+
state = jbuf;
143+
}
144+
145+
146+
constexpr auto
147+
long_jump (const X256PP & prng) noexcept
148+
{
149+
auto jrng {prng}; jrng.long_jump(); return jrng;
150+
}
151+
152+
153+
constexpr void
154+
X256PP::long_jump () noexcept
155+
{
156+
decltype(state) jbuf {};
157+
158+
constexpr decltype(state) jtab {
159+
UINT64_C(0x76e15d3efefdcbbf), UINT64_C(0xc5004e441c522fb3),
160+
UINT64_C(0x77710069854ee241), UINT64_C(0x39109bb02acbe635)
161+
};
162+
163+
for (auto j : jtab)
164+
{
165+
for (int b = 0; b < (64); operator () (), b++)
166+
{
167+
if (j & (UINT64_C(1) << b))
168+
for (unsigned int i = 0; i < jbuf.size(); i++)
169+
jbuf[i] ^= state[i];
170+
}
171+
}
172+
173+
state = jbuf;
174+
}
175+
176+
177+
////////////////////////////////////////////////////////////////////////////////
178+
179+
180+
#endif // X256PP_HH_

0 commit comments

Comments
 (0)