Pioneer
Loading...
Searching...
No Matches
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
19extern "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
27class Random : public RefCounted {
28 pcg32 mPCG;
29
30 // For storing second rand from Normal
31 bool cached;
32 double z1;
33
34public:
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
238private:
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
const pcg32 & GetPCG() const
Definition Random.h:236
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
Uint32 Int32()
Definition Random.h:92
Definition RefCounted.h:11
fixedf< 32 > fixed
Definition fixed.h:242