xrpld
Loading...
Searching...
No Matches
include
xrpl
basics
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 <
cstdint
>
7
#include <
limits
>
8
#include <
mutex
>
9
#include <
random
>
10
#include <
type_traits
>
11
12
namespace
xrpl
{
13
14
#ifndef __INTELLISENSE__
15
static_assert
(
16
// NOLINTNEXTLINE(misc-redundant-expression)
17
std::is_integral_v<beast::xor_shift_engine::result_type>
&&
18
std::is_unsigned_v<beast::xor_shift_engine::result_type>
,
19
"The XRPL default PRNG engine must return an unsigned integral type."
);
20
21
static_assert
(
22
// NOLINTNEXTLINE(misc-redundant-expression)
23
std::numeric_limits<beast::xor_shift_engine::result_type>::max
() >=
24
std::numeric_limits<std::uint64_t>::max
(),
25
"The XRPL default PRNG engine return must be at least 64 bits wide."
);
26
#endif
27
28
namespace
detail
{
29
30
// Determines if a type can be called like an Engine
31
// NOLINTNEXTLINE(readability-redundant-typename): typename required by MSVC
32
template
<
class
Engine,
class
Result =
typename
Engine::result_type>
33
using
is_engine
=
std::is_invocable_r<Result, Engine>
;
34
}
// namespace detail
35
47
inline
beast::xor_shift_engine
&
48
defaultPrng
()
49
{
50
// This is used to seed the thread-specific PRNGs on demand
51
static
beast::xor_shift_engine
kSeeder = [] {
52
std::random_device
rng;
53
std::uniform_int_distribution<std::uint64_t>
distribution{1};
54
return
beast::xor_shift_engine
(distribution(rng));
55
}();
56
57
// This protects the seeder
58
static
std::mutex
kM;
59
60
// The thread-specific PRNGs:
61
thread_local
beast::xor_shift_engine
kEngine = [] {
62
std::uint64_t
seed = 0;
63
{
64
std::scoped_lock
const
lk(kM);
65
std::uniform_int_distribution<std::uint64_t>
distribution{1};
66
seed = distribution(kSeeder);
67
}
68
return
beast::xor_shift_engine
{seed};
69
}();
70
71
return
kEngine;
72
}
73
95
template
<
class
Engine,
class
Integral>
96
Integral
97
randInt
(Engine& engine, Integral min, Integral max)
98
requires
(
std::is_integral_v<Integral>
&&
detail::is_engine<Engine>::value
)
99
{
100
XRPL_ASSERT(max > min,
"xrpl::randInt : max over min inputs"
);
101
102
// This should have no state and constructing it should
103
// be very cheap. If that turns out not to be the case
104
// it could be hand-optimized.
105
return
std::uniform_int_distribution<Integral>
(min, max)(engine);
106
}
107
108
template
<
class
Integral>
109
Integral
110
randInt
(Integral min, Integral max)
111
requires
(
std::is_integral_v<Integral>
)
112
{
113
return
randInt
(
defaultPrng
(), min, max);
114
}
115
116
template
<
class
Engine,
class
Integral>
117
Integral
118
randInt
(Engine& engine, Integral max)
119
requires
(
std::is_integral_v<Integral>
&&
detail::is_engine<Engine>::value
)
120
{
121
return
randInt
(engine, Integral(0), max);
122
}
123
124
template
<
class
Integral>
125
Integral
126
randInt
(Integral max)
127
requires
(
std::is_integral_v<Integral>
)
128
{
129
return
randInt
(
defaultPrng
(), max);
130
}
131
132
template
<
class
Integral,
class
Engine>
133
Integral
134
randInt
(Engine& engine)
135
requires
(
std::is_integral_v<Integral>
&&
detail::is_engine<Engine>::value
)
136
{
137
return
randInt
(engine,
std::numeric_limits<Integral>::max
());
138
}
139
140
template
<
class
Integral =
int
>
141
Integral
142
randInt
()
143
requires
(
std::is_integral_v<Integral>
)
144
{
145
return
randInt
(
defaultPrng
(),
std::numeric_limits<Integral>::max
());
146
}
147
148
153
template
<
class
Byte,
class
Engine>
154
Byte
155
randByte
(Engine& engine)
156
requires
(
157
(
std::is_same_v<Byte, unsigned char>
||
std::is_same_v<Byte, std::uint8_t>
) &&
158
detail::is_engine<Engine>::value
)
159
{
160
return
static_cast<
Byte
>
(
randInt<Engine, std::uint32_t>
(
161
engine,
std::numeric_limits<Byte>::min
(),
std::numeric_limits<Byte>::max
()));
162
}
163
164
template
<
class
Byte = std::u
int
8_t>
165
Byte
166
randByte
()
167
requires
(
std::is_same_v<Byte, unsigned char>
||
std::is_same_v<Byte, std::uint8_t>
)
168
{
169
return
randByte<Byte>
(
defaultPrng
());
170
}
171
172
177
template
<
class
Engine>
178
inline
bool
179
randBool
(Engine& engine)
180
{
181
return
randInt
(engine, 1) == 1;
182
}
183
184
inline
bool
185
randBool
()
186
{
187
return
randBool
(
defaultPrng
());
188
}
189
190
191
}
// namespace xrpl
cstdint
std::uint64_t
std::is_integral_v
T is_integral_v
std::is_invocable_r
std::is_same_v
T is_same_v
std::is_unsigned_v
T is_unsigned_v
limits
std::numeric_limits::max
T max(T... args)
std::numeric_limits::min
T min(T... args)
mutex
beast::xor_shift_engine
detail::XorShiftEngine<> xor_shift_engine
XOR-shift Generator.
Definition
xor_shift_engine.h:97
xrpl::detail
Definition
base_uint.h:37
xrpl::detail::is_engine
std::is_invocable_r< Result, Engine > is_engine
Definition
include/xrpl/basics/random.h:33
xrpl
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition
algorithm.h:5
xrpl::randByte
Byte randByte()
Definition
include/xrpl/basics/random.h:166
xrpl::defaultPrng
beast::xor_shift_engine & defaultPrng()
Return the default random engine.
Definition
include/xrpl/basics/random.h:48
xrpl::randInt
Integral randInt()
Definition
include/xrpl/basics/random.h:142
xrpl::randBool
bool randBool()
Definition
include/xrpl/basics/random.h:185
std::random_device
random
std::scoped_lock
type_traits
std::uniform_int_distribution
Generated by
1.16.1