CLHEP VERSION Reference Documentation
   
CLHEP Home Page     CLHEP Documentation     CLHEP Bug Reports

RanshiEngine.cc

Go to the documentation of this file.
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

Generated on 15 Nov 2012 for CLHEP by  doxygen 1.4.7