Geant4  v4-10.4-release
 모두 클래스 네임스페이스들 파일들 함수 변수 타입정의 열거형 타입 열거형 멤버 Friends 매크로 그룹들 페이지들
MixMaxRng.cc
이 파일의 문서화 페이지로 가기
1 //
2 // -*- C++ -*-
3 //
4 // -----------------------------------------------------------------------
5 // HEP Random
6 // --- MixMaxRng ---
7 // class implementation file
8 // -----------------------------------------------------------------------
9 //
10 // This file interfaces the MixMax PseudoRandom Number Generator
11 // proposed by:
12 //
13 // G.K.Savvidy and N.G.Ter-Arutyunian,
14 // On the Monte Carlo simulation of physical systems,
15 // J.Comput.Phys. 97, 566 (1991);
16 // Preprint EPI-865-16-86, Yerevan, Jan. 1986
17 // http://dx.doi.org/10.1016/0021-9991(91)90015-D
18 //
19 // K.Savvidy
20 // "The MIXMAX random number generator"
21 // Comp. Phys. Commun. (2015)
22 // http://dx.doi.org/10.1016/j.cpc.2015.06.003
23 //
24 // K.Savvidy and G.Savvidy
25 // "Spectrum and Entropy of C-systems. MIXMAX random number generator"
26 // Chaos, Solitons & Fractals, Volume 91, (2016) pp. 33-38
27 // http://dx.doi.org/10.1016/j.chaos.2016.05.003
28 //
29 // =======================================================================
30 // Implementation by Konstantin Savvidy - Copyright 2004-2017
31 // =======================================================================
32 
33 #include "CLHEP/Random/Random.h"
34 #include "CLHEP/Random/MixMaxRng.h"
37 
38 #include <string.h> // for strcmp
39 #include <cmath>
40 
41 const unsigned long MASK32=0xffffffff;
42 
43 namespace CLHEP {
44 
45 namespace {
46  // Number of instances with automatic seed selection
47  CLHEP_ATOMIC_INT_TYPE numberOfEngines(0);
48 }
49 
50 static const int MarkerLen = 64; // Enough room to hold a begin or end marker.
51 
54 {
55  int numEngines = ++numberOfEngines;
56  setSeed(static_cast<long>(numEngines));
57 }
58 
61 {
62  theSeed=seed;
63  setSeed(seed);
64 }
65 
66 MixMaxRng::MixMaxRng(std::istream& is)
68 {
69  get(is);
70 }
71 
73 {
74 }
75 
77  : HepRandomEngine(rng)
78 {
79  S.V = rng.S.V;
80  S.sumtot= rng.S.sumtot;
81  S.counter= rng.S.counter;
82 }
83 
85 {
86  // Check assignment to self
87  //
88  if (this == &rng) { return *this; }
89 
90  // Copy base class data
91  //
92  HepRandomEngine::operator=(rng);
93 
94  S.V = rng.S.V;
95  S.sumtot= rng.S.sumtot;
96  S.counter= rng.S.counter;
97 
98  return *this;
99 }
100 
101 void MixMaxRng::saveStatus( const char filename[] ) const
102 {
103  // Create a C file-handle or an object that can accept the same output
104  FILE *fh= fopen(filename, "w");
105  if( fh )
106  {
107  int j;
108  fprintf(fh, "mixmax state, file version 1.0\n" );
109  fprintf(fh, "N=%u; V[N]={", rng_get_N() );
110  for (j=0; (j< (rng_get_N()-1) ); j++) {
111  fprintf(fh, "%llu, ", S.V[j] );
112  }
113  fprintf(fh, "%llu", S.V[rng_get_N()-1] );
114  fprintf(fh, "}; " );
115  fprintf(fh, "counter=%u; ", S.counter );
116  fprintf(fh, "sumtot=%llu;\n", S.sumtot );
117  fclose(fh);
118  }
119 }
120 
121 #define MIXMAX_ARRAY_INDEX_OUT_OF_BOUNDS 0xFF01
122 #define MIXMAX_SEED_WAS_ZERO 0xFF02
123 #define MIXMAX_ERROR_READING_STATE_FILE 0xFF03
124 #define MIXMAX_ERROR_READING_STATE_COUNTER 0xFF04
125 #define MIXMAX_ERROR_READING_STATE_CHECKSUM 0xFF05
126 
127 void MixMaxRng::restoreStatus( const char filename[] )
128 {
129  // a function for reading the state from a file
130  FILE* fin;
131  if( ( fin = fopen(filename, "r") ) )
132  {
133  char l=0;
134  while ( l != '{' ) { // 0x7B = "{"
135  l=fgetc(fin); // proceed until hitting opening bracket
136  }
137  ungetc(' ', fin);
138  }
139  else
140  {
141  fprintf(stderr, "mixmax -> read_state: error reading file %s\n", filename);
143  }
144 
145  myuint_t vecVal;
146  //printf("mixmax -> read_state: starting to read state from file\n");
147  if (!fscanf(fin, "%llu", &S.V[0]) )
148  {
149  fprintf(stderr, "mixmax -> read_state: error reading file %s\n", filename);
151  }
152 
153  int i;
154  for( i = 1; i < rng_get_N(); i++)
155  {
156  if (!fscanf(fin, ", %llu", &vecVal) )
157  {
158  fprintf(stderr, "mixmax -> read_state: error reading vector component i=%d from file %s\n", i, filename);
160  }
161  if( vecVal <= MixMaxRng::M61 )
162  {
163  S.V[i] = vecVal;
164  }
165  else
166  {
167  fprintf(stderr, "mixmax -> read_state: Invalid state vector value= %llu"
168  " ( must be less than %llu ) "
169  " obtained from reading file %s\n"
170  , vecVal, MixMaxRng::M61, filename);
171  }
172  }
173 
174  int counter;
175  if (!fscanf( fin, "}; counter=%i; ", &counter))
176  {
177  fprintf(stderr, "mixmax -> read_state: error reading counter from file %s\n", filename);
179  }
180  if( counter <= rng_get_N() )
181  {
182  S.counter= counter;
183  }
184  else
185  {
186  fprintf(stderr, "mixmax -> read_state: Invalid counter = %d"
187  " Must be 0 <= counter < %u\n" , counter, rng_get_N());
188  print_state();
190  }
191  precalc();
192  myuint_t sumtot;
193  if (!fscanf( fin, "sumtot=%llu\n", &sumtot))
194  {
195  fprintf(stderr, "mixmax -> read_state: error reading checksum from file %s\n", filename);
197  }
198 
199  if (S.sumtot != sumtot)
200  {
201  fprintf(stderr, "mixmax -> checksum error while reading state from file %s - corrupted?\n", filename);
203  }
204  fclose(fin);
205 }
206 
207 #undef MIXMAX_ARRAY_INDEX_OUT_OF_BOUNDS
208 #undef MIXMAX_SEED_WAS_ZERO
209 #undef MIXMAX_ERROR_READING_STATE_FILE
210 #undef MIXMAX_ERROR_READING_STATE_COUNTER
211 #undef MIXMAX_ERROR_READING_STATE_CHECKSUM
212 
214 {
215  std::cout << std::endl;
216  std::cout << "------- MixMaxRng engine status -------" << std::endl;
217 
218  std::cout << " Current state vector is:" << std::endl;
219  print_state();
220  std::cout << "---------------------------------------" << std::endl;
221 }
222 
223 void MixMaxRng::setSeed(long longSeed, int /* extraSeed */)
224 {
225  //seed_uniquestream(0,0,0,longSeed);
226  theSeed = longSeed;
227  seed_spbox(longSeed);
228 }
229 
230 // Preferred Seeding method
231 // the values of 'Seeds' must be valid 32-bit integers
232 // Higher order bits will be ignored!!
233 
234 void MixMaxRng::setSeeds(const long* Seeds, int seedNum)
235 {
236  unsigned long seed0, seed1= 0, seed2= 0, seed3= 0;
237 
238  if( seedNum < 1 ) { // Assuming at least 2 seeds in vector...
239  seed0= static_cast<unsigned long>(Seeds[0]) & MASK32;
240  seed1= static_cast<unsigned long>(Seeds[1]) & MASK32;
241  }
242  else
243  {
244  if( seedNum < 4 ) {
245  seed0= static_cast<unsigned long>(Seeds[0]) & MASK32;
246  if( seedNum > 1){ seed1= static_cast<unsigned long>(Seeds[1]) & MASK32; }
247  if( seedNum > 2){ seed2= static_cast<unsigned long>(Seeds[2]) & MASK32; }
248  }
249  if( seedNum >= 4 ) {
250  seed0= static_cast<unsigned long>(Seeds[0]) & MASK32;
251  seed1= static_cast<unsigned long>(Seeds[1]) & MASK32;
252  seed2= static_cast<unsigned long>(Seeds[2]) & MASK32;
253  seed3= static_cast<unsigned long>(Seeds[3]) & MASK32;
254  }
255  }
256  theSeed = Seeds[0];
257  theSeeds = Seeds;
258  seed_uniquestream(seed3, seed2, seed1, seed0);
259 }
260 
262 {
263  return "MixMaxRng";
264 }
265 
266 constexpr int MixMaxRng::rng_get_N()
267 {
268  return N;
269 }
270 
271 constexpr long long int MixMaxRng::rng_get_SPECIAL()
272 {
273  return SPECIAL;
274 }
275 
277 {
278  return SPECIALMUL;
279 }
280 
281 double MixMaxRng::generate(int i)
282 {
283  S.counter++;
284 #if defined(__clang__) || defined(__llvm__)
285  return INV_M61*static_cast<double>(S.V[i]);
286 #elif defined(__GNUC__) && (__GNUC__ < 7) && (!defined(__ICC)) && defined(__x86_64__) && defined(__SSE2_MATH__)
287  int64_t Z=S.V[i];
288  double F=0.0;
289  //#warning Using the inline assembler
290  /* using SSE inline assemly to zero the xmm register, just before int64 -> double conversion,
291  not necessary in GCC-5 or better, but huge penalty on earlier compilers
292  */
293  __asm__ __volatile__( "pxor %0, %0;"
294  "cvtsi2sdq %1, %0;"
295  :"=x"(F)
296  :"r"(Z)
297  );
298  return F*INV_M61;
299 #else
300  //#warning other method
301  return convert1double(S.V[i]); //get_next_float_packbits();
302 #endif
303 }
304 
306 {
307  myuint_t* Y=S.V.data();
308  myuint_t tempP, tempV;
309  Y[0] = ( tempV = S.sumtot);
310  myuint_t sumtot = Y[0], ovflow = 0; // will keep a running sum of all new elements
311  tempP = 0; // will keep a partial sum of all old elements
312  myuint_t tempPO;
313  tempPO = MULWU(tempP); tempP = modadd(tempP, Y[1] ); tempV = MIXMAX_MOD_MERSENNE(tempV+tempP+tempPO); Y[1] = tempV; sumtot += tempV; if (sumtot < tempV) {ovflow++;};
314  tempPO = MULWU(tempP); tempP = modadd(tempP, Y[2] ); tempV = MIXMAX_MOD_MERSENNE(tempV+tempP+tempPO); Y[2] = tempV; sumtot += tempV; if (sumtot < tempV) {ovflow++;};
315  tempPO = MULWU(tempP); tempP = modadd(tempP, Y[3] ); tempV = MIXMAX_MOD_MERSENNE(tempV+tempP+tempPO); Y[3] = tempV; sumtot += tempV; if (sumtot < tempV) {ovflow++;};
316  tempPO = MULWU(tempP); tempP = modadd(tempP, Y[4] ); tempV = MIXMAX_MOD_MERSENNE(tempV+tempP+tempPO); Y[4] = tempV; sumtot += tempV; if (sumtot < tempV) {ovflow++;};
317  tempPO = MULWU(tempP); tempP = modadd(tempP, Y[5] ); tempV = MIXMAX_MOD_MERSENNE(tempV+tempP+tempPO); Y[5] = tempV; sumtot += tempV; if (sumtot < tempV) {ovflow++;};
318  tempPO = MULWU(tempP); tempP = modadd(tempP, Y[6] ); tempV = MIXMAX_MOD_MERSENNE(tempV+tempP+tempPO); Y[6] = tempV; sumtot += tempV; if (sumtot < tempV) {ovflow++;};
319  tempPO = MULWU(tempP); tempP = modadd(tempP, Y[7] ); tempV = MIXMAX_MOD_MERSENNE(tempV+tempP+tempPO); Y[7] = tempV; sumtot += tempV; if (sumtot < tempV) {ovflow++;};
320  tempPO = MULWU(tempP); tempP = modadd(tempP, Y[8] ); tempV = MIXMAX_MOD_MERSENNE(tempV+tempP+tempPO); Y[8] = tempV; sumtot += tempV; if (sumtot < tempV) {ovflow++;};
321  tempPO = MULWU(tempP); tempP = modadd(tempP, Y[9] ); tempV = MIXMAX_MOD_MERSENNE(tempV+tempP+tempPO); Y[9] = tempV; sumtot += tempV; if (sumtot < tempV) {ovflow++;};
322  tempPO = MULWU(tempP); tempP = modadd(tempP, Y[10]); tempV = MIXMAX_MOD_MERSENNE(tempV+tempP+tempPO); Y[10] = tempV; sumtot += tempV; if (sumtot < tempV) {ovflow++;};
323  tempPO = MULWU(tempP); tempP = modadd(tempP, Y[11]); tempV = MIXMAX_MOD_MERSENNE(tempV+tempP+tempPO); Y[11] = tempV; sumtot += tempV; if (sumtot < tempV) {ovflow++;};
324  tempPO = MULWU(tempP); tempP = modadd(tempP, Y[12]); tempV = MIXMAX_MOD_MERSENNE(tempV+tempP+tempPO); Y[12] = tempV; sumtot += tempV; if (sumtot < tempV) {ovflow++;};
325  tempPO = MULWU(tempP); tempP = modadd(tempP, Y[13]); tempV = MIXMAX_MOD_MERSENNE(tempV+tempP+tempPO); Y[13] = tempV; sumtot += tempV; if (sumtot < tempV) {ovflow++;};
326  tempPO = MULWU(tempP); tempP = modadd(tempP, Y[14]); tempV = MIXMAX_MOD_MERSENNE(tempV+tempP+tempPO); Y[14] = tempV; sumtot += tempV; if (sumtot < tempV) {ovflow++;};
327  tempPO = MULWU(tempP); tempP = modadd(tempP, Y[15]); tempV = MIXMAX_MOD_MERSENNE(tempV+tempP+tempPO); Y[15] = tempV; sumtot += tempV; if (sumtot < tempV) {ovflow++;};
328  tempPO = MULWU(tempP); tempP = modadd(tempP, Y[16]); tempV = MIXMAX_MOD_MERSENNE(tempV+tempP+tempPO); Y[16] = tempV; sumtot += tempV; if (sumtot < tempV) {ovflow++;};
329  S.sumtot = MIXMAX_MOD_MERSENNE(MIXMAX_MOD_MERSENNE(sumtot) + (ovflow <<3 ));
330 
331  S.counter=2;
332  return double(S.V[1])*INV_M61;
333 }
334 
335 void MixMaxRng::flatArray(const int size, double* vect )
336 {
337  // fill_array( S, size, arrayDbl );
338  for (int i=0; i<size; ++i) { vect[i] = flat(); }
339 }
340 
341 MixMaxRng::operator double()
342 {
343  return flat();
344 }
345 
346 MixMaxRng::operator float()
347 {
348  return float( flat() );
349 }
350 
351 MixMaxRng::operator unsigned int()
352 {
353  return static_cast<unsigned int>(get_next());
354  // clhep_get_next returns a 64-bit integer, of which the lower 61 bits
355  // are random and upper 3 bits are zero
356 }
357 
358 std::ostream & MixMaxRng::put ( std::ostream& os ) const
359 {
360  char beginMarker[] = "MixMaxRng-begin";
361  char endMarker[] = "MixMaxRng-end";
362 
363  int pr = os.precision(24);
364  os << beginMarker << " ";
365  os << theSeed << "\n";
366  for (int i=0; i<rng_get_N(); ++i) {
367  os << S.V[i] << "\n";
368  }
369  os << S.counter << "\n";
370  os << S.sumtot << "\n";
371  os << endMarker << "\n";
372  os.precision(pr);
373  return os;
374 }
375 
376 std::vector<unsigned long> MixMaxRng::put () const
377 {
378  std::vector<unsigned long> v;
379  v.push_back (engineIDulong<MixMaxRng>());
380  for (int i=0; i<rng_get_N(); ++i)
381  {
382  v.push_back(static_cast<unsigned long>(S.V[i] & MASK32));
383  // little-ended order on all platforms
384  v.push_back(static_cast<unsigned long>(S.V[i] >> 32 ));
385  // pack uint64 into a data structure which is 32-bit on some platforms
386  }
387  v.push_back(static_cast<unsigned long>(S.counter));
388  v.push_back(static_cast<unsigned long>(S.sumtot & MASK32));
389  v.push_back(static_cast<unsigned long>(S.sumtot >> 32));
390  return v;
391 }
392 
393 std::istream & MixMaxRng::get ( std::istream& is)
394 {
395  char beginMarker [MarkerLen];
396  is >> std::ws;
397  is.width(MarkerLen); // causes the next read to the char* to be <=
398  // that many bytes, INCLUDING A TERMINATION \0
399  // (Stroustrup, section 21.3.2)
400  is >> beginMarker;
401  if (strcmp(beginMarker,"MixMaxRng-begin")) {
402  is.clear(std::ios::badbit | is.rdstate());
403  std::cerr << "\nInput stream mispositioned or"
404  << "\nMixMaxRng state description missing or"
405  << "\nwrong engine type found." << std::endl;
406  return is;
407  }
408  return getState(is);
409 }
410 
411 std::string MixMaxRng::beginTag ()
412 {
413  return "MixMaxRng-begin";
414 }
415 
416 std::istream & MixMaxRng::getState ( std::istream& is )
417 {
418  char endMarker[MarkerLen];
419  is >> theSeed;
420  for (int i=0; i<rng_get_N(); ++i) is >> S.V[i];
421  is >> S.counter;
422  myuint_t checksum;
423  is >> checksum;
424  is >> std::ws;
425  is.width(MarkerLen);
426  is >> endMarker;
427  if (strcmp(endMarker,"MixMaxRng-end")) {
428  is.clear(std::ios::badbit | is.rdstate());
429  std::cerr << "\nMixMaxRng state description incomplete."
430  << "\nInput stream is probably mispositioned now.\n";
431  return is;
432  }
433  if ( S.counter < 0 || S.counter > rng_get_N() ) {
434  std::cerr << "\nMixMaxRng::getState(): "
435  << "vector read wrong value of counter from file!"
436  << "\nInput stream is probably mispositioned now.\n";
437  return is;
438  }
439  precalc();
440  if ( checksum != S.sumtot) {
441  std::cerr << "\nMixMaxRng::getState(): "
442  << "checksum disagrees with value stored in file!"
443  << "\nInput stream is probably mispositioned now.\n";
444  return is;
445  }
446  return is;
447 }
448 
449 bool MixMaxRng::get (const std::vector<unsigned long> & v)
450 {
451  if ((v[0] & 0xffffffffUL) != engineIDulong<MixMaxRng>()) {
452  std::cerr <<
453  "\nMixMaxRng::get(): vector has wrong ID word - state unchanged\n";
454  return false;
455  }
456  return getState(v);
457 }
458 
459 bool MixMaxRng::getState (const std::vector<unsigned long> & v)
460 {
461  if (v.size() != VECTOR_STATE_SIZE ) {
462  std::cerr <<
463  "\nMixMaxRng::getState(): vector has wrong length - state unchanged\n";
464  return false;
465  }
466  for (int i=1; i<2*rng_get_N() ; i=i+2) {
467  S.V[i/2]= ( (v[i] & MASK32) | ( (myuint_t)(v[i+1]) << 32 ) );
468  // unpack from a data structure which is 32-bit on some platforms
469  }
470  S.counter = v[2*rng_get_N()+1];
471  precalc();
472  if ( ( (v[2*rng_get_N()+2] & MASK32)
473  | ( (myuint_t)(v[2*rng_get_N()+3]) << 32 ) ) != S.sumtot) {
474  std::cerr << "\nMixMaxRng::getState(): vector has wrong checksum!"
475  << "\nInput vector is probably mispositioned now.\n";
476  return false;
477  }
478  return true;
479 }
480 
482 {
483  switch (N)
484  {
485  case 17:
486  return 0;
487  break;
488  case 8:
489  return 0;
490  break;
491  case 240:
492  return fmodmulM61( 0, SPECIAL , (k) );
493  break;
494  default:
495  std::cerr << "MIXMAX ERROR: " << "Disallowed value of parameter N\n";
496  std::terminate();
497  break;
498  }
499 }
500 
502 {
503  return (( (k)<<(SPECIALMUL) & M61) ^ ( (k) >> (BITS-SPECIALMUL)) );
504 }
505 
507 {
508  // operates with a raw vector, uses known sum of elements of Y
509  int i;
510 
511  myuint_t tempP, tempV;
512  Y[0] = ( tempV = sumtotOld);
513  myuint_t sumtot = Y[0], ovflow = 0; // will keep a running sum of all new elements
514  tempP = 0; // will keep a partial sum of all old elements
515  for (i=1; (i<N); i++)
516  {
517  myuint_t tempPO = MULWU(tempP);
518  tempP = modadd(tempP, Y[i]);
519  tempV = MIXMAX_MOD_MERSENNE(tempV+tempP+tempPO); // new Y[i] = old Y[i] + old partial * m
520  Y[i] = tempV;
521  sumtot += tempV; if (sumtot < tempV) {ovflow++;}
522  }
523  return MIXMAX_MOD_MERSENNE(MIXMAX_MOD_MERSENNE(sumtot) + (ovflow <<3 ));
524 }
525 
527 {
528  int i;
529  i=S.counter;
530 
531  if ((i<=(N-1)) )
532  {
533  S.counter++;
534  return S.V[i];
535  }
536  else
537  {
538  S.sumtot = iterate_raw_vec(S.V.data(), S.sumtot);
539  S.counter=2;
540  return S.V[1];
541  }
542 }
543 
545 {
546  int i;
547  myuint_t temp;
548  temp = 0;
549  for (i=0; i < N; i++){
550  temp = MIXMAX_MOD_MERSENNE(temp + S.V[i]);
551  }
552  S.sumtot = temp;
553  return temp;
554 }
555 
557 {
558  myuint_t Z=get_next();
559  return convert1double(Z);
560 }
561 
562 void MixMaxRng::seed_vielbein(unsigned int index)
563 {
564  int i;
565  if (index<N)
566  {
567  for (i=0; i < N; i++){
568  S.V[i] = 0;
569  }
570  S.V[index] = 1;
571  }
572  else
573  {
574  std::terminate();
575  }
576  S.counter = N; // set the counter to N if iteration should happen right away
577  S.sumtot = 1;
578 }
579 
580 #define MIXMAX_SEED_WAS_ZERO 0xFF02
581 
583 {
584  // a 64-bit LCG from Knuth line 26, in combination with a bit swap is used to seed
585 
586  const myuint_t MULT64=6364136223846793005ULL;
587  int i;
588 
589  myuint_t sumtot=0,ovflow=0;
590  if (seed == 0)
591  {
592  fprintf(stderr, " try seeding with nonzero seed next time!\n");
593  exit(MIXMAX_SEED_WAS_ZERO);
594  }
595 
596  myuint_t l = seed;
597 
598  for (i=0; i < N; i++){
599  l*=MULT64; l = (l << 32) ^ (l>>32);
600  S.V[i] = l & M61;
601  sumtot += S.V[(i)]; if (sumtot < S.V[(i)]) {ovflow++;}
602  }
603  S.counter = N; // set the counter to N if iteration should happen right away
604  S.sumtot = MIXMAX_MOD_MERSENNE(MIXMAX_MOD_MERSENNE(sumtot) + (ovflow <<3 ));
605 }
606 
607 #undef MIXMAX_SEED_WAS_ZERO
608 
609 void MixMaxRng::seed_uniquestream( myID_t clusterID, myID_t machineID, myID_t runID, myID_t streamID )
610 {
611  seed_vielbein(0);
612  S.sumtot = apply_bigskip(S.V.data(), S.V.data(), clusterID, machineID, runID, streamID );
613  S.counter = 1;
614 }
615 
616 myuint_t MixMaxRng::apply_bigskip( myuint_t* Vout, myuint_t* Vin, myID_t clusterID, myID_t machineID, myID_t runID, myID_t streamID )
617 {
618  /*
619  makes a derived state vector, Vout, from the mother state vector Vin
620  by skipping a large number of steps, determined by the given seeding ID's
621 
622  it is mathematically guaranteed that the substreams derived in this way from the SAME (!!!) Vin will not collide provided
623  1) at least one bit of ID is different
624  2) less than 10^100 numbers are drawn from the stream
625  (this is good enough : a single CPU will not exceed this in the lifetime of the universe, 10^19 sec,
626  even if it had a clock cycle of Planch time, 10^44 Hz )
627 
628  Caution: never apply this to a derived vector, just choose some mother vector Vin, for example the unit vector by seed_vielbein(X,0),
629  and use it in all your runs, just change runID to get completely nonoverlapping streams of random numbers on a different day.
630 
631  clusterID and machineID are provided for the benefit of large organizations who wish to ensure that a simulation
632  which is running in parallel on a large number of clusters and machines will have non-colliding source of random numbers.
633 
634  did i repeat it enough times? the non-collision guarantee is absolute, not probabilistic
635 
636  */
637 
638  const myuint_t skipMat17[128][17] =
639  #include "CLHEP/Random/mixmax_skip_N17.icc"
640  ;
641 
642  const myuint_t* skipMat[128];
643  for (int i=0; i<128; i++) { skipMat[i] = skipMat17[i];}
644 
645  myID_t IDvec[4] = {streamID, runID, machineID, clusterID};
646  int r,i,j, IDindex;
647  myID_t id;
648  myuint_t Y[N], cum[N];
649  myuint_t coeff;
650  myuint_t* rowPtr;
651  myuint_t sumtot=0;
652 
653  for (i=0; i<N; i++) { Y[i] = Vin[i]; sumtot = modadd( sumtot, Vin[i]); } ;
654  for (IDindex=0; IDindex<4; IDindex++)
655  { // go from lower order to higher order ID
656  id=IDvec[IDindex];
657  //printf("now doing ID at level %d, with ID = %d\n", IDindex, id);
658  r = 0;
659  while (id)
660  {
661  if (id & 1)
662  {
663  rowPtr = (myuint_t*)skipMat[r + IDindex*8*sizeof(myID_t)];
664  for (i=0; i<N; i++){ cum[i] = 0; }
665  for (j=0; j<N; j++)
666  { // j is lag, enumerates terms of the poly
667  // for zero lag Y is already given
668  coeff = rowPtr[j]; // same coeff for all i
669  for (i =0; i<N; i++){
670  cum[i] = fmodmulM61( cum[i], coeff , Y[i] ) ;
671  }
672  sumtot = iterate_raw_vec(Y, sumtot);
673  }
674  sumtot=0;
675  for (i=0; i<N; i++){ Y[i] = cum[i]; sumtot = modadd( sumtot, cum[i]); } ;
676  }
677  id = (id >> 1); r++; // bring up the r-th bit in the ID
678  }
679  }
680  sumtot=0;
681  for (i=0; i<N; i++){ Vout[i] = Y[i]; sumtot = modadd( sumtot, Y[i]); }
682  // returns sumtot, and copy the vector over to Vout
683  return (sumtot) ;
684 }
685 
686 #if defined(__x86_64__)
687  myuint_t MixMaxRng::mod128(__uint128_t s)
688  {
689  myuint_t s1;
690  s1 = ( ( ((myuint_t)s)&M61 ) + ( ((myuint_t)(s>>64)) * 8 ) + ( ((myuint_t)s) >>BITS) );
691  return MIXMAX_MOD_MERSENNE(s1);
692  }
694  {
695  __uint128_t temp;
696  temp = (__uint128_t)a*(__uint128_t)b + cum;
697  return mod128(temp);
698  }
699 #else // on all other platforms, including 32-bit linux, PPC and PPC64, ARM and all Windows
701  {
702  const myuint_t MASK32=0xFFFFFFFFULL;
703  myuint_t o,ph,pl,ah,al;
704  o=(s)*a;
705  ph = ((s)>>32);
706  pl = (s) & MASK32;
707  ah = a>>32;
708  al = a & MASK32;
709  o = (o & M61) + ((ph*ah)<<3) + ((ah*pl+al*ph + ((al*pl)>>32))>>29) ;
710  o += cum;
711  o = (o & M61) + ((o>>61));
712  return o;
713  }
714 #endif
715 
717 {
718 #if defined(__x86_64__) && defined(__GNUC__) && (!defined(__ICC))
719  //#warning Using assembler routine in modadd
720  myuint_t out;
721  /* Assembler trick suggested by Andrzej Görlich */
722  __asm__ ("addq %2, %0; "
723  "btrq $61, %0; "
724  "adcq $0, %0; "
725  :"=r"(out)
726  :"0"(foo), "r"(bar)
727  );
728  return out;
729 #else
730  return MIXMAX_MOD_MERSENNE(foo+bar);
731 #endif
732 }
733 
735 {
736  int j;
737  std::cout << "mixmax state, file version 1.0\n";
738  std::cout << "N=" << rng_get_N() << "; V[N]={";
739  for (j=0; (j< (rng_get_N()-1) ); j++) {
740  std::cout << S.V[j] << ", ";
741  }
742  std::cout << S.V[rng_get_N()-1];
743  std::cout << "}; ";
744  std::cout << "counter= " << S.counter;
745  std::cout << "sumtot= " << S.sumtot << "\n";
746 }
747 
749 {
750  S.sumtot = iterate_raw_vec(S.V.data(), S.sumtot); S.counter = 1;
751  MixMaxRng tmp=*this;
752  tmp.BranchInplace(0); // daughter id
753  return tmp;
754 }
755 
757 {
758  // Dont forget to iterate the mother, when branching the daughter, or else will have collisions!
759  // a 64-bit LCG from Knuth line 26, is used to mangle a vector component
760  constexpr myuint_t MULT64=6364136223846793005ULL;
761  myuint_t tmp=S.V[id];
762  S.V[1] *= MULT64; S.V[id] &= M61;
763  S.sumtot = MIXMAX_MOD_MERSENNE( S.sumtot + S.V[id] - tmp + M61);
764  S.sumtot = iterate_raw_vec(S.V.data(), S.sumtot);// printf("iterating!\n");
765  S.counter = 1;
766 }
767 
768 } // namespace CLHEP
double convert1double(myuint_t u)
Definition: MixMaxRng.h:149
void BranchInplace(int id)
Definition: MixMaxRng.cc:756
static constexpr long long int SPECIAL
Definition: MixMaxRng.h:114
unsigned long long int myuint_t
Definition: MixMaxRng.h:47
std::vector< ExP01TrackerHit * > a
Definition: ExP01Classes.hh:33
virtual std::istream & getState(std::istream &is)
Definition: MixMaxRng.cc:416
static std::string beginTag()
Definition: MixMaxRng.cc:411
#define MIXMAX_ERROR_READING_STATE_FILE
Definition: MixMaxRng.cc:123
MixMaxRng Branch()
Definition: MixMaxRng.cc:748
unsigned long int myID_t
Definition: MixMaxRng.h:46
myuint_t precalc()
Definition: MixMaxRng.cc:544
myuint_t apply_bigskip(myuint_t *Vout, myuint_t *Vin, myID_t clusterID, myID_t machineID, myID_t runID, myID_t streamID)
Definition: MixMaxRng.cc:616
#define MIXMAX_MOD_MERSENNE(k)
Definition: MixMaxRng.h:122
Float_t Y
void restoreStatus(const char filename[]="MixMaxRngState.conf")
Definition: MixMaxRng.cc:127
Float_t tmp
static constexpr unsigned int VECTOR_STATE_SIZE
Definition: MixMaxRng.h:120
myuint_t MOD_MULSPEC(myuint_t k)
Definition: MixMaxRng.cc:481
std::array< myuint_t, N > V
Definition: MixMaxRng.h:177
virtual std::istream & get(std::istream &is)
Definition: MixMaxRng.cc:393
MixMaxRng & operator=(const MixMaxRng &rng)
Definition: MixMaxRng.cc:84
fin
Definition: AddMC.C:2
std::vector< unsigned long > put() const
Definition: MixMaxRng.cc:376
Float_t Z
fclose(fg1)
const XML_Char * s
Definition: expat.h:262
const unsigned long MASK32
Definition: MixMaxRng.cc:41
#define MIXMAX_ERROR_READING_STATE_CHECKSUM
Definition: MixMaxRng.cc:125
static const int MarkerLen
Definition: DualRand.cc:67
myuint_t iterate_raw_vec(myuint_t *Y, myuint_t sumtotOld)
Definition: MixMaxRng.cc:506
void setSeeds(const long *seeds, int seedNum=0)
Definition: MixMaxRng.cc:234
double generate(int i)
Definition: MixMaxRng.cc:281
myuint_t fmodmulM61(myuint_t cum, myuint_t s, myuint_t a)
Definition: MixMaxRng.cc:700
long seed
Definition: chem4.cc:68
double get_next_float_packbits()
Definition: MixMaxRng.cc:556
void seed_vielbein(unsigned int i)
Definition: MixMaxRng.cc:562
static constexpr double INV_M61
Definition: MixMaxRng.h:119
void showStatus() const
Definition: MixMaxRng.cc:213
#define CLHEP_ATOMIC_INT_TYPE
Definition: atomic_int.h:20
typedef int(XMLCALL *XML_NotStandaloneHandler)(void *userData)
static constexpr double s
#define MIXMAX_SEED_WAS_ZERO
Definition: MixMaxRng.cc:580
void saveStatus(const char filename[]="MixMaxRngState.conf") const
Definition: MixMaxRng.cc:101
static constexpr myuint_t M61
Definition: MixMaxRng.h:118
static constexpr int rng_get_SPECIALMUL()
Definition: MixMaxRng.cc:276
static constexpr long long int rng_get_SPECIAL()
Definition: MixMaxRng.cc:271
myuint_t MULWU(myuint_t k)
Definition: MixMaxRng.cc:501
double flat()
Definition: MixMaxRng.h:66
void print_state() const
Definition: MixMaxRng.cc:734
void flatArray(const int size, double *vect)
Definition: MixMaxRng.cc:335
double iterate()
Definition: MixMaxRng.cc:305
static constexpr double bar
myuint_t modadd(myuint_t foo, myuint_t bar)
Definition: MixMaxRng.cc:716
void seed_uniquestream(myID_t clusterID, myID_t machineID, myID_t runID, myID_t streamID)
Definition: MixMaxRng.cc:609
static constexpr int BITS
Definition: MixMaxRng.h:117
static const int N
Definition: MixMaxRng.h:51
static std::string engineName()
Definition: MixMaxRng.cc:261
double flat()
Definition: G4AblaRandom.cc:48
rng_state_t S
Definition: MixMaxRng.h:183
#define MIXMAX_ERROR_READING_STATE_COUNTER
Definition: MixMaxRng.cc:124
myuint_t get_next()
Definition: MixMaxRng.cc:526
void setSeed(long seed, int dum=0)
Definition: MixMaxRng.cc:223
static constexpr int rng_get_N()
Definition: MixMaxRng.cc:266
static constexpr long long int SPECIALMUL
Definition: MixMaxRng.h:115
void seed_spbox(myuint_t)
Definition: MixMaxRng.cc:582