MeteoIODoc 20240503.aefd3c94
RandomNumberGenerator.h
Go to the documentation of this file.
1// SPDX-License-Identifier: LGPL-3.0-or-later
2/***********************************************************************************/
3/* Copyright 2018 Michael Reisecker and work cited in documentation and source */
4/***********************************************************************************/
5/* This file is part of MeteoIO.
6 MeteoIO is free software: you can redistribute it and/or modify
7 it under the terms of the GNU Lesser General Public License as published by
8 the Free Software Foundation, either version 3 of the License, or
9 (at your option) any later version.
10
11 MeteoIO is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU Lesser General Public License for more details.
15
16 You should have received a copy of the GNU Lesser General Public License
17 along with MeteoIO. If not, see <http://www.gnu.org/licenses/>.
18*/
19
20#ifndef RANDOMNUMBERGENERATOR_H
21#define RANDOMNUMBERGENERATOR_H
22
23#include <ctime> //for time seed
24#include <inttypes.h> //for uint64_t etc. (ULL guarantees at least 64 bits and should be ok)
25#include <string> //for toString()
26#include <vector> //for internal states
27
28namespace mio {
29
1205class RngCore {
1206 public:
1207 bool hardware_seed_success; //store if hardware seed went as planned (Windows?)
1208
1209 RngCore();
1210 virtual ~RngCore();
1211
1212 virtual uint64_t int64() = 0;
1213 virtual uint32_t int32() = 0;
1214 virtual void getState(std::vector<uint64_t>& ovec_seed) const = 0;
1215 virtual void setState(const std::vector<uint64_t>& ivec_seed) = 0;
1216 //hardware or time seed; everyone may retrieve those from our RNG from outside:
1217 bool getUniqueSeed(uint64_t& store) const;
1218
1219 protected: //some lower level functions
1220 uint64_t combine32to64(const uint32_t& low, const uint32_t& high) const;
1221 double doubFromInt(const uint64_t& rn) const;
1222 double trueDoub(); //[0, 1]
1223
1224 private:
1225 bool getEntropy(uint64_t& store) const; //hardware seed
1226 uint64_t timeMixer(const time_t& tt, const clock_t& cc) const;
1227 uint32_t hash(const uint32_t& nn) const;
1228 unsigned int countLeadingZeros(const uint64_t& nn) const;
1229};
1230
1232 public:
1233 enum RNG_TYPE //computation method
1234 {
1237 RNG_MTW
1239
1240//CUSTOM_DIST step 1/7: Give your distribution a name in this enum
1241 enum RNG_DISTR //desired distribution, only used for doubles!
1242 {
1250 RNG_F
1252 enum RNG_BOUND //return uniform double respecting these boundaries
1253 {
1259
1260 //distribution_params's default is an empty vector, which means choose default params
1261 RandomNumberGenerator(const RNG_TYPE& type = RNG_XOR, const RNG_DISTR& distribution = RNG_UNIFORM,
1262 const std::vector<double>& distribution_params = std::vector<double>());
1264 virtual ~RandomNumberGenerator();
1265
1267
1268 uint64_t int64();
1269 uint32_t int32();
1270 double doub(); //we keep this separate for speed
1271 double doub(const RNG_BOUND& bounds, const bool& true_double = false);
1272 double draw(); //alias for uniform double
1273
1274 double pdf(const double& xx); //probability density function
1275 double cdf(const double& xx); //cumulative distribution function
1276
1277 uint64_t range64(const uint64_t& aa, const uint64_t& bb); //[a, b]
1278 uint32_t range32(const uint32_t& aa, const uint32_t& bb); //[a, b]
1279 bool trueRange32(const uint32_t& aa, const uint32_t& bb, uint32_t& result,
1280 const unsigned int& nmax = 1e6); //[a, b]
1281
1282 void getState(std::vector<uint64_t>& ovec_seed) const;
1283 void setState(const std::vector<uint64_t>& ivec_seed);
1284
1285 RNG_DISTR getDistribution(std::vector<double>& vec_params) const;
1286 void setDistribution(const RNG_DISTR& distribution, const std::vector<double>& vec_params =
1287 std::vector<double>()); //construct empty vector as default
1288 double getDistributionParameter(const std::string& param_name) const;
1289 void setDistributionParameter(const std::string& param_name, const double& param_val);
1290
1291 bool getHardwareSeedSuccess() const;
1292 bool getUniqueSeed(uint64_t& store) const; //allow for outside calls to the seeding function
1293 std::string toString();
1294
1295 static RNG_TYPE strToRngtype(const std::string& str); //get an RNG_TYPE from a string shorthand
1296 static RNG_DISTR strToRngdistr(const std::string& str); //get an RNG_DISTR from a string shorthand
1297
1298 private:
1299 RngCore* rng_core; //generator algorithm
1300 RNG_TYPE rng_type; //for output only so far
1301 RNG_DISTR rng_distribution;
1302 std::vector<double> DistributionParameters; //anything needed by the distributions can be stored here
1303
1304 bool rng_muller_generate; //bookkeeping Box-Muller transform
1305 double rng_muller_z1; //cache
1306 //(tradeoff between readability with the vector and speed with globals)
1307
1308 double (RandomNumberGenerator::*doubFunc)(); //double random numbers algorithm for distribution
1309 double (RandomNumberGenerator::*pdfFunc)(const double& xx) const; //probability density function
1310 double (RandomNumberGenerator::*cdfFunc)(const double& xx) const; //cumulative distribution function
1311
1312//CUSTOM_DIST step 2/7: Add your distribution function, its pdf and cdf here, matching exactly this type:
1313 double doubUniform();
1314 double pdfUniform(const double& xx) const;
1315 double cdfUniform(const double& xx) const;
1316 double doubGauss(); //=normal
1317 double pdfGauss(const double& xx) const;
1318 double cdfGauss(const double& xx) const;
1319 double doubGamma();
1320 double doubChiSquare();
1321 double doubStudentT();
1322 double doubBeta();
1323 double doubF();
1324
1325 double pdfNotImplemented(const double& xx) const;
1326 double cdfNotImplemented(const double& xx) const;
1327
1328 double doubGaussKernel(const double& mean, const double& sigma); //internal calls with specific params
1329 double doubGammaKernel(const double& alpha, const double& beta);
1330 double doubBetaKernel(const double& alpha, const double& beta);
1331};
1332
1333class RngXor : public RngCore { //combined generator with xor, shift and multiply
1334 public: //new generators must provide these
1335 RngXor();
1336 uint64_t int64();
1337 uint32_t int32();
1338 void getState(std::vector<uint64_t>& ovec_seed) const;
1339 void setState(const std::vector<uint64_t>& ivec_seed);
1340
1341 private:
1342 uint64_t state;
1343 uint64_t uu, vv, ww;
1344
1345 bool initAllStates();
1346};
1347
1348class RngPcg : public RngCore { //Permuted linear congruential generator
1349 public:
1350 RngPcg();
1351 uint64_t int64();
1352 uint32_t int32( );
1353 void getState(std::vector<uint64_t>& ovec_seed) const;
1354 void setState(const std::vector<uint64_t>& ivec_seed);
1355
1356 private:
1357 uint64_t state;
1358 uint64_t inc;
1359
1360 bool initAllStates();
1361};
1362
1363class RngMtw : public RngCore { //Mersenne Twister
1364 public:
1365 RngMtw();
1366 uint64_t int64();
1367 uint32_t int32( );
1368 void getState(std::vector<uint64_t>& ovec_seed) const;
1369 void setState(const std::vector<uint64_t>& ivec_seed);
1370
1371 private:
1372 const unsigned int MT_NN; //number of states
1373 const unsigned int MT_MM; //middle word / offset
1374 unsigned int current_mt_index;
1375
1376 std::vector<uint32_t> vec_states;
1377
1378 bool initAllStates();
1379};
1380
1381class RngFactory { //factory for the generator algorithm
1382 public: //(so that memory dedicated to the states lives only as long as the RNG)
1383 static RngCore* getCore(const RandomNumberGenerator::RNG_TYPE& algorithm);
1384};
1385
1386} //namespace
1387
1388#endif
1389
Definition: RandomNumberGenerator.h:1231
uint64_t int64()
Draw a 64 bit random number.
Definition: RandomNumberGenerator.cc:119
bool getHardwareSeedSuccess() const
Check if hardware noise could be read.
Definition: RandomNumberGenerator.cc:534
RandomNumberGenerator(const RNG_TYPE &type=RNG_XOR, const RNG_DISTR &distribution=RNG_UNIFORM, const std::vector< double > &distribution_params=std::vector< double >())
Default constructor.
Definition: RandomNumberGenerator.cc:44
double doub()
Draw a random number with double precision.
Definition: RandomNumberGenerator.cc:137
double draw()
Draw a random number with double precision.
Definition: RandomNumberGenerator.cc:176
uint64_t range64(const uint64_t &aa, const uint64_t &bb)
64 bit random number in an interval [aa, bb]
Definition: RandomNumberGenerator.cc:207
RNG_DISTR getDistribution(std::vector< double > &vec_params) const
Set the state of the RNG (seed the RNG)
Definition: RandomNumberGenerator.cc:287
static RNG_TYPE strToRngtype(const std::string &str)
Get an RNG_TYPE from a string.
Definition: RandomNumberGenerator.cc:625
std::string toString()
Print some info about the selected generator.
Definition: RandomNumberGenerator.cc:554
void setDistributionParameter(const std::string &param_name, const double &param_val)
Set single distribution parameter.
Definition: RandomNumberGenerator.cc:470
double getDistributionParameter(const std::string &param_name) const
Retrieve single distribution parameter.
Definition: RandomNumberGenerator.cc:407
void getState(std::vector< uint64_t > &ovec_seed) const
Get the state of the RNG to save for later continuation.
Definition: RandomNumberGenerator.cc:269
uint32_t int32()
Draw a 32 bit random number.
Definition: RandomNumberGenerator.cc:128
bool getUniqueSeed(uint64_t &store) const
Get a proper 64 bit seeding value for the generator.
Definition: RandomNumberGenerator.cc:545
RNG_BOUND
Definition: RandomNumberGenerator.h:1253
@ RNG_AINCBEXC
[0, 1)
Definition: RandomNumberGenerator.h:1255
@ RNG_AEXCBEXC
(0, 1)
Definition: RandomNumberGenerator.h:1257
@ RNG_AEXCBINC
(0, 1]
Definition: RandomNumberGenerator.h:1256
@ RNG_AINCBINC
[0, 1]
Definition: RandomNumberGenerator.h:1254
uint32_t range32(const uint32_t &aa, const uint32_t &bb)
32 bit random number in an interval [aa, bb]
Definition: RandomNumberGenerator.cc:232
void setState(const std::vector< uint64_t > &ivec_seed)
Set the state of the RNG (seed the RNG)
Definition: RandomNumberGenerator.cc:278
virtual ~RandomNumberGenerator()
Default destructor. Makes sure all states are freed from memory.
Definition: RandomNumberGenerator.cc:83
bool trueRange32(const uint32_t &aa, const uint32_t &bb, uint32_t &result, const unsigned int &nmax=1e6)
Random integer in a range without distribution distortions.
Definition: RandomNumberGenerator.cc:248
RNG_TYPE
Definition: RandomNumberGenerator.h:1234
@ RNG_XOR
Combined generator.
Definition: RandomNumberGenerator.h:1235
@ RNG_PCG
Permuted linear congruential generator.
Definition: RandomNumberGenerator.h:1236
@ RNG_MTW
Mersenne Twister generator.
Definition: RandomNumberGenerator.h:1237
double cdf(const double &xx)
Cumulative distribution function of selected distribution (integrated distribution function)
Definition: RandomNumberGenerator.cc:196
RNG_DISTR
Definition: RandomNumberGenerator.h:1242
@ RNG_GAMMA
Gamma deviates.
Definition: RandomNumberGenerator.h:1246
@ RNG_STUDENTT
Student-t deviates.
Definition: RandomNumberGenerator.h:1248
@ RNG_BETA
Beta deviates.
Definition: RandomNumberGenerator.h:1249
@ RNG_CHISQUARED
Chi-Squared deviates.
Definition: RandomNumberGenerator.h:1247
@ RNG_UNIFORM
Uniform deviates.
Definition: RandomNumberGenerator.h:1243
@ RNG_F
Fisher deviates.
Definition: RandomNumberGenerator.h:1250
@ RNG_NORMAL
= RNG_GAUSS
Definition: RandomNumberGenerator.h:1245
@ RNG_GAUSS
Gaussian deviates.
Definition: RandomNumberGenerator.h:1244
void setDistribution(const RNG_DISTR &distribution, const std::vector< double > &vec_params=std::vector< double >())
Set the distribution to draw random numbers from.
Definition: RandomNumberGenerator.cc:302
RandomNumberGenerator & operator=(const RandomNumberGenerator &rng)
Copy-operator.
Definition: RandomNumberGenerator.cc:94
double pdf(const double &xx)
Probability density function of selected distribution.
Definition: RandomNumberGenerator.cc:186
static RNG_DISTR strToRngdistr(const std::string &str)
Get an RNG_DISTR from a string.
Definition: RandomNumberGenerator.cc:646
Definition: RandomNumberGenerator.h:1205
bool hardware_seed_success
Definition: RandomNumberGenerator.h:1207
virtual uint32_t int32()=0
bool getUniqueSeed(uint64_t &store) const
Definition: RandomNumberGenerator.cc:1148
uint64_t combine32to64(const uint32_t &low, const uint32_t &high) const
Definition: RandomNumberGenerator.cc:1168
virtual void setState(const std::vector< uint64_t > &ivec_seed)=0
virtual void getState(std::vector< uint64_t > &ovec_seed) const =0
double doubFromInt(const uint64_t &rn) const
Definition: RandomNumberGenerator.cc:1175
virtual uint64_t int64()=0
virtual ~RngCore()
Definition: RandomNumberGenerator.cc:1142
RngCore()
Definition: RandomNumberGenerator.cc:1136
double trueDoub()
Definition: RandomNumberGenerator.cc:1184
Definition: RandomNumberGenerator.h:1381
static RngCore * getCore(const RandomNumberGenerator::RNG_TYPE &algorithm)
Definition: RandomNumberGenerator.cc:1273
Definition: RandomNumberGenerator.h:1363
void getState(std::vector< uint64_t > &ovec_seed) const
Definition: RandomNumberGenerator.cc:1008
uint32_t int32()
Definition: RandomNumberGenerator.cc:1039
RngMtw()
Definition: RandomNumberGenerator.cc:990
void setState(const std::vector< uint64_t > &ivec_seed)
Definition: RandomNumberGenerator.cc:1017
uint64_t int64()
Definition: RandomNumberGenerator.cc:1001
Definition: RandomNumberGenerator.h:1348
RngPcg()
Definition: RandomNumberGenerator.cc:924
uint32_t int32()
Definition: RandomNumberGenerator.cc:939
uint64_t int64()
Definition: RandomNumberGenerator.cc:930
void getState(std::vector< uint64_t > &ovec_seed) const
Definition: RandomNumberGenerator.cc:959
void setState(const std::vector< uint64_t > &ivec_seed)
Definition: RandomNumberGenerator.cc:966
Definition: RandomNumberGenerator.h:1333
uint64_t int64()
Definition: RandomNumberGenerator.cc:868
void getState(std::vector< uint64_t > &ovec_seed) const
Definition: RandomNumberGenerator.cc:886
void setState(const std::vector< uint64_t > &ivec_seed)
Definition: RandomNumberGenerator.cc:895
RngXor()
Definition: RandomNumberGenerator.cc:862
uint32_t int32()
Definition: RandomNumberGenerator.cc:881
Definition: Config.cc:31