rippled
Loading...
Searching...
No Matches
include/xrpl/basics/random.h
1//------------------------------------------------------------------------------
2/*
3 This file is part of rippled: https://github.com/ripple/rippled
4 Copyright (c) 2012, 2013 Ripple Labs Inc.
5
6 Permission to use, copy, modify, and/or distribute this software for any
7 purpose with or without fee is hereby granted, provided that the above
8 copyright notice and this permission notice appear in all copies.
9
10 THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17*/
18//==============================================================================
19
20#ifndef RIPPLE_BASICS_RANDOM_H_INCLUDED
21#define RIPPLE_BASICS_RANDOM_H_INCLUDED
22
23#include <xrpl/beast/utility/instrumentation.h>
24#include <xrpl/beast/xor_shift_engine.h>
25
26#include <cstddef>
27#include <cstdint>
28#include <limits>
29#include <mutex>
30#include <random>
31#include <type_traits>
32
33namespace ripple {
34
35#ifndef __INTELLISENSE__
36static_assert(
39 "The Ripple default PRNG engine must return an unsigned integral type.");
40
41static_assert(
44 "The Ripple default PRNG engine return must be at least 64 bits wide.");
45#endif
46
47namespace detail {
48
49// Determines if a type can be called like an Engine
50template <class Engine, class Result = typename Engine::result_type>
52} // namespace detail
53
66{
67 // This is used to seed the thread-specific PRNGs on demand
68 static beast::xor_shift_engine seeder = [] {
71 return beast::xor_shift_engine(distribution(rng));
72 }();
73
74 // This protects the seeder
75 static std::mutex m;
76
77 // The thread-specific PRNGs:
78 thread_local beast::xor_shift_engine engine = [] {
79 std::uint64_t seed;
80 {
81 std::lock_guard lk(m);
83 seed = distribution(seeder);
84 }
85 return beast::xor_shift_engine{seed};
86 }();
87
88 return engine;
89}
90
111template <class Engine, class Integral>
113 std::is_integral<Integral>::value && detail::is_engine<Engine>::value,
114 Integral>
115rand_int(Engine& engine, Integral min, Integral max)
116{
117 XRPL_ASSERT(max > min, "ripple::rand_int : max over min inputs");
118
119 // This should have no state and constructing it should
120 // be very cheap. If that turns out not to be the case
121 // it could be hand-optimized.
122 return std::uniform_int_distribution<Integral>(min, max)(engine);
123}
124
125template <class Integral>
127rand_int(Integral min, Integral max)
128{
129 return rand_int(default_prng(), min, max);
130}
131
132template <class Engine, class Integral>
134 std::is_integral<Integral>::value && detail::is_engine<Engine>::value,
135 Integral>
136rand_int(Engine& engine, Integral max)
137{
138 return rand_int(engine, Integral(0), max);
139}
140
141template <class Integral>
143rand_int(Integral max)
144{
145 return rand_int(default_prng(), max);
146}
147
148template <class Integral, class Engine>
150 std::is_integral<Integral>::value && detail::is_engine<Engine>::value,
151 Integral>
152rand_int(Engine& engine)
153{
155}
156
157template <class Integral = int>
167template <class Byte, class Engine>
171 detail::is_engine<Engine>::value,
172 Byte>
173rand_byte(Engine& engine)
174{
175 return static_cast<Byte>(rand_int<Engine, std::uint32_t>(
176 engine,
179}
180
181template <class Byte = std::uint8_t>
185 Byte>
187{
188 return rand_byte<Byte>(default_prng());
189}
194template <class Engine>
195inline bool
196rand_bool(Engine& engine)
197{
198 return rand_int(engine, 1) == 1;
199}
200
201inline bool
203{
204 return rand_bool(default_prng());
205}
208} // namespace ripple
209
210#endif // RIPPLE_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:25
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.