Belle II Software  release-08-01-10
RandomGenerator.h
1 /**************************************************************************
2  * basf2 (Belle II Analysis Software Framework) *
3  * Author: The Belle II Collaboration *
4  * *
5  * See git log for contributors and copyright holders. *
6  * This file is licensed under LGPL-3.0, see LICENSE.md. *
7  **************************************************************************/
8 
9 #pragma once
10 
11 #include <stdint.h>
12 #include <TRandom.h>
13 #include <vector>
14 
15 namespace Belle2 {
37  class RandomGenerator: public TRandom {
38  public:
48  };
49 
51  explicit RandomGenerator(const std::string& name = "Belle2 Random Generator");
52 
54  virtual ~RandomGenerator() {}
55 
65  void setSeed(const unsigned char* seed, unsigned int n);
66 
68  void setMode(EGeneratorMode mode) { m_mode = mode; }
69 
71  EGeneratorMode getMode() const { return m_mode; }
72 
74  const std::vector<unsigned char>& getSeed() const { return m_seed; }
75 
80  void initialize() { setState(0); }
81 
86  void barrier() { setState(m_barrier + 1); }
87 
89  void setBarrier(int barrierIndex) { setState(barrierIndex); }
90 
92  int getBarrier() const { return m_barrier; }
93 
98  uint64_t random64();
99 
104  uint32_t random32() { return random64() >> 32; }
105 
109  double random01();
110 
112  Double_t Rndm() { return random01(); }
114  Double_t Rndm(Int_t) { return Rndm(); }
119  void RndmArray(Int_t n, Float_t* array);
124  void RndmArray(Int_t n, Double_t* array);
130  void RndmArray(Int_t n, ULong64_t* array);
131 
137  void RndmArray(Int_t n, UInt_t* array);
138 
144  void RndmArray(Int_t n, Int_t* array) { RndmArray(n, (UInt_t*) array); }
145 
151  void RndmArray(Int_t n, Long64_t* array) { RndmArray(n, (ULong64_t*) array); }
152 
157  void RndmArray(Int_t n, unsigned char* array);
158  private:
161  void SetSeed(UInt_t) {}
163  void SetSeed(ULong_t) {}
164 
179  void setState(int barrier);
180 
182  uint64_t m_state[16];
184  unsigned int m_index;
190  std::vector<unsigned char> m_seed;
198  };
199 
200  inline uint64_t RandomGenerator::random64()
201  {
202  //Generate random number using magic, taken from [arXiv:1402.6246] and only
203  //changed to conform to naming scheme
204  uint64_t s0 = m_state[ m_index ];
205  uint64_t s1 = m_state[ m_index = (m_index + 1) & 15 ];
206  s1 ^= s1 << 31;
207  s1 ^= s1 >> 11;
208  s0 ^= s0 >> 30;
209  return (m_state[ m_index ] = s0 ^ s1) * 1181783497276652981LL;
210  }
211 
212  inline void RandomGenerator::RndmArray(Int_t n, Float_t* array)
213  {
214  //We could optimize this more thoroughly since one 64bit random int is
215  //enough to generate two floats but this would probably be rather academic
216  for (int i = 0; i < n; ++i) array[i] = random01();
217  }
218 
219  inline void RandomGenerator::RndmArray(Int_t n, Double_t* array)
220  {
221  //Fill the array, no optimization whatsoever necessary
222  for (int i = 0; i < n; ++i) array[i] = random01();
223  }
224 
225  inline void RandomGenerator::RndmArray(Int_t n, ULong64_t* array)
226  {
227  //Fill the array, no optimization whatsoever necessary
228  for (int i = 0; i < n; ++i) array[i] = random64();
229  }
230 
231  inline void RandomGenerator::RndmArray(Int_t n, UInt_t* array)
232  {
233  //Fill the most part of the array using 64bit numbers
234  RndmArray(n / 2, (ULong64_t*)array);
235  //Only for uneven number of elements we need to fill the last one using a
236  //32bit number
237  if (n % 2) array[n - 1] = random32();
238  }
239 
241  {
242  // There are two possibilities to generate a uniform double between 0 and
243  // 1: multiply the integer by a constant or exploit the double
244  // representation and use some bit shift magic. We have both implementation
245  // here and they seem to produce the exact same output so we stick with the
246  // more readable one but leave the bitshift solution just in case
247 #ifdef RANDOM_IEEE754
248  //Generate a double in (0,1) using magic bit hackery with doubles: The
249  //memory layout of a IEEE754 double precision floating point variable
250  //is [sign(1)|exponent(11)|fraction(52)] with values in parentheses
251  //being the number of bits. The actual value is then
252  //-1^{sign} * (1.fraction) * 2^{exponent-1023}. Setting sign to 0 the
253  //exponent to 1023 will thus return a value between 1 (inclusive) and 2
254  //(exclusive). So we shift the 64bit integer to the right by 12 bits
255  //(which gives as zeros for sign and exponent) and logical or this with
256  //the correct binary representation of the exponent
257 
258  //To do this we use a union to modify the binary representation using
259  //an integer and then return the double value
260  union { uint64_t i; double d; } x;
261  x.i = random64() >> 12;
262  //This is a bit academic but we want (0,1) so if we happen to get
263  //exactly zero we try again. Chance is 1 in 2^52
264  if (x.i == 0) return random01();
265  x.i |= 0x3FF0000000000000ULL;
266  return x.d - 1.0;
267 #else
268  //Generate a double (0,1) the traditional way by multiplying it with a
269  //constant. As doubles only have a precision of 52 bits we need to
270  //remove the 12 leading bits from our random int value
271  const uint64_t x = random64() >> 12;
272  //This is a bit academic but we want (0,1) so if we happen to get
273  //exactly zero we try again. Chance is 1 in 2^52
274  if (!x) return random01();
275  //return x / 2^{52};
276  return x * 2.220446049250313080847263336181640625e-16;
277 #endif
278  }
280 }
Fast Random number Generator using on xorshift1024* [arXiv:1402.6246].
void RndmArray(Int_t n, Long64_t *array)
Fill an array of 64bit integers with random values in [INT64_MIN, INT64_MAX], both limits included.
void setState(int barrier)
Set the state of the random number generator.
void setBarrier(int barrierIndex)
manually set the barrier index to a fixed value
EGeneratorMode
Generator mode: determines which information is used to generate the internal state.
@ c_runDependent
Use experiment and run number to generate state.
@ c_eventDependent
Use experiment, run and event number to generate state.
@ c_independent
Don't use event info to generate state.
uint64_t m_state[16]
Internal state of the random number generator.
Double_t Rndm(Int_t)
Generate a random value in (0,1), both limits excluded (backward compatibility with root < 6....
void initialize()
set the State from event meta information like experiment, run, and event number.
ClassDef(RandomGenerator, 2)
and the root dictionary macro needs to be documented as well :) Version 2: merge m_eventDependent and...
int getBarrier() const
obtain the currently active barrier id
Double_t Rndm()
Generate a random value in (0,1), both limits excluded.
void RndmArray(Int_t n, Int_t *array)
Fill an array of 32bit integers with random values in [INT32_MIN, INT32_MAX], both limits included.
unsigned int m_index
currently active index in the internal state
int m_barrier
current barrier index.
EGeneratorMode m_mode
Current generator mode.
EGeneratorMode getMode() const
Get the generator mode.
void setSeed(const unsigned char *seed, unsigned int n)
Set the seed information.
std::vector< unsigned char > m_seed
seed information
void setMode(EGeneratorMode mode)
Set the generator mode.
void SetSeed(UInt_t)
override base class SetSeed to do nothing, we don't need it but it gets called by parent constructor
uint32_t random32()
Generate one 32bit unsigned integer between 0 and UINT32_MAX (both inclusive)
RandomGenerator(const std::string &name="Belle2 Random Generator")
Default constructor, does not initialize the generator.
virtual ~RandomGenerator()
Destructor to free the seed information.
const std::vector< unsigned char > & getSeed() const
return the seed object
void SetSeed(ULong_t)
argument type was changed in root 6.08.
void barrier()
increase the barrier index.
double random01()
Generate a random double value between 0 and 1, both limits excluded.
uint64_t random64()
Generate one 64bit unsigned integer between 0 and UINT64_MAX (both inclusive).
void RndmArray(Int_t n, Float_t *array)
Fill an array of floats with random values in (0,1), both limits excluded.
Abstract base class for different kinds of events.