rippled
Loading...
Searching...
No Matches
include/xrpl/basics/random.h
1#ifndef XRPL_BASICS_RANDOM_H_INCLUDED
2#define XRPL_BASICS_RANDOM_H_INCLUDED
3
4#include <xrpl/beast/utility/instrumentation.h>
5#include <xrpl/beast/xor_shift_engine.h>
6
7#include <cstddef>
8#include <cstdint>
9#include <limits>
10#include <mutex>
11#include <random>
12#include <type_traits>
13
14namespace ripple {
15
16#ifndef __INTELLISENSE__
17static_assert(
20 "The Ripple default PRNG engine must return an unsigned integral type.");
21
22static_assert(
25 "The Ripple default PRNG engine return must be at least 64 bits wide.");
26#endif
27
28namespace detail {
29
30// Determines if a type can be called like an Engine
31template <class Engine, class Result = typename Engine::result_type>
33} // namespace detail
34
47{
48 // This is used to seed the thread-specific PRNGs on demand
49 static beast::xor_shift_engine seeder = [] {
52 return beast::xor_shift_engine(distribution(rng));
53 }();
54
55 // This protects the seeder
56 static std::mutex m;
57
58 // The thread-specific PRNGs:
59 thread_local beast::xor_shift_engine engine = [] {
60 std::uint64_t seed;
61 {
62 std::lock_guard lk(m);
64 seed = distribution(seeder);
65 }
66 return beast::xor_shift_engine{seed};
67 }();
68
69 return engine;
70}
71
92template <class Engine, class Integral>
94 std::is_integral<Integral>::value && detail::is_engine<Engine>::value,
95 Integral>
96rand_int(Engine& engine, Integral min, Integral max)
97{
98 XRPL_ASSERT(max > min, "ripple::rand_int : max over min inputs");
99
100 // This should have no state and constructing it should
101 // be very cheap. If that turns out not to be the case
102 // it could be hand-optimized.
103 return std::uniform_int_distribution<Integral>(min, max)(engine);
104}
105
106template <class Integral>
108rand_int(Integral min, Integral max)
109{
110 return rand_int(default_prng(), min, max);
111}
112
113template <class Engine, class Integral>
115 std::is_integral<Integral>::value && detail::is_engine<Engine>::value,
116 Integral>
117rand_int(Engine& engine, Integral max)
118{
119 return rand_int(engine, Integral(0), max);
120}
121
122template <class Integral>
124rand_int(Integral max)
125{
126 return rand_int(default_prng(), max);
127}
128
129template <class Integral, class Engine>
131 std::is_integral<Integral>::value && detail::is_engine<Engine>::value,
132 Integral>
133rand_int(Engine& engine)
134{
136}
137
138template <class Integral = int>
148template <class Byte, class Engine>
152 detail::is_engine<Engine>::value,
153 Byte>
154rand_byte(Engine& engine)
155{
156 return static_cast<Byte>(rand_int<Engine, std::uint32_t>(
157 engine,
160}
161
162template <class Byte = std::uint8_t>
166 Byte>
168{
169 return rand_byte<Byte>(default_prng());
170}
175template <class Engine>
176inline bool
177rand_bool(Engine& engine)
178{
179 return rand_int(engine, 1) == 1;
180}
181
182inline bool
184{
185 return rand_bool(default_prng());
186}
189} // namespace ripple
190
191#endif // XRPL_BASICS_RANDOM_H_INCLUDED
T is_same_v
T max(T... args)
detail::xor_shift_engine<> xor_shift_engine
XOR-shift Generator.
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:6
std::enable_if_t<(std::is_same< Byte, unsigned char >::value||std::is_same< Byte, std::uint8_t >::value), Byte > rand_byte()
std::enable_if_t< std::is_integral< Integral >::value, Integral > rand_int()
beast::xor_shift_engine & default_prng()
Return the default random engine.