// $Id: RanecuEngine.cc,v 1.7 2010/07/20 18:06:02 garren Exp $ // -*- C++ -*- // // ----------------------------------------------------------------------- // HEP Random // --- RanecuEngine --- // class implementation file // ----------------------------------------------------------------------- // This file is part of Geant4 (simulation toolkit for HEP). // // RANECU Random Engine - algorithm originally written in FORTRAN77 // as part of the MATHLIB HEP library. // ======================================================================= // Gabriele Cosmo - Created - 2nd February 1996 // - Minor corrections: 31st October 1996 // - Added methods for engine status: 19th November 1996 // - Added abs for setting seed index: 11th July 1997 // - Modified setSeeds() to handle default index: 16th Oct 1997 // - setSeed() now resets the engine status to the original // values in the static table of HepRandom: 19th Mar 1998 // J.Marraffino - Added stream operators and related constructor. // Added automatic seed selection from seed table and // engine counter: 16th Feb 1998 // Ken Smith - Added conversion operators: 6th Aug 1998 // J. Marraffino - Remove dependence on hepString class 13 May 1999 // M. Fischler - Add endl to the end of saveStatus 10 Apr 2001 // M. Fischler - In restore, checkFile for file not found 03 Dec 2004 // M. Fischler - Methods for distrib. instance save/restore 12/8/04 // M. Fischler - split get() into tag validation and // getState() for anonymous restores 12/27/04 // M. Fischler - put/get for vectors of ulongs 3/14/05 // M. Fischler - State-saving using only ints, for portability 4/12/05 // M. Fischler - Modify ctor and setSeed to utilize all info provided // and avoid coincidence of same state from different // seeds 6/22/10 // // ======================================================================= #include "CLHEP/Random/defs.h" #include "CLHEP/Random/Random.h" #include "CLHEP/Random/RanecuEngine.h" #include "CLHEP/Random/engineIDulong.h" #include // for strcmp #include #include namespace CLHEP { static const int MarkerLen = 64; // Enough room to hold a begin or end marker. static const double prec = 4.6566128E-10; std::string RanecuEngine::name() const {return "RanecuEngine";} void RanecuEngine::further_randomize (int seq, int col, int index, int modulus) { table[seq][col] -= (index&0x3FFFFFFF); while (table[seq][col] <= 0) table[seq][col] += (modulus-1); } // mf 6/22/10 // Number of instances with automatic seed selection int RanecuEngine::numEngines = 0; RanecuEngine::RanecuEngine() : HepRandomEngine() { int cycle = abs(int(numEngines/maxSeq)); seq = abs(int(numEngines%maxSeq)); numEngines += 1; theSeed = seq; long mask = ((cycle & 0x007fffff) << 8); for (int i=0; i<2; ++i) { for (int j=0; j> *this; } RanecuEngine::~RanecuEngine() {} void RanecuEngine::setSeed(long index, int dum) { seq = abs(int(index%maxSeq)); theSeed = seq; HepRandom::getTheTableSeeds(table[seq],seq); theSeeds = &table[seq][0]; further_randomize (seq, 0, index, shift1); // mf 6/22/10 further_randomize (seq, 1, dum, shift2); // mf 6/22/10 } void RanecuEngine::setSeeds(const long* seeds, int pos) { if (pos != -1) { seq = abs(int(pos%maxSeq)); theSeed = seq; } // only positive seeds are allowed table[seq][0] = abs(seeds[0])%shift1; table[seq][1] = abs(seeds[1])%shift2; theSeeds = &table[seq][0]; } void RanecuEngine::setIndex(long index) { seq = abs(int(index%maxSeq)); theSeed = seq; theSeeds = &table[seq][0]; } void RanecuEngine::saveStatus( const char filename[] ) const { std::ofstream outFile( filename, std::ios::out ) ; if (!outFile.bad()) { outFile << "Uvec\n"; std::vector v = put(); #ifdef TRACE_IO std::cout << "Result of v = put() is:\n"; #endif for (unsigned int i=0; i v; unsigned long xin; for (unsigned int ivec=0; ivec < VECTOR_STATE_SIZE; ++ivec) { inFile >> xin; #ifdef TRACE_IO std::cout << "ivec = " << ivec << " xin = " << xin << " "; if (ivec%3 == 0) std::cout << "\n"; #endif if (!inFile) { inFile.clear(std::ios::badbit | inFile.rdstate()); std::cerr << "\nJamesRandom state (vector) description improper." << "\nrestoreStatus has failed." << "\nInput stream is probably mispositioned now." << std::endl; return; } v.push_back(xin); } getState(v); return; } if (!inFile.bad() && !inFile.eof()) { // inFile >> theSeed; removed -- encompased by possibleKeywordInput for (int i=0; i<2; ++i) inFile >> table[theSeed][i]; seq = int(theSeed); } } void RanecuEngine::showStatus() const { std::cout << std::endl; std::cout << "--------- Ranecu engine status ---------" << std::endl; std::cout << " Initial seed (index) = " << theSeed << std::endl; std::cout << " Current couple of seeds = " << table[theSeed][0] << ", " << table[theSeed][1] << std::endl; std::cout << "----------------------------------------" << std::endl; } double RanecuEngine::flat() { const int index = seq; long seed1 = table[index][0]; long seed2 = table[index][1]; int k1 = (int)(seed1/ecuyer_b); int k2 = (int)(seed2/ecuyer_e); seed1 = ecuyer_a*(seed1-k1*ecuyer_b)-k1*ecuyer_c; if (seed1 < 0) seed1 += shift1; seed2 = ecuyer_d*(seed2-k2*ecuyer_e)-k2*ecuyer_f; if (seed2 < 0) seed2 += shift2; table[index][0] = seed1; table[index][1] = seed2; long diff = seed1-seed2; if (diff <= 0) diff += (shift1-1); return (double)(diff*prec); } void RanecuEngine::flatArray(const int size, double* vect) { const int index = seq; long seed1 = table[index][0]; long seed2 = table[index][1]; int k1, k2; register int i; for (i=0; i v = put(); for (unsigned int i=0; i RanecuEngine::put () const { std::vector v; v.push_back (engineIDulong()); v.push_back(static_cast(theSeed)); v.push_back(static_cast(table[theSeed][0])); v.push_back(static_cast(table[theSeed][1])); return v; } std::istream & RanecuEngine::get ( std::istream& is ) { char beginMarker [MarkerLen]; is >> std::ws; is.width(MarkerLen); // causes the next read to the char* to be <= // that many bytes, INCLUDING A TERMINATION \0 // (Stroustrup, section 21.3.2) is >> beginMarker; if (strcmp(beginMarker,"RanecuEngine-begin")) { is.clear(std::ios::badbit | is.rdstate()); std::cerr << "\nInput stream mispositioned or" << "\nRanecuEngine state description missing or" << "\nwrong engine type found." << std::endl; return is; } return getState(is); } std::string RanecuEngine::beginTag ( ) { return "RanecuEngine-begin"; } std::istream & RanecuEngine::getState ( std::istream& is ) { if ( possibleKeywordInput ( is, "Uvec", theSeed ) ) { std::vector v; unsigned long uu; for (unsigned int ivec=0; ivec < VECTOR_STATE_SIZE; ++ivec) { is >> uu; if (!is) { is.clear(std::ios::badbit | is.rdstate()); std::cerr << "\nRanecuEngine state (vector) description improper." << "\ngetState() has failed." << "\nInput stream is probably mispositioned now." << std::endl; return is; } v.push_back(uu); } getState(v); return (is); } // is >> theSeed; Removed, encompassed by possibleKeywordInput() char endMarker [MarkerLen]; for (int i=0; i<2; ++i) { is >> table[theSeed][i]; } is >> std::ws; is.width(MarkerLen); is >> endMarker; if (strcmp(endMarker,"RanecuEngine-end")) { is.clear(std::ios::badbit | is.rdstate()); std::cerr << "\nRanecuEngine state description incomplete." << "\nInput stream is probably mispositioned now." << std::endl; return is; } seq = int(theSeed); return is; } bool RanecuEngine::get (const std::vector & v) { if ((v[0] & 0xffffffffUL) != engineIDulong()) { std::cerr << "\nRanecuEngine get:state vector has wrong ID word - state unchanged\n"; return false; } return getState(v); } bool RanecuEngine::getState (const std::vector & v) { if (v.size() != VECTOR_STATE_SIZE ) { std::cerr << "\nRanecuEngine get:state vector has wrong length - state unchanged\n"; return false; } theSeed = v[1]; table[theSeed][0] = v[2]; table[theSeed][1] = v[3]; seq = int(theSeed); return true; } } // namespace CLHEP