33#include "CLHEP/Random/defs.h"
34#include "CLHEP/Random/Random.h"
35#include "CLHEP/Random/MixMaxRng.h"
36#include "CLHEP/Random/engineIDulong.h"
37#include "CLHEP/Utility/atomic_int.h"
45const unsigned long MASK32=0xffffffff;
54static const int MarkerLen = 64;
59 int numEngines = ++numberOfEngines;
60 setSeed(
static_cast<long>(numEngines));
84 S.sumtot= rng.S.sumtot;
85 S.counter= rng.S.counter;
92 if (
this == &rng) {
return *
this; }
96 HepRandomEngine::operator=(rng);
99 S.sumtot= rng.S.sumtot;
100 S.counter= rng.S.counter;
108 FILE *fh= fopen(filename,
"w");
112 fprintf(fh,
"mixmax state, file version 1.0\n" );
113 fprintf(fh,
"N=%u; V[N]={", rng_get_N() );
114 for (j=0; (j< (rng_get_N()-1) ); j++) {
115 fprintf(fh,
"%llu, ", S.V[j] );
117 fprintf(fh,
"%llu", S.V[rng_get_N()-1] );
119 fprintf(fh,
"counter=%u; ", S.counter );
120 fprintf(fh,
"sumtot=%llu;\n", S.sumtot );
129 if( ( fin = fopen(filename,
"r") ) )
139 fprintf(stderr,
"mixmax -> read_state: error reading file %s\n", filename);
140 throw std::runtime_error(
"Error in reading state file");
145 if (!fscanf(fin,
"%llu", &S.V[0]) )
147 fprintf(stderr,
"mixmax -> read_state: error reading file %s\n", filename);
148 throw std::runtime_error(
"Error in reading state file");
152 for( i = 1; i < rng_get_N(); i++)
154 if (!fscanf(fin,
", %llu", &vecVal) )
156 fprintf(stderr,
"mixmax -> read_state: error reading vector component i=%d from file %s\n", i, filename);
157 throw std::runtime_error(
"Error in reading state file");
159 if( vecVal <= MixMaxRng::M61 )
165 fprintf(stderr,
"mixmax -> read_state: Invalid state vector value= %llu"
166 " ( must be less than %llu ) "
167 " obtained from reading file %s\n"
168 , vecVal, MixMaxRng::M61, filename);
173 if (!fscanf( fin,
"}; counter=%i; ", &counter))
175 fprintf(stderr,
"mixmax -> read_state: error reading counter from file %s\n", filename);
176 throw std::runtime_error(
"Error in reading state file");
178 if( counter <= rng_get_N() )
184 fprintf(stderr,
"mixmax -> read_state: Invalid counter = %d"
185 " Must be 0 <= counter < %u\n" , counter, rng_get_N());
187 throw std::runtime_error(
"Error in reading state counter");
191 if (!fscanf( fin,
"sumtot=%llu\n", &sumtot))
193 fprintf(stderr,
"mixmax -> read_state: error reading checksum from file %s\n", filename);
194 throw std::runtime_error(
"Error in reading state file");
197 if (S.sumtot != sumtot)
199 fprintf(stderr,
"mixmax -> checksum error while reading state from file %s - corrupted?\n", filename);
200 throw std::runtime_error(
"Error in reading state checksum");
207 std::cout << std::endl;
208 std::cout <<
"------- MixMaxRng engine status -------" << std::endl;
210 std::cout <<
" Current state vector is:" << std::endl;
212 std::cout <<
"---------------------------------------" << std::endl;
219 seed_spbox(longSeed);
228 myID_t seed0, seed1= 0, seed2= 0, seed3= 0;
238 if( seedNum > 1){ seed1=
static_cast<myID_t>(Seeds[1]) &
MASK32; }
239 if( seedNum > 2){ seed2=
static_cast<myID_t>(Seeds[2]) &
MASK32; }
250 seed_uniquestream(seed3, seed2, seed1, seed0);
258constexpr int MixMaxRng::rng_get_N()
263constexpr long long int MixMaxRng::rng_get_SPECIAL()
268constexpr int MixMaxRng::rng_get_SPECIALMUL()
273double MixMaxRng::generate(
int i)
276#if defined(__clang__) || defined(__llvm__)
277 return INV_M61*
static_cast<double>(S.V[i]);
278#elif defined(__GNUC__) && (__GNUC__ < 7) && (!defined(__ICC)) && defined(__x86_64__) && defined(__SSE2_MATH__)
285 __asm__ __volatile__(
"pxor %0, %0;"
293 return convert1double(S.V[i]);
297double MixMaxRng::iterate()
301 Y[0] = ( tempV = S.sumtot);
305 tempPO = MULWU(tempP); tempP = modadd(tempP,
Y[1] ); tempV =
MIXMAX_MOD_MERSENNE(tempV+tempP+tempPO);
Y[1] = tempV; sumtot += tempV;
if (sumtot < tempV) {ovflow++;};
306 tempPO = MULWU(tempP); tempP = modadd(tempP,
Y[2] ); tempV =
MIXMAX_MOD_MERSENNE(tempV+tempP+tempPO);
Y[2] = tempV; sumtot += tempV;
if (sumtot < tempV) {ovflow++;};
307 tempPO = MULWU(tempP); tempP = modadd(tempP,
Y[3] ); tempV =
MIXMAX_MOD_MERSENNE(tempV+tempP+tempPO);
Y[3] = tempV; sumtot += tempV;
if (sumtot < tempV) {ovflow++;};
308 tempPO = MULWU(tempP); tempP = modadd(tempP,
Y[4] ); tempV =
MIXMAX_MOD_MERSENNE(tempV+tempP+tempPO);
Y[4] = tempV; sumtot += tempV;
if (sumtot < tempV) {ovflow++;};
309 tempPO = MULWU(tempP); tempP = modadd(tempP,
Y[5] ); tempV =
MIXMAX_MOD_MERSENNE(tempV+tempP+tempPO);
Y[5] = tempV; sumtot += tempV;
if (sumtot < tempV) {ovflow++;};
310 tempPO = MULWU(tempP); tempP = modadd(tempP,
Y[6] ); tempV =
MIXMAX_MOD_MERSENNE(tempV+tempP+tempPO);
Y[6] = tempV; sumtot += tempV;
if (sumtot < tempV) {ovflow++;};
311 tempPO = MULWU(tempP); tempP = modadd(tempP,
Y[7] ); tempV =
MIXMAX_MOD_MERSENNE(tempV+tempP+tempPO);
Y[7] = tempV; sumtot += tempV;
if (sumtot < tempV) {ovflow++;};
312 tempPO = MULWU(tempP); tempP = modadd(tempP,
Y[8] ); tempV =
MIXMAX_MOD_MERSENNE(tempV+tempP+tempPO);
Y[8] = tempV; sumtot += tempV;
if (sumtot < tempV) {ovflow++;};
313 tempPO = MULWU(tempP); tempP = modadd(tempP,
Y[9] ); tempV =
MIXMAX_MOD_MERSENNE(tempV+tempP+tempPO);
Y[9] = tempV; sumtot += tempV;
if (sumtot < tempV) {ovflow++;};
314 tempPO = MULWU(tempP); tempP = modadd(tempP,
Y[10]); tempV =
MIXMAX_MOD_MERSENNE(tempV+tempP+tempPO);
Y[10] = tempV; sumtot += tempV;
if (sumtot < tempV) {ovflow++;};
315 tempPO = MULWU(tempP); tempP = modadd(tempP,
Y[11]); tempV =
MIXMAX_MOD_MERSENNE(tempV+tempP+tempPO);
Y[11] = tempV; sumtot += tempV;
if (sumtot < tempV) {ovflow++;};
316 tempPO = MULWU(tempP); tempP = modadd(tempP,
Y[12]); tempV =
MIXMAX_MOD_MERSENNE(tempV+tempP+tempPO);
Y[12] = tempV; sumtot += tempV;
if (sumtot < tempV) {ovflow++;};
317 tempPO = MULWU(tempP); tempP = modadd(tempP,
Y[13]); tempV =
MIXMAX_MOD_MERSENNE(tempV+tempP+tempPO);
Y[13] = tempV; sumtot += tempV;
if (sumtot < tempV) {ovflow++;};
318 tempPO = MULWU(tempP); tempP = modadd(tempP,
Y[14]); tempV =
MIXMAX_MOD_MERSENNE(tempV+tempP+tempPO);
Y[14] = tempV; sumtot += tempV;
if (sumtot < tempV) {ovflow++;};
319 tempPO = MULWU(tempP); tempP = modadd(tempP,
Y[15]); tempV =
MIXMAX_MOD_MERSENNE(tempV+tempP+tempPO);
Y[15] = tempV; sumtot += tempV;
if (sumtot < tempV) {ovflow++;};
320 tempPO = MULWU(tempP); tempP = modadd(tempP,
Y[16]); tempV =
MIXMAX_MOD_MERSENNE(tempV+tempP+tempPO);
Y[16] = tempV; sumtot += tempV;
if (sumtot < tempV) {ovflow++;};
324 return double(S.V[1])*INV_M61;
330 for (
int i=0; i<size; ++i) { vect[i] =
flat(); }
338MixMaxRng::operator float()
340 return float( flat() );
343MixMaxRng::operator
unsigned int()
345 return static_cast<unsigned int>(get_next());
352 char beginMarker[] =
"MixMaxRng-begin";
353 char endMarker[] =
"MixMaxRng-end";
355 long pr = os.precision(24);
356 os << beginMarker <<
" ";
358 for (
int i=0; i<rng_get_N(); ++i) {
359 os << S.V[i] <<
"\n";
361 os << S.counter <<
"\n";
362 os << S.sumtot <<
"\n";
363 os << endMarker <<
"\n";
370 std::vector<unsigned long> v;
371 v.push_back (engineIDulong<MixMaxRng>());
372 for (
int i=0; i<rng_get_N(); ++i)
374 v.push_back(
static_cast<unsigned long>(S.V[i] &
MASK32));
376 v.push_back(
static_cast<unsigned long>(S.V[i] >> 32 ));
379 v.push_back(
static_cast<unsigned long>(S.counter));
380 v.push_back(
static_cast<unsigned long>(S.sumtot &
MASK32));
381 v.push_back(
static_cast<unsigned long>(S.sumtot >> 32));
387 char beginMarker [MarkerLen];
393 if (strcmp(beginMarker,
"MixMaxRng-begin")) {
394 is.clear(std::ios::badbit | is.rdstate());
395 std::cerr <<
"\nInput stream mispositioned or"
396 <<
"\nMixMaxRng state description missing or"
397 <<
"\nwrong engine type found." << std::endl;
405 return "MixMaxRng-begin";
410 char endMarker[MarkerLen];
412 for (
int i=0; i<rng_get_N(); ++i) is >> S.V[i];
419 if (strcmp(endMarker,
"MixMaxRng-end")) {
420 is.clear(std::ios::badbit | is.rdstate());
421 std::cerr <<
"\nMixMaxRng state description incomplete."
422 <<
"\nInput stream is probably mispositioned now.\n";
425 if ( S.counter < 0 || S.counter > rng_get_N() ) {
426 std::cerr <<
"\nMixMaxRng::getState(): "
427 <<
"vector read wrong value of counter from file!"
428 <<
"\nInput stream is probably mispositioned now.\n";
432 if ( checksum != S.sumtot) {
433 std::cerr <<
"\nMixMaxRng::getState(): "
434 <<
"checksum disagrees with value stored in file!"
435 <<
"\nInput stream is probably mispositioned now.\n";
443 if ((v[0] & 0xffffffffUL) != engineIDulong<MixMaxRng>()) {
445 "\nMixMaxRng::get(): vector has wrong ID word - state unchanged\n";
453 if (v.size() != VECTOR_STATE_SIZE ) {
455 "\nMixMaxRng::getState(): vector has wrong length - state unchanged\n";
458 for (
int i=1; i<2*rng_get_N() ; i=i+2) {
462 S.counter = (int)v[2*rng_get_N()+1];
464 if ( ( (v[2*rng_get_N()+2] &
MASK32)
465 | ( (
myuint_t)(v[2*rng_get_N()+3]) << 32 ) ) != S.sumtot) {
466 std::cerr <<
"\nMixMaxRng::getState(): vector has wrong checksum!"
467 <<
"\nInput vector is probably mispositioned now.\n";
484 return fmodmulM61( 0, SPECIAL , (k) );
487 std::cerr <<
"MIXMAX ERROR: " <<
"Disallowed value of parameter N\n";
495 return (( (k)<<(SPECIALMUL) & M61) ^ ( (k) >> (BITS-SPECIALMUL)) );
504 Y[0] = ( tempV = sumtotOld);
507 for (i=1; (i<N); i++)
510 tempP = modadd(tempP,
Y[i]);
513 sumtot += tempV;
if (sumtot < tempV) {ovflow++;}
530 S.sumtot = iterate_raw_vec(S.V.data(), S.sumtot);
541 for (i=0; i < N; i++){
548double MixMaxRng::get_next_float_packbits()
551 return convert1double(
Z);
554void MixMaxRng::seed_vielbein(
unsigned int index)
559 for (i=0; i < N; i++){
572void MixMaxRng::seed_spbox(
myuint_t seed)
576 const myuint_t MULT64=6364136223846793005ULL;
580 if (seed == 0)
throw std::runtime_error(
"try seeding with nonzero seed next time");
584 for (i=0; i < N; i++){
585 l*=MULT64; l = (l << 32) ^ (l>>32);
587 sumtot += S.V[(i)];
if (sumtot < S.V[(i)]) {ovflow++;}
596 S.sumtot = apply_bigskip(S.V.data(), S.V.data(), clusterID, machineID, runID, streamID );
623 #include "CLHEP/Random/mixmax_skip_N17.icc"
627 for (
int i=0; i<128; i++) { skipMat[i] = skipMat17[i];}
629 myID_t IDvec[4] = {streamID, runID, machineID, clusterID};
637 for (i=0; i<N; i++) {
Y[i] = Vin[i]; sumtot = modadd( sumtot, Vin[i]); } ;
638 for (IDindex=0; IDindex<4; IDindex++)
648 for (i=0; i<N; i++){ cum[i] = 0; }
653 for (i =0; i<N; i++){
654 cum[i] = fmodmulM61( cum[i], coeff ,
Y[i] ) ;
656 sumtot = iterate_raw_vec(
Y, sumtot);
659 for (i=0; i<N; i++){
Y[i] = cum[i]; sumtot = modadd( sumtot, cum[i]); } ;
665 for (i=0; i<N; i++){ Vout[i] =
Y[i]; sumtot = modadd( sumtot,
Y[i]); }
670#if defined(__x86_64__)
671 myuint_t MixMaxRng::mod128(__uint128_t s)
680 temp = (__uint128_t)a*(__uint128_t)b + cum;
693 o = (o & M61) + ((ph*ah)<<3) + ((ah*pl+al*ph + ((al*pl)>>32))>>29) ;
695 o = (o & M61) + ((o>>61));
702#if defined(__x86_64__) && defined(__GNUC__) && (!defined(__ICC))
706 __asm__ (
"addq %2, %0; "
718void MixMaxRng::print_state()
const
721 std::cout <<
"mixmax state, file version 1.0\n";
722 std::cout <<
"N=" << rng_get_N() <<
"; V[N]={";
723 for (j=0; (j< (rng_get_N()-1) ); j++) {
724 std::cout << S.V[j] <<
", ";
726 std::cout << S.V[rng_get_N()-1];
728 std::cout <<
"counter= " << S.counter;
729 std::cout <<
"sumtot= " << S.sumtot <<
"\n";
732MixMaxRng MixMaxRng::Branch()
734 S.sumtot = iterate_raw_vec(S.V.data(), S.sumtot); S.counter = 1;
736 tmp.BranchInplace(0);
740void MixMaxRng::BranchInplace(
int id)
744 constexpr myuint_t MULT64=6364136223846793005ULL;
746 S.V[1] *= MULT64; S.V[id] &= M61;
748 S.sumtot = iterate_raw_vec(S.V.data(), S.sumtot);
const unsigned long MASK32
#define MIXMAX_MOD_MERSENNE(k)
#define CLHEP_ATOMIC_INT_TYPE
void restoreStatus(const char filename[]="MixMaxRngState.conf")
void flatArray(const int size, double *vect)
void setSeed(long seed, int dum=0)
static std::string beginTag()
void saveStatus(const char filename[]="MixMaxRngState.conf") const
virtual std::istream & get(std::istream &is)
MixMaxRng & operator=(const MixMaxRng &rng)
virtual std::istream & getState(std::istream &is)
std::vector< unsigned long > put() const
void setSeeds(const long *seeds, int seedNum=0)
static std::string engineName()
unsigned long long int myuint_t