rippled
Loading...
Searching...
No Matches
include/xrpl/basics/random.h
1#pragma once
2
3#include <xrpl/beast/utility/instrumentation.h>
4#include <xrpl/beast/xor_shift_engine.h>
5
6#include <cstddef>
7#include <cstdint>
8#include <limits>
9#include <mutex>
10#include <random>
11#include <type_traits>
12
13namespace xrpl {
14
15#ifndef __INTELLISENSE__
16static_assert(
19 "The Ripple default PRNG engine must return an unsigned integral type.");
20
21static_assert(
23 "The Ripple default PRNG engine return must be at least 64 bits wide.");
24#endif
25
26namespace detail {
27
28// Determines if a type can be called like an Engine
29template <class Engine, class Result = typename Engine::result_type>
31} // namespace detail
32
45{
46 // This is used to seed the thread-specific PRNGs on demand
47 static beast::xor_shift_engine seeder = [] {
50 return beast::xor_shift_engine(distribution(rng));
51 }();
52
53 // This protects the seeder
54 static std::mutex m;
55
56 // The thread-specific PRNGs:
57 thread_local beast::xor_shift_engine engine = [] {
58 std::uint64_t seed;
59 {
60 std::lock_guard lk(m);
62 seed = distribution(seeder);
63 }
64 return beast::xor_shift_engine{seed};
65 }();
66
67 return engine;
68}
69
90template <class Engine, class Integral>
91std::enable_if_t<std::is_integral<Integral>::value && detail::is_engine<Engine>::value, Integral>
92rand_int(Engine& engine, Integral min, Integral max)
93{
94 XRPL_ASSERT(max > min, "xrpl::rand_int : max over min inputs");
95
96 // This should have no state and constructing it should
97 // be very cheap. If that turns out not to be the case
98 // it could be hand-optimized.
99 return std::uniform_int_distribution<Integral>(min, max)(engine);
100}
101
102template <class Integral>
104rand_int(Integral min, Integral max)
105{
106 return rand_int(default_prng(), min, max);
107}
108
109template <class Engine, class Integral>
110std::enable_if_t<std::is_integral<Integral>::value && detail::is_engine<Engine>::value, Integral>
111rand_int(Engine& engine, Integral max)
112{
113 return rand_int(engine, Integral(0), max);
114}
115
116template <class Integral>
118rand_int(Integral max)
119{
120 return rand_int(default_prng(), max);
121}
122
123template <class Integral, class Engine>
124std::enable_if_t<std::is_integral<Integral>::value && detail::is_engine<Engine>::value, Integral>
125rand_int(Engine& engine)
126{
128}
129
130template <class Integral = int>
140template <class Byte, class Engine>
143 detail::is_engine<Engine>::value,
144 Byte>
145rand_byte(Engine& engine)
146{
147 return static_cast<Byte>(
148 rand_int<Engine, std::uint32_t>(engine, std::numeric_limits<Byte>::min(), std::numeric_limits<Byte>::max()));
149}
150
151template <class Byte = std::uint8_t>
154{
155 return rand_byte<Byte>(default_prng());
156}
161template <class Engine>
162inline bool
163rand_bool(Engine& engine)
164{
165 return rand_int(engine, 1) == 1;
166}
167
168inline bool
170{
171 return rand_bool(default_prng());
172}
175} // namespace xrpl
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:5
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.