rng.cpp
Go to the documentation of this file.
1 
9 #include "rng.h"
10 #include <argos3/core/utility/configuration/argos_exception.h>
11 #include <argos3/core/utility/logging/argos_log.h>
12 #include <cstring>
13 #include <limits>
14 #include <cmath>
15 
16 namespace argos {
17 
18  /****************************************/
19  /****************************************/
20 
21  /* Period parameters */
22  static const SInt32 N = 624;
23  static const SInt32 M = 397;
24  static const UInt32 MATRIX_A = 0x9908b0dfUL; /* constant vector a */
25  static const UInt32 UPPER_MASK = 0x80000000UL; /* most significant w-r bits */
26  static const UInt32 LOWER_MASK = 0x7fffffffUL; /* least significant r bits */
27  static const CRange<UInt32> INT_RANGE = CRange<UInt32>(0, 0xFFFFFFFFUL);
28 
29  std::map<std::string, CRandom::CCategory*> CRandom::m_mapCategories;
30 
31  /* Checks that a category exists. It internally creates an iterator that points to the category, if found. */
32 #define CHECK_CATEGORY(category) \
33  std::map<std::string, CCategory*>::iterator itCategory = m_mapCategories.find(category); \
34  if(itCategory == m_mapCategories.end()) { \
35  THROW_ARGOSEXCEPTION("CRandom:: can't find category \"" << category << "\"."); \
36  }
37 
38  /****************************************/
39  /****************************************/
40 
42  m_unSeed(un_seed),
43  m_punState(new UInt32[N]),
44  m_nIndex(N+1) {
45  Reset();
46  }
47 
48  /****************************************/
49  /****************************************/
50 
51  CRandom::CRNG::CRNG(const CRNG& c_rng) :
52  m_unSeed(c_rng.m_unSeed),
53  m_punState(new UInt32[N]),
54  m_nIndex(c_rng.m_nIndex) {
55  ::memcpy(m_punState, c_rng.m_punState, N * sizeof(UInt32));
56  }
57 
58  /****************************************/
59  /****************************************/
60 
62  delete[] m_punState;
63  }
64 
65  /****************************************/
66  /****************************************/
67 
69  m_punState[0]= m_unSeed & 0xffffffffUL;
70  for (m_nIndex = 1; m_nIndex < N; ++m_nIndex) {
71  m_punState[m_nIndex] =
72  (1812433253UL * (m_punState[m_nIndex-1] ^ (m_punState[m_nIndex-1] >> 30)) + m_nIndex);
73  m_punState[m_nIndex] &= 0xffffffffUL;
74  }
75  }
76 
77  /****************************************/
78  /****************************************/
79 
81  return Uniform32bit() < f_true * INT_RANGE.GetMax();
82  }
83 
84  /****************************************/
85  /****************************************/
86 
88  CRadians cRetVal;
89  INT_RANGE.MapValueIntoRange(cRetVal, Uniform32bit(), c_range);
90  return cRetVal;
91  }
92 
93  /****************************************/
94  /****************************************/
95 
97  Real fRetVal;
98  INT_RANGE.MapValueIntoRange(fRetVal, Uniform32bit(), c_range);
99  return fRetVal;
100  }
101 
102  /****************************************/
103  /****************************************/
104 
106  SInt32 nRetVal;
107  INT_RANGE.MapValueIntoRange(nRetVal, Uniform32bit(), c_range);
108  return nRetVal;
109  }
110 
111  /****************************************/
112  /****************************************/
113 
115  UInt32 unRetVal;
116  INT_RANGE.MapValueIntoRange(unRetVal, Uniform32bit(), c_range);
117  return unRetVal;
118  }
119 
120  /****************************************/
121  /****************************************/
122 
124  static CRange<Real> fRange(0.0f, 1.0f);
125  return -Log(Uniform(fRange)) * f_mean;
126  }
127 
128  /****************************************/
129  /****************************************/
130 
132  Real f_mean) {
133  /* This is the Box-Muller method in its cartesian variant
134  see http://www.dspguru.com/dsp/howtos/how-to-generate-white-gaussian-noise
135  */
136  static CRange<Real> fRange(-1.0f, 1.0f);
137  Real fNum1, fNum2;
138  Real fSquare;
139  do {
140  fNum1 = Uniform(fRange);
141  fNum2 = Uniform(fRange);
142  fSquare = fNum1 * fNum1 + fNum2 * fNum2;
143  } while(fSquare >= 1);
144  return f_mean + f_std_dev * fNum1 * Sqrt(-2.0f * Log(fSquare) / fSquare);
145  }
146 
147  /****************************************/
148  /****************************************/
149 
151  /* Draw a number uniformly from (0,1) --- bounds excluded */
152  static CRange<Real> cUnitRange(0.0f, 1.0f);
153  Real fValue;
154  do {
155  fValue = Uniform(cUnitRange);
156  }
157  while(! cUnitRange.WithinMinBoundExcludedMaxBoundExcluded(fValue));
158  /* Calculate the value to return from the definition of Rayleigh distribution
159  * http://en.wikipedia.org/wiki/Rayleigh_distribution#Generating_Rayleigh-distributed_random_variates
160  */
161  return f_sigma * Sqrt(-2.0f * Log(fValue));
162  }
163 
164 /****************************************/
165  /****************************************/
166 
168  /* Draw a number uniformly from (0,1) */
169  Real fValue;
170  fValue = Gaussian(1,0);
171  /* Calculate the value to return from the definition of Lognormal distribution
172  * http://en.wikipedia.org/wiki/Log-normal_distribution#Generating_log-normally_distributed_random_variates
173  */
174  return std::exp(f_mu + f_sigma * fValue);
175  }
176 
177  /****************************************/
178  /****************************************/
179 
180  UInt32 CRandom::CRNG::Uniform32bit() {
181  UInt32 y;
182  static UInt32 mag01[2] = { 0x0UL, MATRIX_A };
183  /* mag01[x] = x * MATRIX_A for x=0,1 */
184 
185  if (m_nIndex >= N) { /* generate N words at one time */
186  SInt32 kk;
187  for (kk = 0; kk < N - M; ++kk) {
188  y = (m_punState[kk] & UPPER_MASK) | (m_punState[kk+1] & LOWER_MASK);
189  m_punState[kk] = m_punState[kk+M] ^ (y >> 1) ^ mag01[y & 0x1UL];
190  }
191  for (; kk < N - 1; ++kk) {
192  y = (m_punState[kk] & UPPER_MASK) | (m_punState[kk+1] & LOWER_MASK);
193  m_punState[kk] = m_punState[kk+(M-N)] ^ (y >> 1) ^ mag01[y & 0x1UL];
194  }
195  y = (m_punState[N-1] & UPPER_MASK) | (m_punState[0] & LOWER_MASK);
196  m_punState[N-1] = m_punState[M-1] ^ (y >> 1) ^ mag01[y & 0x1UL];
197 
198  m_nIndex = 0;
199  }
200 
201  y = m_punState[m_nIndex++];
202 
203  /* Tempering */
204  y ^= (y >> 11);
205  y ^= (y << 7) & 0x9d2c5680UL;
206  y ^= (y << 15) & 0xefc60000UL;
207  y ^= (y >> 18);
208 
209  return y;
210  }
211 
212  /****************************************/
213  /****************************************/
214 
215  CRandom::CCategory::CCategory(const std::string& str_id,
216  UInt32 un_seed) :
217  m_strId(str_id),
218  m_unSeed(un_seed),
219  m_cSeeder(un_seed),
220  m_cSeedRange(1, std::numeric_limits<UInt32>::max()) {}
221 
222  /****************************************/
223  /****************************************/
224 
226  while(! m_vecRNGList.empty()) {
227  delete m_vecRNGList.back();
228  m_vecRNGList.pop_back();
229  }
230  }
231 
232  /****************************************/
233  /****************************************/
234 
236  m_unSeed = un_seed;
237  m_cSeeder.SetSeed(m_unSeed);
238  }
239 
240  /****************************************/
241  /****************************************/
242 
244  /* Get seed from internal RNG */
245  UInt32 unSeed = m_cSeeder.Uniform(m_cSeedRange);
246  /* Create new RNG */
247  m_vecRNGList.push_back(new CRNG(unSeed));
248  return m_vecRNGList.back();
249  }
250 
251  /****************************************/
252  /****************************************/
253 
255  /* Reset internal RNG */
256  m_cSeeder.Reset();
257  ReseedRNGs();
258  /* Reset the RNGs */
259  for(size_t i = 0; i < m_vecRNGList.size(); ++i) {
260  m_vecRNGList[i]->Reset();
261  }
262  }
263 
264  /****************************************/
265  /****************************************/
266 
268  for(size_t i = 0; i < m_vecRNGList.size(); ++i) {
269  /* Get seed from internal RNG */
270  m_vecRNGList[i]->SetSeed(m_cSeeder.Uniform(m_cSeedRange));
271  }
272  }
273 
274  /****************************************/
275  /****************************************/
276 
277  bool CRandom::CreateCategory(const std::string& str_category,
278  UInt32 un_seed) {
279  /* Is there a category already? */
280  std::map<std::string, CCategory*>::iterator itCategory = m_mapCategories.find(str_category);
281  if(itCategory == m_mapCategories.end()) {
282  /* No, create it */
283  m_mapCategories.insert(
284  std::pair<std::string,
285  CRandom::CCategory*>(str_category,
286  new CRandom::CCategory(str_category,
287  un_seed)));
288  return true;
289  }
290  return false;
291  }
292 
293  /****************************************/
294  /****************************************/
295 
296  CRandom::CCategory& CRandom::GetCategory(const std::string& str_category) {
297  CHECK_CATEGORY(str_category);
298  return *(itCategory->second);
299  }
300 
301  /****************************************/
302  /****************************************/
303 
304  bool CRandom::ExistsCategory(const std::string& str_category) {
305  try {
306  CHECK_CATEGORY(str_category);
307  return true;
308  }
309  catch(CARGoSException& ex) {
310  return false;
311  }
312  }
313 
314  /****************************************/
315  /****************************************/
316 
317  void CRandom::RemoveCategory(const std::string& str_category) {
318  CHECK_CATEGORY(str_category);
319  delete itCategory->second;
320  m_mapCategories.erase(itCategory);
321  }
322 
323  /****************************************/
324  /****************************************/
325 
326  CRandom::CRNG* CRandom::CreateRNG(const std::string& str_category) {
327  CHECK_CATEGORY(str_category);
328  return itCategory->second->CreateRNG();
329  }
330 
331  /****************************************/
332  /****************************************/
333 
334  UInt32 CRandom::GetSeedOf(const std::string& str_category) {
335  CHECK_CATEGORY(str_category);
336  return itCategory->second->GetSeed();
337  }
338 
339  /****************************************/
340  /****************************************/
341 
342  void CRandom::SetSeedOf(const std::string& str_category,
343  UInt32 un_seed) {
344  CHECK_CATEGORY(str_category);
345  itCategory->second->SetSeed(un_seed);
346  }
347 
348  /****************************************/
349  /****************************************/
350 
351  void CRandom::Reset() {
352  for(std::map<std::string, CCategory*>::iterator itCategory = m_mapCategories.begin();
353  itCategory != m_mapCategories.end();
354  ++itCategory) {
355  itCategory->second->ResetRNGs();
356  }
357  }
358 
359  /****************************************/
360  /****************************************/
361 
362 }
The RNG.
Definition: rng.h:90
bool Bernoulli(Real f_true=0.5)
Returns a random value from a Bernoulli distribution.
Definition: rng.cpp:80
signed int SInt32
32-bit signed integer.
Definition: datatypes.h:93
void ResetRNGs()
Resets the RNGs in this category.
Definition: rng.cpp:254
#define Sqrt
Definition: general.h:64
virtual ~CCategory()
Class destructor.
Definition: rng.cpp:225
float Real
Collects all ARGoS code.
Definition: datatypes.h:39
static UInt32 GetSeedOf(const std::string &str_category)
Returns the seed of the wanted category.
Definition: rng.cpp:334
Real Lognormal(Real f_sigma, Real f_mu)
Returns a random value from a Lognormal distribution.
Definition: rng.cpp:167
void ReseedRNGs()
Sets new seed for the RNGs in this category.
Definition: rng.cpp:267
The RNG category.
Definition: rng.h:222
#define M(row, col)
void Reset()
Reset the RNG.
Definition: rng.cpp:68
virtual ~CRNG()
Class destructor.
Definition: rng.cpp:61
It defines the basic type CRadians, used to store an angle value in radians.
Definition: angles.h:42
STL namespace.
static void Reset()
Resets all the RNG categories.
Definition: rng.cpp:351
unsigned int UInt32
32-bit unsigned integer.
Definition: datatypes.h:97
CRadians Uniform(const CRange< CRadians > &c_range)
Returns a random value from a uniform distribution.
Definition: rng.cpp:87
#define CHECK_CATEGORY(category)
Definition: rng.cpp:32
CRNG(UInt32 un_seed)
Class constructor.
Definition: rng.cpp:41
CCategory(const std::string &str_id, UInt32 un_seed)
Class constructor.
Definition: rng.cpp:215
CRNG * CreateRNG()
Creates a new RNG inside this category.
Definition: rng.cpp:243
static void RemoveCategory(const std::string &str_category)
Removes the wanted category.
Definition: rng.cpp:317
static CCategory & GetCategory(const std::string &str_category)
Returns a reference to the wanted category.
Definition: rng.cpp:296
The exception that wraps all errors in ARGoS.
static bool ExistsCategory(const std::string &str_category)
Returns true if the given category exists in the pool.
Definition: rng.cpp:304
Real Exponential(Real f_mean)
Returns a random value from an exponential distribution.
Definition: rng.cpp:123
Real Gaussian(Real f_std_dev, Real f_mean=0.0f)
Returns a random value from a Gaussian distribution.
Definition: rng.cpp:131
static CRNG * CreateRNG(const std::string &str_category)
Creates a new RNG inside the given category.
Definition: rng.cpp:326
#define Log
Definition: general.h:63
bool WithinMinBoundExcludedMaxBoundExcluded(const T &t_value) const
Definition: range.h:93
void SetSeed(UInt32 un_seed)
Sets the new seed of the category.
Definition: rng.cpp:235
static bool CreateCategory(const std::string &str_category, UInt32 un_seed)
Creates a new category.
Definition: rng.cpp:277
The namespace containing all the ARGoS related code.
Definition: ci_actuator.h:12
Real Rayleigh(Real f_sigma)
Returns a random value from a Rayleigh distribution.
Definition: rng.cpp:150
static void SetSeedOf(const std::string &str_category, UInt32 un_seed)
Sets the new seed of the wanted category.
Definition: rng.cpp:342