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(
17 // NOLINTNEXTLINE(misc-redundant-expression)
20 "The Ripple default PRNG engine must return an unsigned integral type.");
21
22static_assert(
23 // NOLINTNEXTLINE(misc-redundant-expression)
26 "The Ripple default PRNG engine return must be at least 64 bits wide.");
27#endif
28
29namespace detail {
30
31// Determines if a type can be called like an Engine
32template <class Engine, class Result = typename Engine::result_type>
34} // namespace detail
35
48{
49 // This is used to seed the thread-specific PRNGs on demand
50 static beast::xor_shift_engine seeder = [] {
53 return beast::xor_shift_engine(distribution(rng));
54 }();
55
56 // This protects the seeder
57 static std::mutex m;
58
59 // The thread-specific PRNGs:
60 thread_local beast::xor_shift_engine engine = [] {
61 std::uint64_t seed = 0;
62 {
63 std::lock_guard const lk(m);
65 seed = distribution(seeder);
66 }
67 return beast::xor_shift_engine{seed};
68 }();
69
70 return engine;
71}
72
93template <class Engine, class Integral>
94std::enable_if_t<std::is_integral<Integral>::value && detail::is_engine<Engine>::value, Integral>
95rand_int(Engine& engine, Integral min, Integral max)
96{
97 XRPL_ASSERT(max > min, "xrpl::rand_int : max over min inputs");
98
99 // This should have no state and constructing it should
100 // be very cheap. If that turns out not to be the case
101 // it could be hand-optimized.
102 return std::uniform_int_distribution<Integral>(min, max)(engine);
103}
104
105template <class Integral>
107rand_int(Integral min, Integral max)
108{
109 return rand_int(default_prng(), min, max);
110}
111
112template <class Engine, class Integral>
113std::enable_if_t<std::is_integral<Integral>::value && detail::is_engine<Engine>::value, Integral>
114rand_int(Engine& engine, Integral max)
115{
116 return rand_int(engine, Integral(0), max);
117}
118
119template <class Integral>
121rand_int(Integral max)
122{
123 return rand_int(default_prng(), max);
124}
125
126template <class Integral, class Engine>
127std::enable_if_t<std::is_integral<Integral>::value && detail::is_engine<Engine>::value, Integral>
128rand_int(Engine& engine)
129{
131}
132
133template <class Integral = int>
143template <class Byte, class Engine>
146 detail::is_engine<Engine>::value,
147 Byte>
148rand_byte(Engine& engine)
149{
150 return static_cast<Byte>(rand_int<Engine, std::uint32_t>(
152}
153
154template <class Byte = std::uint8_t>
157 Byte>
159{
160 return rand_byte<Byte>(default_prng());
161}
166template <class Engine>
167inline bool
168rand_bool(Engine& engine)
169{
170 return rand_int(engine, 1) == 1;
171}
172
173inline bool
175{
176 return rand_bool(default_prng());
177}
180} // 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.