Belle II Software  release-05-02-19
RandomGenerator.h
1 /**************************************************************************
2  * BASF2 (Belle Analysis Framework 2) *
3  * Copyright(C) 2015 - Belle II Collaboration *
4  * *
5  * Author: The Belle II Collaboration *
6  * Contributors: Martin Ritter *
7  * *
8  * This software is provided "as is" without any warranty. *
9  **************************************************************************/
10 
11 #pragma once
12 
13 #include <stdint.h>
14 #include <TRandom.h>
15 #include <vector>
16 
17 namespace Belle2 {
39  class RandomGenerator: public TRandom {
40  public:
43  enum EGeneratorMode {
50  };
51 
53  explicit RandomGenerator(const std::string& name = "Belle2 Random Generator");
54 
56  virtual ~RandomGenerator() {}
57 
67  void setSeed(const unsigned char* seed, unsigned int n);
68 
70  void setMode(EGeneratorMode mode) { m_mode = mode; }
71 
73  EGeneratorMode getMode() const { return m_mode; }
74 
76  const std::vector<unsigned char>& getSeed() const { return m_seed; }
77 
82  void initialize() { setState(0); }
83 
88  void barrier() { setState(m_barrier + 1); }
89 
91  void setBarrier(int barrierIndex) { setState(barrierIndex); }
92 
94  int getBarrier() const { return m_barrier; }
95 
100  uint64_t random64();
101 
106  uint32_t random32() { return random64() >> 32; }
107 
111  double random01();
112 
114  Double_t Rndm() { return random01(); }
116  Double_t Rndm(Int_t) { return Rndm(); }
121  void RndmArray(Int_t n, Float_t* array);
126  void RndmArray(Int_t n, Double_t* array);
132  void RndmArray(Int_t n, ULong64_t* array);
133 
139  void RndmArray(Int_t n, UInt_t* array);
140 
146  void RndmArray(Int_t n, Int_t* array) { RndmArray(n, (UInt_t*) array); }
147 
153  void RndmArray(Int_t n, Long64_t* array) { RndmArray(n, (ULong64_t*) array); }
154 
159  void RndmArray(Int_t n, unsigned char* array);
160  private:
163  void SetSeed(UInt_t) {}
165  void SetSeed(ULong_t) {}
166 
181  void setState(int barrier);
182 
184  uint64_t m_state[16];
186  unsigned int m_index;
190  int m_barrier;
192  std::vector<unsigned char> m_seed;
200  };
201 
202  inline uint64_t RandomGenerator::random64()
203  {
204  //Generate random number using magic, taken from [arXiv:1402.6246] and only
205  //changed to conform to naming scheme
206  uint64_t s0 = m_state[ m_index ];
207  uint64_t s1 = m_state[ m_index = (m_index + 1) & 15 ];
208  s1 ^= s1 << 31;
209  s1 ^= s1 >> 11;
210  s0 ^= s0 >> 30;
211  return (m_state[ m_index ] = s0 ^ s1) * 1181783497276652981LL;
212  }
213 
214  inline void RandomGenerator::RndmArray(Int_t n, Float_t* array)
215  {
216  //We could optimize this more thoroughly since one 64bit random int is
217  //enough to generate two floats but this would probably be rather academic
218  for (int i = 0; i < n; ++i) array[i] = random01();
219  }
220 
221  inline void RandomGenerator::RndmArray(Int_t n, Double_t* array)
222  {
223  //Fill the array, no optimization whatsoever necessary
224  for (int i = 0; i < n; ++i) array[i] = random01();
225  }
226 
227  inline void RandomGenerator::RndmArray(Int_t n, ULong64_t* array)
228  {
229  //Fill the array, no optimization whatsoever necessary
230  for (int i = 0; i < n; ++i) array[i] = random64();
231  }
232 
233  inline void RandomGenerator::RndmArray(Int_t n, UInt_t* array)
234  {
235  //Fill the most part of the array using 64bit numbers
236  RndmArray(n / 2, (ULong64_t*)array);
237  //Only for uneven number of elements we need to fill the last one using a
238  //32bit number
239  if (n % 2) array[n - 1] = random32();
240  }
241 
242  inline double RandomGenerator::random01()
243  {
244  // There are two possibilities to generate a uniform double between 0 and
245  // 1: multiply the integer by a constant or exploit the double
246  // representation and use some bit shift magic. We have both implementation
247  // here and they seem to produce the exact same output so we stick with the
248  // more readable one but leave the bitshift solution just in case
249 #ifdef RANDOM_IEEE754
250  //Generate a double in (0,1) using magic bit hackery with doubles: The
251  //memory layout of a IEEE754 double precision floating point variable
252  //is [sign(1)|exponent(11)|fraction(52)] with values in parentheses
253  //being the number of bits. The actual value is then
254  //-1^{sign} * (1.fraction) * 2^{exponent-1023}. Setting sign to 0 the
255  //exponent to 1023 will thus return a value between 1 (inclusive) and 2
256  //(exclusive). So we shift the 64bit integer to the right by 12 bits
257  //(which gives as zeros for sign and exponent) and logical or this with
258  //the correct binary representation of the exponent
259 
260  //To do this we use a union to modify the binary representation using
261  //an integer and then return the double value
262  union { uint64_t i; double d; } x;
263  x.i = random64() >> 12;
264  //This is a bit academic but we want (0,1) so if we happen to get
265  //exactly zero we try again. Chance is 1 in 2^52
266  if (x.i == 0) return random01();
267  x.i |= 0x3FF0000000000000ULL;
268  return x.d - 1.0;
269 #else
270  //Generate a double (0,1) the traditional way by multiplying it with a
271  //constant. As doubles only have a precision of 52 bits we need to
272  //remove the 12 leading bits from our random int value
273  const uint64_t x = random64() >> 12;
274  //This is a bit academic but we want (0,1) so if we happen to get
275  //exactly zero we try again. Chance is 1 in 2^52
276  if (!x) return random01();
277  //return x / 2^{52};
278  return x * 2.220446049250313080847263336181640625e-16;
279 #endif
280  }
282 }
Belle2::RandomGenerator::c_independent
@ c_independent
Don't use event info to generate state.
Definition: RandomGenerator.h:53
Belle2::RandomGenerator::c_runDependent
@ c_runDependent
Use experiment and run number to generate state.
Definition: RandomGenerator.h:55
Belle2::RandomGenerator::getMode
EGeneratorMode getMode() const
Get the generator mode.
Definition: RandomGenerator.h:81
Belle2::RandomGenerator::RandomGenerator
RandomGenerator(const std::string &name="Belle2 Random Generator")
Default constructor, does not initialize the generator.
Definition: RandomGenerator.cc:37
Belle2::RandomGenerator::random32
uint32_t random32()
Generate one 32bit unsigned integer between 0 and UINT32_MAX (both inclusive)
Definition: RandomGenerator.h:114
Belle2::RandomGenerator::c_eventDependent
@ c_eventDependent
Use experiment, run and event number to generate state.
Definition: RandomGenerator.h:57
Belle2::RandomGenerator::~RandomGenerator
virtual ~RandomGenerator()
Destructor to free the seed information.
Definition: RandomGenerator.h:64
Belle2::RandomGenerator::setState
void setState(int barrier)
Set the state of the random number generator.
Definition: RandomGenerator.cc:53
Belle2::RandomGenerator
Fast Random number Generator using on xorshift1024* [arXiv:1402.6246].
Definition: RandomGenerator.h:47
Belle2::RandomGenerator::m_seed
std::vector< unsigned char > m_seed
seed information
Definition: RandomGenerator.h:200
Belle2::RandomGenerator::setBarrier
void setBarrier(int barrierIndex)
manually set the barrier index to a fixed value
Definition: RandomGenerator.h:99
Belle2::RandomGenerator::m_mode
EGeneratorMode m_mode
Current generator mode.
Definition: RandomGenerator.h:202
Belle2::RandomGenerator::random64
uint64_t random64()
Generate one 64bit unsigned integer between 0 and UINT64_MAX (both inclusive).
Definition: RandomGenerator.h:210
Belle2
Abstract base class for different kinds of events.
Definition: MillepedeAlgorithm.h:19
Belle2::RandomGenerator::SetSeed
void SetSeed(UInt_t)
override base class SetSeed to do nothing, we don't need it but it gets called by parent constructor
Definition: RandomGenerator.h:171
Belle2::RandomGenerator::ClassDef
ClassDef(RandomGenerator, 2)
and the root dictionary macro needs to be documented as well :) Version 2: merge m_eventDependent and...
Belle2::RandomGenerator::getSeed
const std::vector< unsigned char > & getSeed() const
return the seed object
Definition: RandomGenerator.h:84
Belle2::RandomGenerator::random01
double random01()
Generate a random double value between 0 and 1, both limits excluded.
Definition: RandomGenerator.h:250
Belle2::RandomGenerator::setSeed
void setSeed(const unsigned char *seed, unsigned int n)
Set the seed information.
Definition: RandomGenerator.cc:44
Belle2::RandomGenerator::m_index
unsigned int m_index
currently active index in the internal state
Definition: RandomGenerator.h:194
Belle2::RandomGenerator::Rndm
Double_t Rndm()
Generate a random value in (0,1), both limits excluded.
Definition: RandomGenerator.h:122
Belle2::RandomGenerator::EGeneratorMode
EGeneratorMode
Generator mode: determines which information is used to generate the internal state.
Definition: RandomGenerator.h:51
Belle2::RandomGenerator::RndmArray
void RndmArray(Int_t n, Float_t *array)
Fill an array of floats with random values in (0,1), both limits excluded.
Definition: RandomGenerator.h:222
Belle2::RandomGenerator::m_state
uint64_t m_state[16]
Internal state of the random number generator.
Definition: RandomGenerator.h:192
Belle2::RandomGenerator::m_barrier
int m_barrier
current barrier index.
Definition: RandomGenerator.h:198
Belle2::RandomGenerator::setMode
void setMode(EGeneratorMode mode)
Set the generator mode.
Definition: RandomGenerator.h:78
Belle2::RandomGenerator::initialize
void initialize()
set the State from event meta information like experiment, run, and event number.
Definition: RandomGenerator.h:90
Belle2::RandomGenerator::getBarrier
int getBarrier() const
obtain the currently active barrier id
Definition: RandomGenerator.h:102
Belle2::RandomGenerator::barrier
void barrier()
increase the barrier index.
Definition: RandomGenerator.h:96