-
Notifications
You must be signed in to change notification settings - Fork 1
/
randomnumbergen.h
234 lines (171 loc) · 6.88 KB
/
randomnumbergen.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
// Copyright (c) 2007-2015 by Space-Time Engineering, LLC ("STE").
// All Rights Reserved.
//
// This source code is a part of Scenargie Software ("Software") and is
// subject to STE Software License Agreement. The information contained
// herein is considered a trade secret of STE, and may not be used as
// the basis for any other software, hardware, product or service.
//
// Refer to license.txt for more specific directives.
#ifndef RANDOMNUMBERGEN_H
#define RANDOMNUMBERGEN_H
#include <cmath>
#include <string>
#include <limits>
#include "boost/math/constants/constants.hpp"
#include "boost/random.hpp"
#include <stdint.h>
namespace ScenSim {
typedef uint32_t RandomNumberGeneratorSeedType;
inline
unsigned long long int HashStringToInt(const std::string& aStringToHash)
{
unsigned long long int hash = 5381;
for(size_t i = 0; (i < aStringToHash.size()); i++) {
hash = 33 * hash + static_cast<unsigned long long int>(aStringToHash[i]);
}//if//
return (hash);
}
inline
RandomNumberGeneratorSeedType HashInputsToMakeSeed(
const RandomNumberGeneratorSeedType seed,
const unsigned long long int hashingInput)
{
// Formula is just "picked out of the air" (constants are prime).
const unsigned long long int hash1 = seed;
const unsigned long long int hash2 = hashingInput;
return (static_cast<RandomNumberGeneratorSeedType>(
(98385721723 * hash1 + 7138347631 * hash2 + 924713)));
}
template<typename T> inline
RandomNumberGeneratorSeedType HashInputsToMakeSeed(
const RandomNumberGeneratorSeedType seed,
const T hashingInput)
{
return (HashInputsToMakeSeed(seed, static_cast<unsigned long long int>(hashingInput)));
}
template<typename T1, typename T2> inline
RandomNumberGeneratorSeedType HashInputsToMakeSeed(
const RandomNumberGeneratorSeedType seed,
const T1 hashingInput1,
const T2 hashingInput2)
{
return HashInputsToMakeSeed(HashInputsToMakeSeed(seed, hashingInput1), hashingInput2);
}
template<typename T1, typename T2, typename T3> inline
RandomNumberGeneratorSeedType HashInputsToMakeSeed(
RandomNumberGeneratorSeedType Seed,
const T1 hashingInput1,
const T2 hashingInput2,
const T3 hashingInput3)
{
return HashInputsToMakeSeed(
HashInputsToMakeSeed(Seed, hashingInput1, hashingInput2), hashingInput3);
}
template<typename T> inline
RandomNumberGeneratorSeedType HashInputsToMakeSeed(
RandomNumberGeneratorSeedType seed,
const std::string& hashingInput1,
const T hashingInput2)
{
return HashInputsToMakeSeed(HashInputsToMakeSeed(seed, HashStringToInt(hashingInput1)), hashingInput2);
}
// Lower quality (Linear congruential generator) Small state and Fast.
class RandomNumberGenerator {
public:
explicit RandomNumberGenerator(const RandomNumberGeneratorSeedType& seed)
: generator(static_cast<boost::rand48::result_type>(seed)) {}
void SetSeed(const RandomNumberGeneratorSeedType& seed)
{ generator.seed(static_cast<boost::rand48::result_type>(seed)); }
int32_t GenerateRandomInt(const int32_t lowestValue, const int32_t highestValue);
double GenerateRandomDouble() {
// Generate range [0,1)
return (static_cast<double>(generator()) / (static_cast<double>(generator.max()) + 1.0));
}
double erand48() { return GenerateRandomDouble(); }
// For compatibility with STL templates.
int32_t operator()(const int32_t maxPlus1) { return ((*this).GenerateRandomInt(0, (maxPlus1-1))); }
private:
boost::rand48 generator;
};//RandomNumberGenerator;
inline
int32_t RandomNumberGenerator::GenerateRandomInt(const int32_t lowestValue, const int32_t highestValue)
{
assert(lowestValue <= highestValue);
if (lowestValue == highestValue) {
return (lowestValue);
}//if//
return (static_cast<int32_t>(
((highestValue - lowestValue + 1) * (*this).GenerateRandomDouble()) + lowestValue));
// Only makes performance sense running in 64bit mode:
//long long int range = (highestValue - lowestValue + 1);
//long long int randomVal = generator();
//return (
// static_cast<int32_t>(
// ((range * randomVal) / (static_cast<long long int>(MAX_RANDOM_INT) + 1)) + lowestValue));
}
//--------------------------------------------------------------------------------------------------
//
// Higher quality random number generators have much larger state.
//
class HighQualityRandomNumberGenerator {
public:
explicit HighQualityRandomNumberGenerator(const RandomNumberGeneratorSeedType& seed)
: generator(static_cast<boost::mt19937::result_type>(seed)) {}
void SetSeed(const RandomNumberGeneratorSeedType& seed)
{ generator.seed(static_cast<boost::mt19937::result_type>(seed)); }
int32_t GenerateRandomInt(const int32_t lowestValue, const int32_t highestValue);
double GenerateRandomDouble() {
// Generate range [0,1)
return (static_cast<double>(generator()) / (static_cast<double>(generator.max()) + 1.0));
}
// For compatibility with STL templates.
int32_t operator()(const int32_t maxPlus1) { return ((*this).GenerateRandomInt(0, (maxPlus1-1))); }
private:
boost::mt19937 generator;
};//HighQualityRandomNumberGenerator//
inline
int32_t HighQualityRandomNumberGenerator::GenerateRandomInt(
const int32_t lowestValue, const int32_t highestValue)
{
assert(lowestValue <= highestValue);
if (lowestValue == highestValue) {
return (lowestValue);
}//if//
return (static_cast<int32_t>(
((highestValue - lowestValue + 1) * (*this).GenerateRandomDouble()) + lowestValue));
}
//--------------------------------------------------------------------------------------------------
inline
double ConvertToExponentialDistribution(const double& randomDouble)
{
// Using assumption that random Double is in the range [0.0,1.0).
return (-log(1.0 - randomDouble));
}
inline
double ConvertToGuassianDistribution(const double& uniformRandom1, const double& uniformRandom2)
{
// Using assumption that random input variables are in the range [0.0,1.0).
using std::max;
const double PI = boost::math::constants::pi<double>();
const double minRandomValue = 1e-100;
return (sqrt(-2.0 * log(max(uniformRandom1, minRandomValue))) * cos(2.0 * PI * uniformRandom2));
}
// More efficent version produces two gaussian distribution values.
inline
void ConvertToGaussianDistribution(
const double& uniformRandom1,
const double& uniformRandom2,
double& gaussianRandom1,
double& gaussianRandom2)
{
// Using assumption that random input variables are in the range [0.0,1.0).
using std::max;
const double PI = boost::math::constants::pi<double>();
const double minRandomValue = 1e-100;
const double factor = sqrt(-2.0 * log(max(uniformRandom1, minRandomValue)));
gaussianRandom1 = factor * cos(2.0 * PI * uniformRandom2);
gaussianRandom2 = factor * sin(2.0 * PI * uniformRandom2);
}
}//namespace//
#endif