MeteoIODoc  2.10.0
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 
28 namespace mio {
29 
1205 class 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
1238  };
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
1251  };
1252  enum RNG_BOUND //return uniform double respecting these boundaries
1253  {
1257  RNG_AEXCBEXC
1258  };
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 
1333 class 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 
1348 class 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 
1363 class 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 
1381 class 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:30