Geant4 Cross Reference

Cross-Referencing   Geant4
Geant4/externals/clhep/src/MixMaxRng.cc

Version: [ ReleaseNotes ] [ 1.0 ] [ 1.1 ] [ 2.0 ] [ 3.0 ] [ 3.1 ] [ 3.2 ] [ 4.0 ] [ 4.0.p1 ] [ 4.0.p2 ] [ 4.1 ] [ 4.1.p1 ] [ 5.0 ] [ 5.0.p1 ] [ 5.1 ] [ 5.1.p1 ] [ 5.2 ] [ 5.2.p1 ] [ 5.2.p2 ] [ 6.0 ] [ 6.0.p1 ] [ 6.1 ] [ 6.2 ] [ 6.2.p1 ] [ 6.2.p2 ] [ 7.0 ] [ 7.0.p1 ] [ 7.1 ] [ 7.1.p1 ] [ 8.0 ] [ 8.0.p1 ] [ 8.1 ] [ 8.1.p1 ] [ 8.1.p2 ] [ 8.2 ] [ 8.2.p1 ] [ 8.3 ] [ 8.3.p1 ] [ 8.3.p2 ] [ 9.0 ] [ 9.0.p1 ] [ 9.0.p2 ] [ 9.1 ] [ 9.1.p1 ] [ 9.1.p2 ] [ 9.1.p3 ] [ 9.2 ] [ 9.2.p1 ] [ 9.2.p2 ] [ 9.2.p3 ] [ 9.2.p4 ] [ 9.3 ] [ 9.3.p1 ] [ 9.3.p2 ] [ 9.4 ] [ 9.4.p1 ] [ 9.4.p2 ] [ 9.4.p3 ] [ 9.4.p4 ] [ 9.5 ] [ 9.5.p1 ] [ 9.5.p2 ] [ 9.6 ] [ 9.6.p1 ] [ 9.6.p2 ] [ 9.6.p3 ] [ 9.6.p4 ] [ 10.0 ] [ 10.0.p1 ] [ 10.0.p2 ] [ 10.0.p3 ] [ 10.0.p4 ] [ 10.1 ] [ 10.1.p1 ] [ 10.1.p2 ] [ 10.1.p3 ] [ 10.2 ] [ 10.2.p1 ] [ 10.2.p2 ] [ 10.2.p3 ] [ 10.3 ] [ 10.3.p1 ] [ 10.3.p2 ] [ 10.3.p3 ] [ 10.4 ] [ 10.4.p1 ] [ 10.4.p2 ] [ 10.4.p3 ] [ 10.5 ] [ 10.5.p1 ] [ 10.6 ] [ 10.6.p1 ] [ 10.6.p2 ] [ 10.6.p3 ] [ 10.7 ] [ 10.7.p1 ] [ 10.7.p2 ] [ 10.7.p3 ] [ 10.7.p4 ] [ 11.0 ] [ 11.0.p1 ] [ 11.0.p2 ] [ 11.0.p3, ] [ 11.0.p4 ] [ 11.1 ] [ 11.1.1 ] [ 11.1.2 ] [ 11.1.3 ] [ 11.2 ] [ 11.2.1 ] [ 11.2.2 ] [ 11.3.0 ]

Diff markup

Differences between /externals/clhep/src/MixMaxRng.cc (Version 11.3.0) and /externals/clhep/src/MixMaxRng.cc (Version 10.7)


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