Pioneer
Random.h
Go to the documentation of this file.
1 // Copyright © 2008-2023 Pioneer Developers. See AUTHORS.txt for details
2 // Licensed under the terms of the GPL v3. See licenses/GPL-3.txt
3 
4 // A deterministic random number generator for use by the rest of the
5 // engine. It *should* give the same output for a given input regardless
6 // of the processor architecture. If it doesn't then it needs to be fixed!
7 
8 // Based on: http://www.javamex.com/tutorials/random_numbers/xorshift.shtml
9 
10 #ifndef RAND_H
11 #define RAND_H
12 
13 #include <assert.h>
14 #include <cmath>
15 
16 #include "RefCounted.h"
17 #include "fixed.h"
18 
19 extern "C" {
20 #include "jenkins/lookup3.h"
21 }
22 
23 #define PCG_LITTLE_ENDIAN 1
24 #include "pcg-cpp/pcg_random.hpp"
25 
26 // A deterministic random number generator
27 class Random : public RefCounted {
28  pcg32 mPCG;
29 
30  // For storing second rand from Normal
31  bool cached;
32  double z1;
33 
34 public:
35  //
36  // Constructors
37  //
38 
39  // Construct a new random generator using the given seed
40  Random(const Uint32 initialSeed = 0xabcd1234)
41  {
42  seed(initialSeed);
43  }
44 
45  // Construct a new generator given an array of 32-bit seeds.
46  Random(const Uint32 *const seeds, size_t length)
47  {
48  seed(seeds, length);
49  }
50 
51  // Construct a new random generator from an array of 64-bit
52  // seeds.
53  Random(const Uint64 *const seeds, size_t length)
54  {
55  seed(reinterpret_cast<const Uint32 *>(seeds), length * 2);
56  }
57 
58  //
59  // Seed functions
60  //
61 
62  // Seed the RNG using the hash of the given array of seeds.
63  void seed(const Uint32 *const seeds, size_t length)
64  {
65  const Uint32 hash = lookup3_hashword(seeds, length, 0);
66  mPCG.seed(hash);
67  cached = false;
68  }
69 
70  // Seed using an array of 64-bit integers
71  void seed(const Uint64 *const seeds, size_t length)
72  {
73  seed(reinterpret_cast<const Uint32 *>(seeds), length * 2);
74  }
75 
76  // Seed using a single 32-bit integer
77  void seed(const Uint32 value)
78  {
79  seed(&value, 1);
80  }
81 
82  //
83  // Number generators.
84  //
85  // Starting from a given seed value the generator will return the
86  // same sequence of numbers. Unless otherwise stated the numbers
87  // are 32-bit and each call consumes one
88  //
89 
90  // Get the next integer from the sequence
91  // interval [0, 2**32)
92  inline Uint32 Int32()
93  {
94  return mPCG();
95  }
96 
97  // Pick an integer like you're rolling a "choices" sided die,
98  // a 6 sided die would return a number between 0 and 5.
99  // interval [0, choices)
100  inline Uint32 Int32(const int choices)
101  {
102  return Int32() % choices;
103  }
104 
105  // Pick a number between min and max, inclusive.
106  // interval [min, max]
107  inline int Int32(const int min, const int max)
108  {
109  return (Int32() % (1 + max - min)) + min;
110  }
111 
112  // Pick a number in the half open interval [0, 1)
113  inline double Double()
114  {
115  return double(Int32()) * (1. / 4294967296.); // divided by 2^32
116  }
117 
118  // Pick a number in the closed interval [0, 1]
119  inline double Double_closed()
120  {
121  return double(Int32()) * (1. / 4294967295.); // divided by 2^32 - 1
122  }
123 
124  // Pick a number in the open interval (0, 1)
125  inline double Double_open()
126  {
127  return (double(Int32()) + .5) * (1. / 4294967296.); // divided by 2^32
128  }
129 
130  // Pick a 53-bit resolution double in the half open interval [0, 1)
131  // This method consumes two 32-bit numbers from the sequence.
132  inline double Double53()
133  {
134  return (double(Int32() >> 5) * 67108864. + double(Int32() >> 6)) * (1. / 9007199254740992.);
135  }
136 
137  // Pick a number in the half-open interval [min, limit)
138  inline double Double(double min, double limit)
139  {
140  return Double(limit - min) + min;
141  }
142 
143  // Pick a number in the half-open interval [0, limit)
144  inline double Double(double limit)
145  {
146  return limit * Double();
147  }
148 
149  // Pick a number between 0 and max inclusive
150  // interval [0, max]
151  inline double Double_closed(double max)
152  {
153  return max * Double_closed();
154  }
155 
156  // Pick a number between min and max inclusive
157  // interval [min, max]
158  inline double Double_closed(double min, double max)
159  {
160  return Double_closed(max - min) + min;
161  }
162 
163  // interval [0,1)
164  inline double NDouble(int p)
165  {
166  double o = Double(1.0);
167  while (--p > 0)
168  o *= Double(1.0);
169  return o;
170  }
171 
172  // Normal distribution with zero mean, and unit variance
173  inline double Normal()
174  {
175  return Normal(0.0, 1.0);
176  }
177 
178  // Normal distribution with unit variance
179  inline double Normal(const double mean)
180  {
181  return Normal(mean, 1.0);
182  }
183 
184  //Normal (Gauss) distribution
185  inline double Normal(const double mean, const double stddev)
186  {
187  //https://en.wikipedia.org/wiki/Box-Muller_transform#Polar_form
188  double u, v, s, z0;
189 
190  if (cached) {
191  z0 = z1;
192  cached = false;
193  } else {
194  do {
195  u = Double_closed(-1, 1);
196  v = Double_closed(-1, 1);
197  s = u * u + v * v;
198  } while (s >= 1.0);
199 
200  s = sqrt((-2.0 * log(s)) / s);
201  z0 = u * s;
202  z1 = v * s;
203  cached = true;
204  }
205 
206  return mean + z0 * stddev;
207  }
208 
209  inline int Poisson(const double lambda)
210  {
211  int k = 0;
212  double p = Double();
213  const double target = exp(-lambda);
214  while (p > target) {
215  k += 1;
216  p *= Double();
217  }
218  return k;
219  }
220 
221  // Pick a fixed-point integer half open interval [0,1)
222  inline fixed Fixed()
223  {
224  return fixed(Int32());
225  }
226 
227  // interval [0,1)
228  inline fixed NFixed(int p)
229  {
230  fixed o = Fixed();
231  while (--p > 0)
232  o *= Fixed();
233  return o;
234  }
235 
236  const pcg32 &GetPCG() const { return mPCG; }
237 
238 private:
239  Random(const Random &); // copy constructor not defined
240  void operator=(const Random &); // assignment operator not defined
241 };
242 
243 #endif // RAND_H
Definition: Random.h:27
double Double_closed(double min, double max)
Definition: Random.h:158
double Double(double min, double limit)
Definition: Random.h:138
double NDouble(int p)
Definition: Random.h:164
int Poisson(const double lambda)
Definition: Random.h:209
double Double_closed()
Definition: Random.h:119
double Double53()
Definition: Random.h:132
fixed Fixed()
Definition: Random.h:222
double Double()
Definition: Random.h:113
double Double_closed(double max)
Definition: Random.h:151
int Int32(const int min, const int max)
Definition: Random.h:107
fixed NFixed(int p)
Definition: Random.h:228
double Normal(const double mean)
Definition: Random.h:179
double Normal()
Definition: Random.h:173
double Double(double limit)
Definition: Random.h:144
double Double_open()
Definition: Random.h:125
Random(const Uint32 initialSeed=0xabcd1234)
Definition: Random.h:40
void seed(const Uint32 value)
Definition: Random.h:77
Random(const Uint32 *const seeds, size_t length)
Definition: Random.h:46
Uint32 Int32(const int choices)
Definition: Random.h:100
Random(const Uint64 *const seeds, size_t length)
Definition: Random.h:53
void seed(const Uint64 *const seeds, size_t length)
Definition: Random.h:71
void seed(const Uint32 *const seeds, size_t length)
Definition: Random.h:63
double Normal(const double mean, const double stddev)
Definition: Random.h:185
const pcg32 & GetPCG() const
Definition: Random.h:236
Uint32 Int32()
Definition: Random.h:92
Definition: RefCounted.h:11
fixedf< 32 > fixed
Definition: fixed.h:242