random.cc
1 #include "icemc_random.h"
2 #include "TUUID.h"
3 #include "TRandom3.h"
4 
5 #if ROOT_VERSION_CODE >= ROOT_VERSION(6,8,0)
6 #include "TRandomGen.h"
7 #endif
8 
9 ClassImp(TRandomXoshiro256Plus);
10 
11 
12 
19 static ULong_t next_ran_splitmix64(ULong_t x)
20 {
21  ULong_t z = (x += 0x9e3779b97f4a7c15);
22  z = (z ^ (z >> 30)) * 0xbf58476d1ce4e5b9;
23  z = (z ^ (z >> 27)) * 0x94d049bb133111eb;
24  return z ^ (z >> 31);
25 }
26 
27 /* see http://xoshiro.di.unimi.it/xoshiro256plus.c */
28 static inline ULong_t rotl(const ULong_t x, int k)
29 {
30  return (x << k) | (x >> (64-k));
31 
32 }
33 
34 /* Note that unlike in the reference implementation, we increment the state then return the new value
35  * This is to avoid seeding of the state with e.g. run,event causing problems!
36  **/
37 ULong_t TRandomXoshiro256Plus::RawRndm()
38 {
39  const ULong_t t = fState[1] << 17;
40  fState[2] ^= fState[0];
41  fState[3] ^= fState[1];
42  fState[1] ^= fState[2];
43  fState[0] ^= fState[3];
44  fState[2] ^= t;
45  fState[3] = rotl(fState[3],45);
46 
47  return fState[0] + fState[3];
48 }
49 
50 Double_t TRandomXoshiro256Plus::Rndm()
51 {
52  const Double_t inv_max = 1./(1ull << 53);
53  return (RawRndm() >> 11) * inv_max;
54 }
55 
56 void TRandomXoshiro256Plus::SetSeed(ULong_t seed)
57 {
58  if (seed == 0)
59  {
60  TUUID uuid;
61  uuid.GetUUID( (UChar_t*) fState);
62  TUUID uuid2;
63  uuid2.GetUUID( ((UChar_t*) fState) + 16);
64  }
65  else
66  {
67  fState[0] = next_ran_splitmix64(seed);
68  fState[1] = next_ran_splitmix64(fState[0]);
69  fState[2] = next_ran_splitmix64(fState[1]);
70  fState[3] = next_ran_splitmix64(fState[2]);
71  }
72 }
73 
74 
75 
76 void TRandomXoshiro256Plus::RndmArray(Int_t n, Float_t * arr)
77 {
78  const Float_t inv_max = 1./(1ul << 24);
79  for (Int_t i = 0; i < n/2; i++)
80  {
81  arr[2*i] = ((RawRndm() >> 16) & 0xffffff) *inv_max;
82  arr[2*i+1] = (RawRndm() >>40) *inv_max;
83  }
84 
85  //we have one left over...
86  if (n % 2) arr[n-1] = (RawRndm() >>40) *inv_max;
87 
88 }
89 
90 void TRandomXoshiro256Plus::RndmArray(Int_t n, Double_t * arr)
91 {
92  const Double_t inv_max = 1./(1ull << 53);
93  for (Int_t i = 0; i < n; i++) arr[i] = (RawRndm()>>11) *inv_max;
94 }
95 
96 
97 
98 
99 static ULong_t the_seed = 12345;
100 static WhichIceMcRNGType the_rng_type;
101 static TRandom* rngs[HOW_MANY_RNGS_DO_WE_HAVE];
102 
103 
105 {
106  public:
108  {
109  setRNGType(RNG_TYPE_XOSHIRO256PLUS);
110  }
111 };
112 
113 static random_initializer initializer;
114 
115 
116 WhichIceMcRNGType getRNGType() { return the_rng_type; }
117 
118 void setRNGType(WhichIceMcRNGType type)
119 {
120  the_rng_type = type;
121 
122  for (unsigned i = 0; i < HOW_MANY_RNGS_DO_WE_HAVE; i++)
123  {
124  if (rngs[i]) delete rngs[i];
125 
126  rngs[i] = type == RNG_TYPE_XOSHIRO256PLUS ? (TRandom*) new TRandomXoshiro256Plus(the_seed) :
127 #if ROOT_VERSION_CODE >= ROOT_VERSION(6,8,0)
128  type == RNG_TYPE_MT64 ? (TRandom*) new TRandomMT64 :
129  type == RNG_TYPE_MIXMAX256 ? (TRandom*) new TRandomMixMax256 :
130 #endif
131  (TRandom*) new TRandom3;
132  }
133 }
134 
135 
136 void setSeed(ULong_t s)
137 {
138  the_seed = s;
139  for (unsigned i = 0; i <HOW_MANY_RNGS_DO_WE_HAVE; i++) rngs[i]->SetSeed(s + i * 1235); //each gets a different seed derived from the primary.
140 }
141 
142 
143 TRandom * getRNG(WhichIceMcRNG w)
144 {
145  return rngs[w];
146 }
147 
148