FEAT 3
Finite Element Analysis Toolbox
Loading...
Searching...
No Matches
random.hpp
1// FEAT3: Finite Element Analysis Toolbox, Version 3
2// Copyright (C) 2010 by Stefan Turek & the FEAT group
3// FEAT3 is released under the GNU General Public License version 3,
4// see the file 'copyright.txt' in the top level directory for details.
5
6#pragma once
7
8// includes, FEAT
10#include <kernel/util/type_traits.hpp>
11
12// includes, system
13#include <algorithm>
14#include <limits>
15#include <cstdint>
16#include <chrono>
17
18namespace FEAT
19{
21 namespace Intern
22 {
23 // Random number class; this class's gen() function takes a Random object reference and
24 // uses its next() function to generate a random number of the specified type T_.
25 template<typename T_, typename TypeClass_ = typename Type::Traits<T_>::TypeClass>
26 class RandomNumber;
27 } // namespace Intern
29
53 class Random
54 {
55 public:
57 typedef std::uint64_t SeedType;
58
60 static constexpr SeedType xor_mult = SeedType(2685821657736338717ull);
61
62 private:
64 std::uint64_t _seed;
66 std::uint64_t _x;
67
68 public:
72 explicit Random() :
73 _seed(0),
74 _x(0)
75 {
76 // use the high-resolution clock from the standard library go get the epoch time in nanoseconds as the seed
77 auto now = std::chrono::high_resolution_clock::now();
78 _seed = _x = std::chrono::duration_cast<std::chrono::duration<SeedType, std::nano>>(now.time_since_epoch()).count() + SeedType(17u);
79 }
80
87 explicit Random(SeedType seed) :
88 _seed(seed),
89 _x(seed)
90 {
91 XASSERTM(seed != SeedType(0), "Random seed must not be zero!");
92 }
93
96 {
97 return _seed;
98 }
99
106 uint64_t next()
107 {
108 _x ^= _x >> 12;
109 _x ^= _x << 25;
110 _x ^= _x >> 27;
111 return _x * xor_mult;
112 }
113
132 template<typename T_>
134 {
135 x = FEAT::Intern::RandomNumber<T_>::gen(*this);
136 return *this;
137 }
138
156 template<typename T_>
157 T_ operator()(T_ a, T_ b)
158 {
159 return FEAT::Intern::RandomNumber<T_>::gen_ranged(*this, std::min(a, b), std::max(a, b));
160 }
161 }; // class Random
162
164 namespace Intern
165 {
166 // Random integer class; this class is the base class for the integer specialization
167 // of the RandomNumber class defined below.
168 template<typename T_, size_t num_bytes_ = sizeof(T_)>
169 class RandomInteger;
170
171 // Helper class: return non-negative integer
172 template<typename T_, bool signed_ = (Type::Traits<T_>::is_signed)>
173 class NonNegInt
174 {
175 public:
176 static T_ make(T_ x)
177 {
178 return x;
179 }
180 };
181
182 // specialization for signed integer types
183 template<typename T_>
184 class NonNegInt<T_, true>
185 {
186 public:
187 static T_ make(T_ x)
188 {
189 return (x < T_(0) ? T_(-(x + T_(1))) : x);
190 }
191 };
192
193 // specialization for 8-bit integers
194 template<typename T_>
195 class RandomInteger<T_, 1>
196 {
197 public:
198 static T_ gen(Random& rng)
199 {
200 return (T_)(rng.next() & 0xFFu);
201 }
202 };
203
204 // specialization for 16-bit integers
205 template<typename T_>
206 class RandomInteger<T_, 2>
207 {
208 public:
209 static T_ gen(Random& rng)
210 {
211 return (T_)(rng.next() & 0xFFFFu);
212 }
213 };
214
215 // specialization for 32-bit integers
216 template<typename T_>
217 class RandomInteger<T_, 4>
218 {
219 public:
220 static T_ gen(Random& rng)
221 {
222 return (T_)(rng.next() & 0xFFFFFFFFu);
223 }
224 };
225
226 // specialization for 64-bit integers
227 template<typename T_>
228 class RandomInteger<T_, 8>
229 {
230 public:
231 static T_ gen(Random& rng)
232 {
233 return (T_)(rng.next());
234 }
235 };
236
237 // specialization for integers
238 template<typename T_>
239 class RandomNumber<T_, Type::IntegralClass> :
240 public RandomInteger<T_>
241 {
242 public:
243 static T_ gen_ranged(Random& rng, T_ a, T_ b)
244 {
245 // call gen() prior to the if-clause to advance the rng in any case
246 // also, ensure that the value is non-negative
247 T_ x = NonNegInt<T_>::make(RandomInteger<T_>::gen(rng));
248 if(a < b)
249 // Note: The following casting orgy is necessary on some compilers if the type 'T_' is
250 // actually shorter than 'int', as the arithmetic operations return values of type 'int'
251 // in this case.
252 return T_(a + T_(x % T_(T_(b - a) + T_(1))));
253 else
254 return a;
255 }
256 };
257
258 // specialization for floating point numbers
259 template<typename T_>
260 class RandomNumber<T_, Type::FloatingClass>
261 {
262 public:
263 static T_ gen(Random& rng)
264 {
265 static constexpr std::uint64_t mask = std::uint64_t(0xFFFFFFFFull);
266 const double d = 1.0 / double(mask);
267 return T_(double(rng.next() & mask) * d);
268 }
269
270 static T_ gen_ranged(Random& rng, T_ a, T_ b)
271 {
272 // machine exactness; we do not want to divide by anything smaller than that...
273 static const T_ eps = std::numeric_limits<T_>::epsilon();
274
275 // call gen() prior to the if-clause to advance the rng in any case
276 T_ x(gen(rng));
277 if(a + eps < b)
278 return a + x * (b - a);
279 else
280 return a;
281 }
282 };
283
284 // specialization for bool
285 template<typename T_>
286 class RandomNumber<T_, Type::BooleanClass>
287 {
288 public:
289 static T_ gen(Random& rng)
290 {
291 return T_(int(rng.next() & 0x8ull) != 0);
292 }
293
294 static T_ gen_ranged(Random& rng, T_ a, T_ b)
295 {
296 // call gen() prior to the if-clause to advance the rng in any case
297 T_ x(gen(rng));
298 // The following case may look pointless for bool, but if a and b are equal
299 // we want to return that value here - otherwise its either true or false.
300 if(a != b)
301 return x;
302 else
303 return a;
304 }
305 };
306 } // namespace Intern
308} // namespace FEAT
#define XASSERTM(expr, msg)
Assertion macro definition with custom message.
Definition: assertion.hpp:263
Pseudo-Random Number Generator.
Definition: random.hpp:54
T_ operator()(T_ a, T_ b)
Ranged evaluation operator.
Definition: random.hpp:157
uint64_t next()
Returns the next number in the stream.
Definition: random.hpp:106
std::uint64_t _seed
the rng's original seed
Definition: random.hpp:64
std::uint64_t SeedType
seed type
Definition: random.hpp:57
Random(SeedType seed)
Constructor.
Definition: random.hpp:87
std::uint64_t _x
the rng's working values
Definition: random.hpp:66
Random & operator>>(T_ &x)
Extraction operator.
Definition: random.hpp:133
SeedType get_seed() const
Definition: random.hpp:95
static constexpr SeedType xor_mult
internal multiplier
Definition: random.hpp:60
Random()
Default constructor that seeds the RNG with the current high-resolution clock time.
Definition: random.hpp:72
T_ eps()
Returns the machine precision constant for a floating-point data type.
Definition: math.hpp:787
Type
bitmask for zfp header
Definition: pack.hpp:81
FEAT namespace.
Definition: adjactor.hpp:12