CLHEP VERSION Reference Documentation
CLHEP Home Page CLHEP Documentation CLHEP Bug Reports |
00001 // $Id: RanshiEngine.cc,v 1.6 2010/06/16 17:24:53 garren Exp $ 00002 // -*- C++ -*- 00003 // 00004 // ----------------------------------------------------------------------- 00005 // HEP Random 00006 // --- RanshiEngine --- 00007 // class implementation file 00008 // ----------------------------------------------------------------------- 00009 // 00010 // This algorithm implements the random number generator as proposed by 00011 // "F. Gutbrod, Comp. Phys. Comm. 87 (1995) 291-306". 00012 // 00013 // ======================================================================= 00014 // Ken Smith - Created: 9th June 1998 00015 // - Removed std::pow() from flat method: 21st Jul 1998 00016 // - Added conversion operators: 6th Aug 1998 00017 // J. Marraffino - Added some explicit casts to deal with 00018 // machines where sizeof(int) != sizeof(long) 22 Aug 1998 00019 // M. Fischler - Modified constructors taking seeds to not 00020 // depend on numEngines (same seeds should 00021 // produce same sequences). Default still 00022 // depends on numEngines. 16 Sep 1998 00023 // - Modified use of the various exponents of 2 00024 // to avoid per-instance space overhead and 00025 // correct the rounding procedure 16 Sep 1998 00026 // J. Marraffino - Remove dependence on hepString class 13 May 1999 00027 // M. Fischler - In restore, checkFile for file not found 03 Dec 2004 00028 // M. Fischler - Methods for instance save/restore 12/8/04 00029 // M. Fischler - split get() into tag validation and 00030 // getState() for anonymous restores 12/27/04 00031 // M. Fischler - State-saving using only ints, for portability 4/12/05 00032 // 00033 // ======================================================================= 00034 00035 #include "CLHEP/Random/defs.h" 00036 #include "CLHEP/Random/RanshiEngine.h" 00037 #include "CLHEP/Random/engineIDulong.h" 00038 #include <string.h> // for strcmp 00039 00040 namespace CLHEP { 00041 00042 static const int MarkerLen = 64; // Enough room to hold a begin or end marker. 00043 00044 std::string RanshiEngine::name() const {return "RanshiEngine";} 00045 00046 // Number of instances with automatic seed selection 00047 int RanshiEngine::numEngines = 0; 00048 00049 RanshiEngine::RanshiEngine() 00050 : HepRandomEngine(), 00051 halfBuff(0), numFlats(0) 00052 { 00053 int i = 0; 00054 while (i < numBuff) { 00055 buffer[i] = (unsigned int)(numEngines+19780503L*(i+1)); 00056 ++i; 00057 } 00058 theSeed = numEngines+19780503L*++i; 00059 redSpin = (unsigned int)(theSeed & 0xffffffff); 00060 ++numEngines; 00061 for( i = 0; i < 10000; ++i) flat(); // Warm-up by running thorugh 10000 nums 00062 } 00063 00064 RanshiEngine::RanshiEngine(std::istream& is) 00065 : HepRandomEngine(), 00066 halfBuff(0), numFlats(0) 00067 { 00068 is >> *this; 00069 } 00070 00071 RanshiEngine::RanshiEngine(long seed) 00072 : HepRandomEngine(), 00073 halfBuff(0), numFlats(0) 00074 { 00075 for (int i = 0; i < numBuff; ++i) { 00076 buffer[i] = (unsigned int)seed&0xffffffff; 00077 } 00078 theSeed = seed; 00079 redSpin = (unsigned int)(theSeed & 0xffffffff); 00080 int j; 00081 for (j = 0; j < numBuff*20; ++j) { // "warm-up" for engine to hit 00082 flat(); // every ball on average 20X. 00083 } 00084 } 00085 00086 RanshiEngine::RanshiEngine(int rowIndex, int colIndex) 00087 : HepRandomEngine(), 00088 halfBuff(0), numFlats(0) 00089 { 00090 int i = 0; 00091 while( i < numBuff ) { 00092 buffer[i] = (unsigned int)((rowIndex + (i+1)*(colIndex+8))&0xffffffff); 00093 ++i; 00094 } 00095 theSeed = rowIndex; 00096 redSpin = colIndex & 0xffffffff; 00097 for( i = 0; i < 100; ++i) flat(); // Warm-up by running thorugh 100 nums 00098 } 00099 00100 RanshiEngine::~RanshiEngine() { } 00101 00102 double RanshiEngine::flat() { 00103 unsigned int redAngle = (((numBuff/2) - 1) & redSpin) + halfBuff; 00104 unsigned int blkSpin = buffer[redAngle] & 0xffffffff; 00105 unsigned int boostResult = blkSpin ^ redSpin; 00106 00107 buffer[redAngle] = ((blkSpin << 17) | (blkSpin >> (32-17))) ^ redSpin; 00108 00109 redSpin = (blkSpin + numFlats++) & 0xffffffff; 00110 halfBuff = numBuff/2 - halfBuff; 00111 00112 return ( blkSpin * twoToMinus_32() + // most significant part 00113 (boostResult>>11) * twoToMinus_53() + // fill in remaining bits 00114 nearlyTwoToMinus_54()); // non-zero 00115 } 00116 00117 void RanshiEngine::flatArray(const int size, double* vect) { 00118 for (int i = 0; i < size; ++i) { 00119 vect[i] = flat(); 00120 } 00121 } 00122 00123 void RanshiEngine::setSeed(long seed, int) { 00124 *this = RanshiEngine(seed); 00125 } 00126 00127 void RanshiEngine::setSeeds(const long* seeds, int) { 00128 if (*seeds) { 00129 int i = 0; 00130 while (seeds[i] && i < numBuff) { 00131 buffer[i] = (unsigned int)seeds[i]; 00132 ++i; 00133 } 00134 while (i < numBuff) { 00135 buffer[i] = buffer[i-1]; 00136 ++i; 00137 } 00138 theSeed = seeds[0]; 00139 redSpin = (unsigned int)theSeed; 00140 } 00141 theSeeds = seeds; 00142 } 00143 00144 void RanshiEngine::saveStatus(const char filename[]) const { 00145 std::ofstream outFile(filename, std::ios::out); 00146 if (!outFile.bad()) { 00147 outFile << "Uvec\n"; 00148 std::vector<unsigned long> v = put(); 00149 #ifdef TRACE_IO 00150 std::cout << "Result of v = put() is:\n"; 00151 #endif 00152 for (unsigned int i=0; i<v.size(); ++i) { 00153 outFile << v[i] << "\n"; 00154 #ifdef TRACE_IO 00155 std::cout << v[i] << " "; 00156 if (i%6==0) std::cout << "\n"; 00157 #endif 00158 } 00159 #ifdef TRACE_IO 00160 std::cout << "\n"; 00161 #endif 00162 } 00163 #ifdef REMOVED 00164 if (!outFile.bad()) { 00165 outFile << std::setprecision(20) << theSeed << std::endl; 00166 for (int i = 0; i < numBuff; ++i) { 00167 outFile << buffer[i] << " "; 00168 } 00169 outFile << redSpin << " " << numFlats << " " << halfBuff << std::endl; 00170 } 00171 #endif 00172 } 00173 00174 void RanshiEngine::restoreStatus(const char filename[]) { 00175 std::ifstream inFile(filename, std::ios::in); 00176 if (!checkFile ( inFile, filename, engineName(), "restoreStatus" )) { 00177 std::cerr << " -- Engine state remains unchanged\n"; 00178 return; 00179 } 00180 if ( possibleKeywordInput ( inFile, "Uvec", theSeed ) ) { 00181 std::vector<unsigned long> v; 00182 unsigned long xin; 00183 for (unsigned int ivec=0; ivec < VECTOR_STATE_SIZE; ++ivec) { 00184 inFile >> xin; 00185 #ifdef TRACE_IO 00186 std::cout << "ivec = " << ivec << " xin = " << xin << " "; 00187 if (ivec%3 == 0) std::cout << "\n"; 00188 #endif 00189 if (!inFile) { 00190 inFile.clear(std::ios::badbit | inFile.rdstate()); 00191 std::cerr << "\nRanshiEngine state (vector) description improper." 00192 << "\nrestoreStatus has failed." 00193 << "\nInput stream is probably mispositioned now." << std::endl; 00194 return; 00195 } 00196 v.push_back(xin); 00197 } 00198 getState(v); 00199 return; 00200 } 00201 00202 if (!inFile.bad()) { 00203 // inFile >> theSeed; removed -- encompased by possibleKeywordInput 00204 for (int i = 0; i < numBuff; ++i) { 00205 inFile >> buffer[i]; 00206 } 00207 inFile >> redSpin >> numFlats >> halfBuff; 00208 } 00209 } 00210 00211 void RanshiEngine::showStatus() const { 00212 std::cout << std::setprecision(20) << std::endl; 00213 std::cout << "----------- Ranshi engine status ----------" << std::endl; 00214 std::cout << "Initial seed = " << theSeed << std::endl; 00215 std::cout << "Current red spin = " << redSpin << std::endl; 00216 std::cout << "Values produced = " << numFlats << std::endl; 00217 std::cout << "Side of buffer = " << (halfBuff ? "upper" : "lower") 00218 << std::endl; 00219 std::cout << "Current buffer = " << std::endl; 00220 for (int i = 0; i < numBuff; i+=4) { 00221 std::cout << std::setw(10) << std::setiosflags(std::ios::right) 00222 << buffer[i] << std::setw(11) << buffer[i+1] << std::setw(11) 00223 << buffer[i+2] << std::setw(11) << buffer[i+3] << std::endl; 00224 } 00225 std::cout << "-------------------------------------------" << std::endl; 00226 } 00227 00228 RanshiEngine::operator float() { 00229 unsigned int redAngle = (((numBuff/2) - 1) & redSpin) + halfBuff; 00230 unsigned int blkSpin = buffer[redAngle] & 0xffffffff; 00231 00232 buffer[redAngle] = ((blkSpin << 17) | (blkSpin >> (32-17))) ^ redSpin; 00233 00234 redSpin = (blkSpin + numFlats++) & 0xffffffff; 00235 halfBuff = numBuff/2 - halfBuff; 00236 00237 return float(blkSpin * twoToMinus_32()); 00238 } 00239 00240 RanshiEngine::operator unsigned int() { 00241 unsigned int redAngle = (((numBuff/2) - 1) & redSpin) + halfBuff; 00242 unsigned int blkSpin = buffer[redAngle] & 0xffffffff; 00243 00244 buffer[redAngle] = ((blkSpin << 17) | (blkSpin >> (32-17))) ^ redSpin; 00245 00246 redSpin = (blkSpin + numFlats++) & 0xffffffff; 00247 halfBuff = numBuff/2 - halfBuff; 00248 00249 return blkSpin; 00250 } 00251 00252 std::ostream& RanshiEngine::put (std::ostream& os ) const { 00253 char beginMarker[] = "RanshiEngine-begin"; 00254 os << beginMarker << "\nUvec\n"; 00255 std::vector<unsigned long> v = put(); 00256 for (unsigned int i=0; i<v.size(); ++i) { 00257 os << v[i] << "\n"; 00258 } 00259 return os; 00260 #ifdef REMOVED 00261 char endMarker[] = "RanshiEngine-end"; 00262 int pr=os.precision(20); 00263 os << " " << beginMarker << " "; 00264 00265 os << theSeed << "\n"; 00266 for (int i = 0; i < numBuff; ++i) { 00267 os << buffer[i] << "\n"; 00268 } 00269 os << redSpin << " " << numFlats << "\n" << halfBuff; 00270 00271 os << " " << endMarker << "\n"; 00272 os.precision(pr); 00273 return os; 00274 #endif 00275 } 00276 00277 std::vector<unsigned long> RanshiEngine::put () const { 00278 std::vector<unsigned long> v; 00279 v.push_back (engineIDulong<RanshiEngine>()); 00280 for (int i = 0; i < numBuff; ++i) { 00281 v.push_back(static_cast<unsigned long>(buffer[i])); 00282 } 00283 v.push_back(static_cast<unsigned long>(redSpin)); 00284 v.push_back(static_cast<unsigned long>(numFlats)); 00285 v.push_back(static_cast<unsigned long>(halfBuff)); 00286 return v; 00287 } 00288 00289 std::istream& RanshiEngine::get (std::istream& is) { 00290 char beginMarker [MarkerLen]; 00291 is >> std::ws; 00292 is.width(MarkerLen); // causes the next read to the char* to be <= 00293 // that many bytes, INCLUDING A TERMINATION \0 00294 // (Stroustrup, section 21.3.2) 00295 is >> beginMarker; 00296 if (strcmp(beginMarker,"RanshiEngine-begin")) { 00297 is.clear(std::ios::badbit | is.rdstate()); 00298 std::cerr << "\nInput mispositioned or" 00299 << "\nRanshiEngine state description missing or" 00300 << "\nwrong engine type found." << std::endl; 00301 return is; 00302 } 00303 return getState(is); 00304 } 00305 00306 std::string RanshiEngine::beginTag ( ) { 00307 return "RanshiEngine-begin"; 00308 } 00309 00310 std::istream& RanshiEngine::getState (std::istream& is) { 00311 if ( possibleKeywordInput ( is, "Uvec", theSeed ) ) { 00312 std::vector<unsigned long> v; 00313 unsigned long uu; 00314 for (unsigned int ivec=0; ivec < VECTOR_STATE_SIZE; ++ivec) { 00315 is >> uu; 00316 if (!is) { 00317 is.clear(std::ios::badbit | is.rdstate()); 00318 std::cerr << "\nRanshiEngine state (vector) description improper." 00319 << "\ngetState() has failed." 00320 << "\nInput stream is probably mispositioned now." << std::endl; 00321 return is; 00322 } 00323 v.push_back(uu); 00324 } 00325 getState(v); 00326 return (is); 00327 } 00328 00329 // is >> theSeed; Removed, encompassed by possibleKeywordInput() 00330 00331 char endMarker [MarkerLen]; 00332 for (int i = 0; i < numBuff; ++i) { 00333 is >> buffer[i]; 00334 } 00335 is >> redSpin >> numFlats >> halfBuff; 00336 is >> std::ws; 00337 is.width(MarkerLen); 00338 is >> endMarker; 00339 if (strcmp(endMarker,"RanshiEngine-end")) { 00340 is.clear(std::ios::badbit | is.rdstate()); 00341 std::cerr << "\nRanshiEngine state description incomplete." 00342 << "\nInput stream is probably mispositioned now." << std::endl; 00343 return is; 00344 } 00345 return is; 00346 } 00347 00348 bool RanshiEngine::get (const std::vector<unsigned long> & v) { 00349 if ((v[0] & 0xffffffffUL) != engineIDulong<RanshiEngine>()) { 00350 std::cerr << 00351 "\nRanshiEngine get:state vector has wrong ID word - state unchanged\n"; 00352 return false; 00353 } 00354 return getState(v); 00355 } 00356 00357 bool RanshiEngine::getState (const std::vector<unsigned long> & v) { 00358 if (v.size() != VECTOR_STATE_SIZE ) { 00359 std::cerr << 00360 "\nRanshiEngine get:state vector has wrong length - state unchanged\n"; 00361 return false; 00362 } 00363 for (int i = 0; i < numBuff; ++i) { 00364 buffer[i] = v[i+1]; 00365 } 00366 redSpin = v[numBuff+1]; 00367 numFlats = v[numBuff+2]; 00368 halfBuff = v[numBuff+3]; 00369 return true; 00370 } 00371 00372 } // namespace CLHEP