Ocean
RandomGenerator.h
Go to the documentation of this file.
1 /*
2  * Copyright (c) Meta Platforms, Inc. and affiliates.
3  *
4  * This source code is licensed under the MIT license found in the
5  * LICENSE file in the root directory of this source tree.
6  */
7 
8 #ifndef META_OCEAN_BASE_RANDOM_GENERATOR_H
9 #define META_OCEAN_BASE_RANDOM_GENERATOR_H
10 
11 #include "ocean/base/Base.h"
12 #include "ocean/base/Lock.h"
13 
14 #include <cstdlib>
15 
16 namespace Ocean
17 {
18 
19 /**
20  * This class implements a generator for random numbers.
21  * A random generator object can be used to improve the performance of code (needing random numbers) which is applied on several CPU cores in parallel.<br>
22  * The default random number functions of the standard library are thread-safe but may apply expensive locks to synchronize the individual seed parameters of the individual threads.<br>
23  * Therefore, this class can be used to improve the code performance significantly in multi-threaded environments.<br>
24  * The following code example shows the correct application of this class for multi-core functions (which can be invoked e.g., by the Worker class):<br>
25  * @code
26  * void multiCoreFunction(RandomGenerator& randomGenerator, unsigned int* data, unsigned int firstObject, unsigned int numberObjects)
27  * {
28  * /// create a local random generator object which uses the function's random generator to create a new seed value
29  * RandomGenerator localRandomGenerator(randomGenerator);
30  *
31  * for (unsigned int n = firstObject; n <= firstObject + numberObjects; ++n)
32  * {
33  * /// we create random values and use the local random generator (not the function's random generator)
34  * data[n] = RandomI::random(localRandomGenerator, 100u);
35  * }
36  * }
37  * @endcode
38  * @see RandomI, Worker.
39  * @ingroup base
40  */
41 class OCEAN_BASE_EXPORT RandomGenerator
42 {
43  public:
44 
45  /**
46  * Creates a new random generator and initializes the internal parameter with the random value of the standard random function.
47  * Ensure that RandomI::initialize() has been called before using this constructor.
48  * @see RandomI::initialize().
49  */
51 
52  /**
53  * Creates a new random generator and initializes the internal parameter by a random value provided by the locked random function of the given generator.
54  * @param generator Random number generator used for initialization, the generator's seed will be changed during the initialization
55  */
56  explicit inline RandomGenerator(RandomGenerator& generator);
57 
58  /**
59  * Creates a new random generator and optional initializes the internal parameter by a random value provided by the locked random function of the given generator, if no generator is provided the standard random function will be used for initialization.
60  * @param optionalGenerator The random number generator used for initialization (the generator's seed will be changed during the initialization), nullptr to use the standard random function for initialization
61  */
62  explicit RandomGenerator(RandomGenerator* optionalGenerator);
63 
64  /**
65  * Move constructor.
66  * @param randomGenerator The random generator object to be moved
67  */
68  inline RandomGenerator(RandomGenerator&& randomGenerator);
69 
70  /**
71  * Creates a new random generator and initializes the internal parameter by the given value.
72  * @param seed The seed initialization value, with range [0, infinity)
73  */
74  explicit inline RandomGenerator(const unsigned int seed);
75 
76  /**
77  * Returns the next random number.
78  * Beware: This function is not thread safe.
79  * @return Random number with range [0, 32767]
80  * @see lockedRand().
81  */
82  inline unsigned int rand();
83 
84  /**
85  * Returns the next random number.
86  * This function is thread safe.
87  * @return Random number with range [0, 32767]
88  * @see rand().
89  */
90  inline unsigned int lockedRand();
91 
92  /**
93  * Returns the current seed value of this object.
94  * This seed value changes whenever a new random number is generated.
95  * @return Current seed value
96  */
97  inline unsigned int seed() const;
98 
99  /**
100  * Returns the initial seed value which was used to initialize this random generator.
101  * The initial seed value will not change during the lifetime of the generator.
102  * @return The random generator's initial seed value
103  */
104  inline unsigned int initialSeed() const;
105 
106  /**
107  * Move operator.
108  * @param randomGenerator The random generator object to be moved
109  * @return Reference to this object
110  */
112 
113  /**
114  * Returns the maximal random value of this generator.
115  * @return Maximal random value of this generator
116  */
117  static constexpr unsigned int randMax();
118 
119  private:
120 
121  /**
122  * Returns a seed value based on the current time, the thread id, and a random value from RandomI.
123  * @return The combined seed value
124  */
125  static unsigned int threadAndTimeBasedSeed();
126 
127  private:
128 
129  /// The seed value which was used to initialize this random generator.
130  unsigned int initialSeed_ = (unsigned int)(-1);
131 
132  /// Internal seed parameter used for random number generation, changes whenever a new random number is generated.
133  unsigned int seed_ = (unsigned int)(-1);
134 
135  /// Generator lock.
137 };
138 
140 {
141  const unsigned int seedLow = generator.lockedRand() & 0xFFFFu;
142  const unsigned int seedHigh = (generator.lockedRand() & 0xFFFFu) << 16u;
143 
144  initialSeed_ = seedLow | seedHigh;
145 
146  // doing first randomization step
147  seed_ = initialSeed_ * 214013L + 2531011L;
148 }
149 
150 inline RandomGenerator::RandomGenerator(const unsigned int seed) :
151  initialSeed_(seed)
152 {
154 }
155 
157 {
158  *this = std::move(randomGenerator);
159 }
160 
161 inline unsigned int RandomGenerator::rand()
162 {
163  return (unsigned int)(((seed_ = seed_ * 214013L + 2531011L) >> 16) & 0x7fff);
164 }
165 
166 inline unsigned int RandomGenerator::lockedRand()
167 {
168  const ScopedLock scopedLock(lock_);
169 
170  return (unsigned int)(((seed_ = seed_ * 214013L + 2531011L) >> 16) & 0x7fff);
171 }
172 
173 inline unsigned int RandomGenerator::seed() const
174 {
175  return seed_;
176 }
177 
178 inline unsigned int RandomGenerator::initialSeed() const
179 {
180  return initialSeed_;
181 }
182 
183 constexpr unsigned int RandomGenerator::randMax()
184 {
185  return 0x7fffu;
186 }
187 
188 }
189 
190 #endif // META_OCEAN_BASE_RANDOM_GENERATOR_H
This class implements a recursive lock object.
Definition: Lock.h:31
This class implements a generator for random numbers.
Definition: RandomGenerator.h:42
Lock lock_
Generator lock.
Definition: RandomGenerator.h:136
static unsigned int threadAndTimeBasedSeed()
Returns a seed value based on the current time, the thread id, and a random value from RandomI.
unsigned int lockedRand()
Returns the next random number.
Definition: RandomGenerator.h:166
unsigned int rand()
Returns the next random number.
Definition: RandomGenerator.h:161
static constexpr unsigned int randMax()
Returns the maximal random value of this generator.
Definition: RandomGenerator.h:183
unsigned int initialSeed_
The seed value which was used to initialize this random generator.
Definition: RandomGenerator.h:130
unsigned int seed() const
Returns the current seed value of this object.
Definition: RandomGenerator.h:173
RandomGenerator & operator=(RandomGenerator &&randomGenerator)
Move operator.
unsigned int initialSeed() const
Returns the initial seed value which was used to initialize this random generator.
Definition: RandomGenerator.h:178
unsigned int seed_
Internal seed parameter used for random number generation, changes whenever a new random number is ge...
Definition: RandomGenerator.h:133
RandomGenerator(RandomGenerator *optionalGenerator)
Creates a new random generator and optional initializes the internal parameter by a random value prov...
RandomGenerator()
Creates a new random generator and initializes the internal parameter with the random value of the st...
This class implements a scoped lock object for recursive lock objects.
Definition: Lock.h:135
The namespace covering the entire Ocean framework.
Definition: Accessor.h:15