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.6.p1)


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