rippled
ripple/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 <ripple/beast/xor_shift_engine.h>
24 #include <cassert>
25 #include <cstddef>
26 #include <cstdint>
27 #include <cstring>
28 #include <limits>
29 #include <mutex>
30 #include <random>
31 #include <type_traits>
32 
33 namespace ripple {
34 
35 #ifndef __INTELLISENSE__
36 static_assert(
39  "The Ripple default PRNG engine must return an unsigned integral type.");
40 
41 static_assert(
44  "The Ripple default PRNG engine return must be at least 64 bits wide.");
45 #endif
46 
47 namespace detail {
48 
49 // Determines if a type can be called like an Engine
50 template <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 
111 template <class Engine, class Integral>
113  std::is_integral<Integral>::value && detail::is_engine<Engine>::value,
114  Integral>
115 rand_int(Engine& engine, Integral min, Integral max)
116 {
117  assert(max > min);
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 
125 template <class Integral>
127 rand_int(Integral min, Integral max)
128 {
129  return rand_int(default_prng(), min, max);
130 }
131 
132 template <class Engine, class Integral>
134  std::is_integral<Integral>::value && detail::is_engine<Engine>::value,
135  Integral>
136 rand_int(Engine& engine, Integral max)
137 {
138  return rand_int(engine, Integral(0), max);
139 }
140 
141 template <class Integral>
143 rand_int(Integral max)
144 {
145  return rand_int(default_prng(), max);
146 }
147 
148 template <class Integral, class Engine>
150  std::is_integral<Integral>::value && detail::is_engine<Engine>::value,
151  Integral>
152 rand_int(Engine& engine)
153 {
155 }
156 
157 template <class Integral = int>
160 {
162 }
167 template <class Byte, class Engine>
171  detail::is_engine<Engine>::value,
172  Byte>
173 rand_byte(Engine& engine)
174 {
175  return static_cast<Byte>(rand_int<Engine, std::uint32_t>(
176  engine,
179 }
180 
181 template <class Byte = std::uint8_t>
185  Byte>
187 {
188  return rand_byte<Byte>(default_prng());
189 }
194 template <class Engine>
195 inline bool
196 rand_bool(Engine& engine)
197 {
198  return rand_int(engine, 1) == 1;
199 }
200 
201 inline bool
203 {
204  return rand_bool(default_prng());
205 }
208 } // namespace ripple
209 
210 #endif // RIPPLE_BASICS_RANDOM_H_INCLUDED
std::is_same
beast::xor_shift_engine
detail::xor_shift_engine<> xor_shift_engine
XOR-shift Generator.
Definition: xor_shift_engine.h:114
std::is_unsigned
std::uniform_int_distribution
cstring
random
std::lock_guard
STL class.
ripple::rand_int
std::enable_if_t< std::is_integral< Integral >::value &&detail::is_engine< Engine >::value, Integral > rand_int(Engine &engine, Integral min, Integral max)
Return a uniformly distributed random integer.
Definition: ripple/basics/random.h:115
std::random_device
std::enable_if_t
cstddef
ripple::rand_byte
std::enable_if_t<(std::is_same< Byte, unsigned char >::value||std::is_same< Byte, std::uint8_t >::value) &&detail::is_engine< Engine >::value, Byte > rand_byte(Engine &engine)
Return a random byte.
Definition: ripple/basics/random.h:173
ripple::default_prng
beast::xor_shift_engine & default_prng()
Return the default random engine.
Definition: ripple/basics/random.h:65
cstdint
std::is_invocable_r
std::uint64_t
std::is_integral
ripple
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition: RCLCensorshipDetector.h:29
limits
cassert
mutex
beast::detail::xor_shift_engine
Definition: xor_shift_engine.h:32
ripple::rand_bool
bool rand_bool(Engine &engine)
Return a random boolean value.
Definition: ripple/basics/random.h:196
std::numeric_limits
type_traits