RanshiEngine.cc

Go to the documentation of this file.
00001 // $Id:$
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 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/RanshiEngine.h"
00036 #include "CLHEP/Random/engineIDulong.h"
00037 #include <string.h>     // for strcmp
00038 
00039 namespace CLHEP {
00040 
00041 static const int MarkerLen = 64; // Enough room to hold a begin or end marker. 
00042 
00043 std::string RanshiEngine::name() const {return "RanshiEngine";}
00044 
00045 // Number of instances with automatic seed selection
00046 int RanshiEngine::numEngines = 0;
00047 
00048 RanshiEngine::RanshiEngine()
00049 : HepRandomEngine(),
00050   halfBuff(0), numFlats(0) 
00051 {
00052   int i = 0;
00053   while (i < numBuff) {    
00054     buffer[i] = (unsigned int)(numEngines+19780503L*(i+1));
00055     ++i;
00056   }
00057   theSeed = numEngines+19780503L*++i;
00058   redSpin = (unsigned int)(theSeed & 0xffffffff);
00059   ++numEngines;
00060   for( i = 0; i < 10000; ++i) flat();  // Warm-up by running thorugh 10000 nums
00061 }
00062 
00063 RanshiEngine::RanshiEngine(std::istream& is)
00064 : HepRandomEngine(),
00065   halfBuff(0), numFlats(0) 
00066 {
00067   is >> *this;
00068 }
00069 
00070 RanshiEngine::RanshiEngine(long seed)
00071 : HepRandomEngine(),
00072   halfBuff(0), numFlats(0) 
00073 {
00074   for (int i = 0; i < numBuff; ++i) {
00075     buffer[i] = (unsigned int)seed&0xffffffff;
00076   }
00077   theSeed = seed;
00078   redSpin = (unsigned int)(theSeed & 0xffffffff);
00079   int j;
00080   for (j = 0; j < numBuff*20; ++j) {      // "warm-up" for engine to hit
00081     flat();                               //  every ball on average 20X.
00082   }
00083 }
00084 
00085 RanshiEngine::RanshiEngine(int rowIndex, int colIndex)
00086 : HepRandomEngine(),
00087   halfBuff(0), numFlats(0) 
00088 {
00089   int i = 0;
00090   while( i < numBuff ) {
00091     buffer[i] = (unsigned int)((rowIndex + (i+1)*(colIndex+8))&0xffffffff);
00092     ++i;
00093   }
00094   theSeed = rowIndex;
00095   redSpin = colIndex & 0xffffffff;
00096   for( i = 0; i < 100; ++i) flat();    // Warm-up by running thorugh 100 nums
00097 }
00098 
00099 RanshiEngine::~RanshiEngine() { }
00100 
00101 double RanshiEngine::flat() {
00102   unsigned int redAngle = (((numBuff/2) - 1) & redSpin) + halfBuff;
00103   unsigned int blkSpin     = buffer[redAngle] & 0xffffffff;
00104   unsigned int boostResult = blkSpin ^ redSpin;
00105 
00106   buffer[redAngle] = ((blkSpin << 17) | (blkSpin >> (32-17))) ^ redSpin;
00107   
00108   redSpin  = (blkSpin + numFlats++) & 0xffffffff;
00109   halfBuff = numBuff/2 - halfBuff;
00110   
00111   return ( blkSpin * twoToMinus_32() +            // most significant part
00112            (boostResult>>11) * twoToMinus_53() +  // fill in remaining bits
00113            nearlyTwoToMinus_54());              // non-zero
00114 }
00115 
00116 void RanshiEngine::flatArray(const int size, double* vect) {
00117   for (int i = 0; i < size; ++i) {
00118     vect[i] = flat();
00119   }
00120 }
00121 
00122 void RanshiEngine::setSeed(long seed, int) {
00123   *this = RanshiEngine(seed); 
00124 }
00125 
00126 void RanshiEngine::setSeeds(const long* seeds, int) {
00127   if (*seeds) {
00128     int i = 0;
00129     while (seeds[i] && i < numBuff) {
00130       buffer[i] = (unsigned int)seeds[i];
00131       ++i;
00132     }
00133     while (i < numBuff) {
00134       buffer[i] = buffer[i-1];
00135       ++i;
00136     }
00137     theSeed = seeds[0];
00138     redSpin = (unsigned int)theSeed;
00139   }
00140   theSeeds = seeds;
00141 }
00142      
00143 void RanshiEngine::saveStatus(const char filename[]) const {
00144   std::ofstream outFile(filename, std::ios::out);
00145   if (!outFile.bad()) {
00146     outFile << "Uvec\n";
00147     std::vector<unsigned long> v = put();
00148     for (unsigned int i=0; i<v.size(); ++i) {
00149       outFile << v[i] << "\n";
00150     }
00151   }
00152 }
00153 
00154 void RanshiEngine::restoreStatus(const char filename[]) {
00155   std::ifstream inFile(filename, std::ios::in);
00156   if (!checkFile ( inFile, filename, engineName(), "restoreStatus" )) {
00157     std::cerr << "  -- Engine state remains unchanged\n";
00158     return;
00159   }
00160   if ( possibleKeywordInput ( inFile, "Uvec", theSeed ) ) {
00161     std::vector<unsigned long> v;
00162     unsigned long xin;
00163     for (unsigned int ivec=0; ivec < VECTOR_STATE_SIZE; ++ivec) {
00164       inFile >> xin;
00165       if (!inFile) {
00166         inFile.clear(std::ios::badbit | inFile.rdstate());
00167         std::cerr << "\nRanshiEngine state (vector) description improper."
00168                << "\nrestoreStatus has failed."
00169                << "\nInput stream is probably mispositioned now." << std::endl;
00170         return;
00171       }
00172       v.push_back(xin);
00173     }
00174     getState(v);
00175     return;
00176   }
00177 
00178   if (!inFile.bad()) {
00179 //     inFile >> theSeed;  removed -- encompased by possibleKeywordInput
00180     for (int i = 0; i < numBuff; ++i) {
00181       inFile >> buffer[i];
00182     }
00183     inFile >> redSpin >> numFlats >> halfBuff;
00184   }
00185 }
00186 
00187 void RanshiEngine::showStatus() const {
00188   std::cout << std::setprecision(20) << std::endl;
00189   std::cout << "----------- Ranshi engine status ----------" << std::endl;
00190   std::cout << "Initial seed      = " << theSeed << std::endl;
00191   std::cout << "Current red spin  = " << redSpin << std::endl;
00192   std::cout << "Values produced   = " << numFlats << std::endl;
00193   std::cout << "Side of buffer    = " << (halfBuff ? "upper" : "lower")
00194             << std::endl;
00195   std::cout << "Current buffer    = " << std::endl;
00196   for (int i = 0; i < numBuff; i+=4) {
00197     std::cout << std::setw(10) << std::setiosflags(std::ios::right)
00198               << buffer[i]     << std::setw(11) << buffer[i+1] << std::setw(11)
00199               << buffer[i+2]   << std::setw(11) << buffer[i+3] << std::endl;
00200   }
00201   std::cout << "-------------------------------------------" << std::endl;
00202 }
00203 
00204 RanshiEngine::operator float() {
00205   unsigned int redAngle = (((numBuff/2) - 1) & redSpin) + halfBuff;
00206   unsigned int blkSpin  = buffer[redAngle] & 0xffffffff;
00207   
00208   buffer[redAngle] = ((blkSpin << 17) | (blkSpin >> (32-17))) ^ redSpin;
00209   
00210   redSpin  = (blkSpin + numFlats++) & 0xffffffff;
00211   halfBuff = numBuff/2 - halfBuff;
00212   
00213   return float(blkSpin * twoToMinus_32());
00214 }
00215 
00216 RanshiEngine::operator unsigned int() {
00217   unsigned int redAngle = (((numBuff/2) - 1) & redSpin) + halfBuff;
00218   unsigned int blkSpin  = buffer[redAngle] & 0xffffffff;
00219   
00220   buffer[redAngle] = ((blkSpin << 17) | (blkSpin >> (32-17))) ^ redSpin;
00221   
00222   redSpin  = (blkSpin + numFlats++) & 0xffffffff;
00223   halfBuff = numBuff/2 - halfBuff;
00224   
00225   return blkSpin;
00226 }
00227 
00228 std::ostream& RanshiEngine::put (std::ostream& os ) const {
00229   char beginMarker[] = "RanshiEngine-begin";
00230   os << beginMarker << "\nUvec\n";
00231   std::vector<unsigned long> v = put();
00232   for (unsigned int i=0; i<v.size(); ++i) {
00233      os <<  v[i] <<  "\n";
00234   }
00235   return os;  
00236 }
00237 
00238 std::vector<unsigned long> RanshiEngine::put () const {
00239   std::vector<unsigned long> v;
00240   v.push_back (engineIDulong<RanshiEngine>());
00241   for (int i = 0; i < numBuff; ++i) {
00242     v.push_back(static_cast<unsigned long>(buffer[i]));
00243   }
00244   v.push_back(static_cast<unsigned long>(redSpin));
00245   v.push_back(static_cast<unsigned long>(numFlats));
00246   v.push_back(static_cast<unsigned long>(halfBuff));  
00247   return v;
00248 }
00249 
00250 std::istream& RanshiEngine::get (std::istream& is) {
00251   char beginMarker [MarkerLen];
00252   is >> std::ws;
00253   is.width(MarkerLen);  // causes the next read to the char* to be <=
00254                         // that many bytes, INCLUDING A TERMINATION \0 
00255                         // (Stroustrup, section 21.3.2)
00256   is >> beginMarker;
00257   if (strcmp(beginMarker,"RanshiEngine-begin")) {
00258     is.clear(std::ios::badbit | is.rdstate());
00259     std::cerr << "\nInput mispositioned or"
00260               << "\nRanshiEngine state description missing or"
00261               << "\nwrong engine type found." << std::endl;
00262     return is;
00263   }
00264   return getState(is);
00265 }
00266 
00267 std::string RanshiEngine::beginTag ( )  { 
00268   return "RanshiEngine-begin"; 
00269 }
00270   
00271 std::istream& RanshiEngine::getState (std::istream& is) {
00272   if ( possibleKeywordInput ( is, "Uvec", theSeed ) ) {
00273     std::vector<unsigned long> v;
00274     unsigned long uu;
00275     for (unsigned int ivec=0; ivec < VECTOR_STATE_SIZE; ++ivec) {
00276       is >> uu;
00277       if (!is) {
00278         is.clear(std::ios::badbit | is.rdstate());
00279         std::cerr << "\nRanshiEngine state (vector) description improper."
00280                 << "\ngetState() has failed."
00281                << "\nInput stream is probably mispositioned now." << std::endl;
00282         return is;
00283       }
00284       v.push_back(uu);
00285     }
00286     getState(v);
00287     return (is);
00288   }
00289 
00290 //  is >> theSeed;  Removed, encompassed by possibleKeywordInput()
00291 
00292   char endMarker   [MarkerLen];
00293   for (int i = 0; i < numBuff; ++i) {
00294     is >> buffer[i];
00295   }
00296   is >> redSpin >> numFlats >> halfBuff;
00297   is >> std::ws;
00298   is.width(MarkerLen);  
00299   is >> endMarker;
00300   if (strcmp(endMarker,"RanshiEngine-end")) {
00301     is.clear(std::ios::badbit | is.rdstate());
00302     std::cerr << "\nRanshiEngine state description incomplete."
00303               << "\nInput stream is probably mispositioned now." << std::endl;
00304     return is;
00305   }
00306   return is;
00307 }
00308 
00309 bool RanshiEngine::get (const std::vector<unsigned long> & v) {
00310   if ((v[0] & 0xffffffffUL) != engineIDulong<RanshiEngine>()) {
00311     std::cerr << 
00312         "\nRanshiEngine get:state vector has wrong ID word - state unchanged\n";
00313     return false;
00314   }
00315   return getState(v);
00316 }
00317 
00318 bool RanshiEngine::getState (const std::vector<unsigned long> & v) {
00319   if (v.size() != VECTOR_STATE_SIZE ) {
00320     std::cerr << 
00321         "\nRanshiEngine get:state vector has wrong length - state unchanged\n";
00322     return false;
00323   }
00324   for (int i = 0; i < numBuff; ++i) {
00325     buffer[i] = v[i+1];
00326   }
00327   redSpin  = v[numBuff+1];
00328   numFlats = v[numBuff+2]; 
00329   halfBuff = v[numBuff+3];
00330   return true;
00331 }
00332 
00333 }  // namespace CLHEP

Generated on Mon May 27 17:50:34 2013 for Geant4 by  doxygen 1.4.7