Arene Base
Fundamental Utilities For Safety Critical C++
Loading...
Searching...
No Matches
prng_xoshiro.hpp
Go to the documentation of this file.
1#ifndef INCLUDE_GUARD_ARENE_BASE_ARENE_BASE_TESTING_PRNG_XOSHIRO_HPP_
2#define INCLUDE_GUARD_ARENE_BASE_ARENE_BASE_TESTING_PRNG_XOSHIRO_HPP_
3
4#include "arene/base/array/array.hpp"
5#include "arene/base/stdlib_choice/cstdint.hpp"
6
7namespace arene {
8namespace base {
9namespace testing {
10
11/// @brief pseudorandom number generator implementing the xoshiro256++ algorithm
12///
13/// xoshiro256++ is a general-purpose PRNG designed by David Blackman and
14/// Sebastiano Vigna. It offers sub-nanosecond speed, a 256-bit state space
15/// large enough for parallel applications, and passes all known statistical
16/// test suites.
17///
18/// The generator satisfies the C++ UniformRandomBitGenerator named
19/// requirement, so it can be used with standard library distributions
20/// and algorithms that accept a URBG.
21///
22/// A single 64-bit seed is expanded into the full 256-bit internal state
23/// using the SplitMix64 generator, as recommended by the xoshiro authors.
24/// This ensures the state is never all-zero (the only disallowed state)
25/// for any seed value.
26///
27/// @see https://prng.di.unimi.it/
28/// @see https://prng.di.unimi.it/xoshiro256plusplus.c
30 /// @brief internal state of the generator
31 array<std::uint64_t, 4> state_{};
32
33 /// @brief bitwise rotate a value to the left
34 /// @tparam N number of bit positions to rotate
35 /// @param arg value to rotate.
36 /// @return rotated value
37 template <std::uint8_t N>
38 static constexpr auto rotate_left(std::uint64_t arg) -> std::uint64_t {
39 constexpr auto upper_limit = 64U;
40 static_assert(N < upper_limit, "rotation amount must be less than 64");
41
42 return N == 0U ? arg : ((arg << N) | (arg >> (upper_limit - N)));
43 }
44
45 /// @brief 64-bit PRNG used to expand a single seed into the four 64-bit state
46 /// words required by xoshiro256++
47 /// @see https://prng.di.unimi.it/splitmix64.c
48 struct splitmix64 {
49 /// @brief splimix64 state
50 std::uint64_t state{};
51
52 /// @brief advance the generator by one step and return the
53 /// scrambled output
54 /// @return next 64-bit pseudorandom value
55 constexpr auto next() noexcept -> std::uint64_t {
56 // fixed constants specified by the algorithm description
57 // NOLINTBEGIN(readability-magic-numbers)
58 auto mixed = (state += std::uint64_t{0x9e3779b97f4a7c15ULL});
59 mixed = (mixed ^ (mixed >> 30U)) * std::uint64_t{0xbf58476d1ce4e5b9ULL};
60 mixed = (mixed ^ (mixed >> 27U)) * std::uint64_t{0x94d049bb133111ebULL};
61 return mixed ^ (mixed >> 31U);
62 // NOLINTEND(readability-magic-numbers)
63 }
64 };
65
66 public:
67 /// @brief seed argument type
69
70 /// @brief prng result type
72
73 /// @brief construct the generator with an explicit seed
74 /// @param initial_seed initial seed value
75 constexpr explicit prng_xoshiro(seed_type initial_seed) noexcept {
76 auto seeder = splitmix64{initial_seed};
77 for (auto& state : state_) {
78 state = seeder.next();
79 }
80 }
81
82 /// @brief construct the generator with a seed of zero
83 constexpr prng_xoshiro() noexcept
85
86 /// @brief generate the next pseudorandom value and advance the
87 /// internal state
88 /// @return a uniformly distributed 64-bit pseudorandom value
89 /// in the range [min(), max()]
90 /// @see https://prng.di.unimi.it/xoshiro256plusplus.c
91 constexpr auto operator()() noexcept -> result_type {
92 // fixed constants specified by the algorithm description
93 // NOLINTBEGIN(readability-magic-numbers)
94 auto const result = rotate_left<23>(state_[0] + state_[3]) + state_[0];
95
96 auto const shifted = state_[1] << 17U;
97
98 state_[2] ^= state_[0];
99 state_[3] ^= state_[1];
100 state_[1] ^= state_[2];
101 state_[0] ^= state_[3];
102
103 state_[2] ^= shifted;
104
105 state_[3] = rotate_left<45>(state_[3]);
106 // NOLINTEND(readability-magic-numbers)
107
108 return result;
109 }
110
111 /// @brief smallest value that @c operator() can return
112 /// @return zero
113 static constexpr auto min() noexcept -> result_type { return {}; }
114
115 /// @brief largest value that @c operator() can return
116 /// @return ~min()
117 static constexpr auto max() noexcept -> result_type { return ~min(); }
118};
119
120} // namespace testing
121} // namespace base
122} // namespace arene
123#endif // INCLUDE_GUARD_ARENE_BASE_ARENE_BASE_TESTING_PRNG_XOSHIRO_HPP_
pseudorandom number generator implementing the xoshiro256++ algorithm
Definition prng_xoshiro.hpp:29
constexpr auto operator()() noexcept -> result_type
generate the next pseudorandom value and advance the internal state
Definition prng_xoshiro.hpp:91
static constexpr auto min() noexcept -> result_type
smallest value that operator() can return
Definition prng_xoshiro.hpp:113
constexpr prng_xoshiro() noexcept
construct the generator with a seed of zero
Definition prng_xoshiro.hpp:83
static constexpr auto max() noexcept -> result_type
largest value that operator() can return
Definition prng_xoshiro.hpp:117
constexpr prng_xoshiro(seed_type initial_seed) noexcept
construct the generator with an explicit seed
Definition prng_xoshiro.hpp:75
Definition customization.hpp:36
Definition array_exceptions_disabled.cpp:11
Copyright 2026, Toyota Motor Corporation.
Definition array_exceptions_disabled.cpp:10