Eclipse SUMO - Simulation of Urban MObility
RandHelper.h
Go to the documentation of this file.
1 /****************************************************************************/
2 // Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo
3 // Copyright (C) 2005-2020 German Aerospace Center (DLR) and others.
4 // This program and the accompanying materials are made available under the
5 // terms of the Eclipse Public License 2.0 which is available at
6 // https://www.eclipse.org/legal/epl-2.0/
7 // This Source Code may also be made available under the following Secondary
8 // Licenses when the conditions for such availability set forth in the Eclipse
9 // Public License 2.0 are satisfied: GNU General Public License, version 2
10 // or later which is available at
11 // https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
12 // SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
13 /****************************************************************************/
20 //
21 /****************************************************************************/
22 #pragma once
23 #include <cassert>
24 #include <vector>
25 #include <map>
26 #include <random>
27 #include <sstream>
28 #include <iostream>
29 
30 //#define DEBUG_RANDCALLS
31 
32 // ===========================================================================
33 // class definitions
34 // ===========================================================================
39 class RandHelper {
40 public:
42  static void insertRandOptions();
43 
45  static void initRand(std::mt19937* which = nullptr, const bool random = false, const int seed = 23423);
46 
48  static void initRandGlobal(std::mt19937* which = nullptr);
49 
51  static inline double rand(std::mt19937* rng = nullptr) {
52  if (rng == 0) {
54  }
55  const double res = double((*rng)() / 4294967296.0);
56 #ifdef DEBUG_RANDCALLS
57  myCallCount[rng]++;
58  if (myCallCount[rng] == myDebugIndex) {
59  std::cout << "DEBUG\n"; // for setting breakpoint
60  }
61  std::stringstream stream; // to reduce output interleaving from different threads
62  stream << " rng" << myRngId.find(rng)->second << " rand call=" << myCallCount[rng] << " val=" << res << "\n";
63  std::cout << stream.str();
64 #endif
65  return res;
66  }
67 
69  static inline double rand(double maxV, std::mt19937* rng = 0) {
70  return maxV * rand(rng);
71  }
72 
74  static inline double rand(double minV, double maxV, std::mt19937* rng = 0) {
75  return minV + (maxV - minV) * rand(rng);
76  }
77 
79  static inline int rand(int maxV, std::mt19937* rng = 0) {
80  if (rng == 0) {
82  }
83  unsigned int usedBits = maxV - 1;
84  usedBits |= usedBits >> 1;
85  usedBits |= usedBits >> 2;
86  usedBits |= usedBits >> 4;
87  usedBits |= usedBits >> 8;
88  usedBits |= usedBits >> 16;
89 
90  // Draw numbers until one is found in [0, maxV-1]
91  int result;
92  do {
93  result = (*rng)() & usedBits;
94  } while (result >= maxV);
95  return result;
96  }
97 
99  static inline int rand(int minV, int maxV, std::mt19937* rng = 0) {
100  return minV + rand(maxV - minV, rng);
101  }
102 
104  static inline long long int rand(long long int maxV, std::mt19937* rng = 0) {
105  if (maxV <= std::numeric_limits<int>::max()) {
106  return rand((int)maxV, rng);
107  }
108  if (rng == 0) {
110  }
111  unsigned long long int usedBits = maxV - 1;
112  usedBits |= usedBits >> 1;
113  usedBits |= usedBits >> 2;
114  usedBits |= usedBits >> 4;
115  usedBits |= usedBits >> 8;
116  usedBits |= usedBits >> 16;
117  usedBits |= usedBits >> 32;
118 
119  // Draw numbers until one is found in [0, maxV-1]
120  long long int result;
121  do {
122  result = (((unsigned long long int)(*rng)() << 32) | (*rng)()) & usedBits; // toss unused bits to shorten search
123  } while (result >= maxV);
124  return result;
125  }
126 
128  static inline long long int rand(long long int minV, long long int maxV, std::mt19937* rng = 0) {
129  return minV + rand(maxV - minV, rng);
130  }
131 
133  static inline double randNorm(double mean, double variance, std::mt19937* rng = 0) {
134  // Polar method to avoid cosine
135  double u, q;
136  do {
137  u = rand(2.0, rng) - 1;
138  const double v = rand(2.0, rng) - 1;
139  q = u * u + v * v;
140  } while (q == 0.0 || q >= 1.0);
141  return (double)(mean + variance * u * sqrt(-2 * log(q) / q));
142  }
143 
145  template<class T>
146  static inline const T&
147  getRandomFrom(const std::vector<T>& v, std::mt19937* rng = 0) {
148  assert(v.size() > 0);
149  return v[rand((int)v.size(), rng)];
150  }
151 
153  static std::string saveState(std::mt19937* rng = 0) {
154  if (rng == 0) {
156  }
157  std::ostringstream oss;
158  oss << (*rng);
159  return oss.str();
160  }
161 
163  static void loadState(const std::string& state, std::mt19937* rng = 0) {
164  if (rng == 0) {
166  }
167  std::istringstream iss(state);
168  iss >> (*rng);
169  }
170 
171 
172 protected:
174  static std::mt19937 myRandomNumberGenerator;
175 
176 #ifdef DEBUG_RANDCALLS
177  static std::map<std::mt19937*, int> myCallCount;
178  static std::map<std::mt19937*, int> myRngId;
179  static int myDebugIndex;
180 #endif
181 
182 };
Utility functions for using a global, resetable random number generator.
Definition: RandHelper.h:39
static double rand(std::mt19937 *rng=nullptr)
Returns a random real number in [0, 1)
Definition: RandHelper.h:51
static double rand(double minV, double maxV, std::mt19937 *rng=0)
Returns a random real number in [minV, maxV)
Definition: RandHelper.h:74
static std::string saveState(std::mt19937 *rng=0)
save rng state to string
Definition: RandHelper.h:153
static void loadState(const std::string &state, std::mt19937 *rng=0)
load rng state from string
Definition: RandHelper.h:163
static long long int rand(long long int minV, long long int maxV, std::mt19937 *rng=0)
Returns a random 64 bit integer in [minV, maxV-1].
Definition: RandHelper.h:128
static void initRand(std::mt19937 *which=nullptr, const bool random=false, const int seed=23423)
Initialises the random number generator with hardware randomness or seed.
Definition: RandHelper.cpp:60
static const T & getRandomFrom(const std::vector< T > &v, std::mt19937 *rng=0)
Returns a random element from the given vector.
Definition: RandHelper.h:147
static void initRandGlobal(std::mt19937 *which=nullptr)
Reads the given random number options and initialises the random number generator in accordance.
Definition: RandHelper.cpp:76
static void insertRandOptions()
Initialises the given options container with random number options.
Definition: RandHelper.cpp:44
static double randNorm(double mean, double variance, std::mt19937 *rng=0)
Access to a random number from a normal distribution.
Definition: RandHelper.h:133
static long long int rand(long long int maxV, std::mt19937 *rng=0)
Returns a random 64 bit integer in [0, maxV-1].
Definition: RandHelper.h:104
static double rand(double maxV, std::mt19937 *rng=0)
Returns a random real number in [0, maxV)
Definition: RandHelper.h:69
static int rand(int minV, int maxV, std::mt19937 *rng=0)
Returns a random integer in [minV, maxV-1].
Definition: RandHelper.h:99
static std::mt19937 myRandomNumberGenerator
the random number generator to use
Definition: RandHelper.h:174
static int rand(int maxV, std::mt19937 *rng=0)
Returns a random integer in [0, maxV-1].
Definition: RandHelper.h:79