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

Hurd160Engine.cc

Go to the documentation of this file.
00001 // $Id: Hurd160Engine.cc,v 1.7 2010/07/20 18:07:17 garren Exp $
00002 // -*- C++ -*-
00003 //
00004 // -----------------------------------------------------------------------
00005 //                           HEP Random
00006 // Ken Smith      - Initial draft started:                    23rd Jul 1998
00007 //                - Added conversion operators:                6th Aug 1998
00008 // J. Marraffino  - Added some explicit casts to deal with
00009 //                  machines where sizeof(int) != sizeof(long)  22 Aug 1998
00010 // M. Fischler    - Modified use of the various exponents of 2
00011 //                  to avoid per-instance space overhead and
00012 //                  correct the rounding procedure              15 Sep 1998
00013 //                - Modified various methods to avoid any
00014 //                  possibility of predicting the next number
00015 //                  based on the last several:  We skip one 
00016 //                  32-bit word per cycle.                      15 Sep 1998
00017 //                - modify word[0] in two of the constructors
00018 //                  so that no sequence can ever accidentally
00019 //                  be produced by differnt seeds.              15 Sep 1998
00020 // J. Marraffino  - Remove dependence on hepStrings class       13 May 1999
00021 // M. Fischler    - Put endl at end of a save                   10 Apr 2001
00022 // M. Fischler    - In restore, checkFile for file not found    03 Dec 2004
00023 // M. Fischler    - Methods put, get for instance save/restore   12/8/04    
00024 // M. Fischler    - split get() into tag validation and 
00025 //                  getState() for anonymous restores           12/27/04    
00026 // M. Fischler    - put/get for vectors of ulongs               3/14/05
00027 // M. Fischler    - State-saving using only ints, for portability 4/12/05
00028 //                  
00029 // =======================================================================
00030 
00031 #include "CLHEP/Random/defs.h"
00032 #include "CLHEP/Random/Random.h"
00033 #include "CLHEP/Random/Hurd160Engine.h"
00034 #include "CLHEP/Random/engineIDulong.h"
00035 #include <string.h>     // for strcmp
00036 #include <cstdlib>      // for std::abs(int)
00037 
00038 namespace CLHEP {
00039 
00040 static const int MarkerLen = 64; // Enough room to hold a begin or end marker. 
00041 
00042 std::string Hurd160Engine::name() const {return "Hurd160Engine";}
00043 
00044 // Number of instances with automatic seed selection
00045 int Hurd160Engine::numEngines = 0;
00046 
00047 // Maximum index into the seed table
00048 int Hurd160Engine::maxIndex = 215;
00049 
00050 static inline unsigned int f160(unsigned int a, unsigned int b, unsigned int c)
00051 {
00052   return ( ((b<<2) & 0x7c) | ((a<<2) & ~0x7c) | (a>>30) ) ^ ( (c<<1)|(c>>31) );
00053 }
00054 
00055 Hurd160Engine::Hurd160Engine()
00056 : HepRandomEngine()
00057 {
00058   int cycle    = std::abs(int(numEngines/maxIndex));
00059   int curIndex = std::abs(int(numEngines%maxIndex));
00060   long mask = ((cycle & 0x007fffff) << 8);
00061   long seedlist[2];
00062   HepRandom::getTheTableSeeds( seedlist, curIndex );
00063   seedlist[0] ^= mask;
00064   seedlist[1] = 0;
00065   setSeeds(seedlist, 0);
00066   words[0] ^= 0x1324abcd;        // To make unique vs long or two unsigned
00067   if (words[0]==0) words[0] = 1; // ints in the constructor
00068   ++numEngines;
00069   for( int i=0; i < 100; ++i ) flat();            // warm-up just a bit
00070 }
00071 
00072 Hurd160Engine::Hurd160Engine( std::istream& is )
00073 : HepRandomEngine()
00074 {
00075     is >> *this;
00076 }
00077 
00078 Hurd160Engine::Hurd160Engine( long seed )
00079 : HepRandomEngine()
00080 {
00081   long seedlist[2]={seed,0};
00082   setSeeds(seedlist, 0);
00083   words[0] ^= 0xa5482134;        // To make unique vs default two unsigned
00084   if (words[0]==0) words[0] = 1; // ints in the constructor
00085   for( int i=0; i < 100; ++i ) flat();            // warm-up just a bit
00086 }
00087 
00088 Hurd160Engine::Hurd160Engine( int rowIndex, int colIndex )
00089 : HepRandomEngine()
00090 {
00091   int cycle = std::abs(int(rowIndex/maxIndex));
00092   int   row = std::abs(int(rowIndex%maxIndex));
00093   int   col = colIndex & 0x1;
00094   long mask = (( cycle & 0x000007ff ) << 20 );
00095   long seedlist[2];
00096   HepRandom::getTheTableSeeds( seedlist, row );
00097   // NOTE: is that really the seed wanted (PGC) ??
00098   seedlist[0] = (seedlist[col])^mask;
00099   seedlist[1]= 0;
00100   setSeeds(seedlist, 0);
00101   for( int i=0; i < 100; ++i ) flat();            // warm-up just a bit
00102 }
00103 
00104 Hurd160Engine::~Hurd160Engine() { }
00105 
00106 void Hurd160Engine::advance() {
00107      register unsigned int W0, W1, W2, W3, W4;
00108 
00109      W0 = words[0];
00110      W1 = words[1];
00111      W2 = words[2];
00112      W3 = words[3];
00113      W4 = words[4];
00114      W1 ^= W0; W0 = f160(W4, W3, W0);
00115      W2 ^= W1; W1 = f160(W0, W4, W1);
00116      W3 ^= W2; W2 = f160(W1, W0, W2);
00117      W4 ^= W3; W3 = f160(W2, W1, W3);
00118      W0 ^= W4; W4 = f160(W3, W2, W4);
00119      words[0] = W0 & 0xffffffff;
00120      words[1] = W1 & 0xffffffff;
00121      words[2] = W2 & 0xffffffff;
00122      words[3] = W3 & 0xffffffff;
00123      words[4] = W4 & 0xffffffff;
00124      wordIndex = 5;
00125 
00126 } // advance();
00127 
00128 double Hurd160Engine::flat() {
00129 
00130   if( wordIndex <= 2 ) {        // MF 9/15/98:
00131                                 // skip word 0 and use two words per flat
00132     advance();
00133   }
00134 
00135   // LG 6/30/2010
00136   // define the order of execution for --wordIndex
00137   double x = words[--wordIndex] * twoToMinus_32() ; // most significant part
00138   double y = (words[--wordIndex]>>11) * twoToMinus_53() + // fill in rest of bits
00139              nearlyTwoToMinus_54();        // make sure non-zero
00140   return  x + y ;
00141 }
00142 
00143 void Hurd160Engine::flatArray( const int size, double* vect ) {
00144     for (int i = 0; i < size; ++i) {
00145         vect[i] = flat();
00146     }
00147 }
00148 
00149 void Hurd160Engine::setSeed( long seed, int ) {
00150   words[0] = (unsigned int)seed;
00151   for (wordIndex = 1; wordIndex < 5; ++wordIndex) {
00152     words[wordIndex] = 69607 * words[wordIndex-1] + 54329;
00153   }
00154 }
00155 
00156 void Hurd160Engine::setSeeds( const long* seeds, int ) {
00157   setSeed( *seeds ? *seeds : 32767, 0 );
00158   theSeeds = seeds;
00159 }
00160      
00161 void Hurd160Engine::saveStatus( const char filename[] ) const {
00162   std::ofstream outFile(filename, std::ios::out);
00163   if( !outFile.bad() ) {
00164     outFile << "Uvec\n";
00165     std::vector<unsigned long> v = put();
00166                      #ifdef TRACE_IO
00167                          std::cout << "Result of v = put() is:\n"; 
00168                      #endif
00169     for (unsigned int i=0; i<v.size(); ++i) {
00170       outFile << v[i] << "\n";
00171                      #ifdef TRACE_IO
00172                            std::cout << v[i] << " ";
00173                            if (i%6==0) std::cout << "\n";
00174                      #endif
00175     }
00176                      #ifdef TRACE_IO
00177                          std::cout << "\n";
00178                      #endif
00179   }
00180 #ifdef REMOVED
00181     outFile << std::setprecision(20) << theSeed << " ";
00182     outFile << wordIndex << " ";
00183     for( int i = 0; i < 5; ++i ) {
00184       outFile << words[i] << " ";
00185     }
00186     outFile << std::endl;
00187 #endif
00188 }
00189 
00190 void Hurd160Engine::restoreStatus( const char filename[] ) {
00191   std::ifstream inFile(filename, std::ios::in);
00192   if (!checkFile ( inFile, filename, engineName(), "restoreStatus" )) { 
00193     std::cerr << "  -- Engine state remains unchanged\n";                 
00194     return;                                                               
00195   }                                                                       
00196   if ( possibleKeywordInput ( inFile, "Uvec", theSeed ) ) {
00197     std::vector<unsigned long> v;
00198     unsigned long xin;
00199     for (unsigned int ivec=0; ivec < VECTOR_STATE_SIZE; ++ivec) {
00200       inFile >> xin;
00201                #ifdef TRACE_IO
00202                std::cout << "ivec = " << ivec << "  xin = " << xin << "    ";
00203                if (ivec%3 == 0) std::cout << "\n"; 
00204                #endif
00205       if (!inFile) {
00206         inFile.clear(std::ios::badbit | inFile.rdstate());
00207         std::cerr << "\nHurd160Engine state (vector) description improper."
00208                << "\nrestoreStatus has failed."
00209                << "\nInput stream is probably mispositioned now." << std::endl;
00210         return;
00211       }
00212       v.push_back(xin);
00213     }
00214     getState(v);
00215     return;
00216   }
00217 
00218   if( !inFile.bad() ) {
00219 //     inFile >> theSeed;  removed -- encompased by possibleKeywordInput
00220     inFile >> wordIndex;
00221     for( int i = 0; i < 5; ++i ) {
00222         inFile >> words[i];
00223     }
00224   }
00225 }
00226 
00227 void Hurd160Engine::showStatus() const {
00228   int pr = std::cout.precision(20);
00229   std::cout << std::endl;
00230   std::cout << "----------- Hurd engine status ----------" << std::endl;
00231   std::cout << "Initial seed  = " << theSeed   << std::endl;
00232   std::cout << "Current index = " << wordIndex << std::endl;
00233   std::cout << "Current words = " << std::endl;
00234   for( int i = 0; i < 5 ; ++i ) {
00235     std::cout << "    " << words[i] << std::endl;
00236   }
00237   std::cout << "------------------------------------------" << std::endl;
00238   std::cout.precision(pr);
00239 }
00240 
00241 Hurd160Engine::operator float() {
00242   if( wordIndex <= 1 ) {        // MF 9/15/98:  skip word 0
00243     advance();
00244   }
00245   return words[--wordIndex ] * twoToMinus_32();
00246 }
00247 
00248 Hurd160Engine::operator unsigned int() {
00249   if( wordIndex <= 1 ) {        // MF 9/15/98:  skip word 0
00250     advance();
00251   }
00252   return words[--wordIndex];
00253 }
00254 
00255 std::ostream& Hurd160Engine::put(std::ostream& os) const {
00256   char beginMarker[] = "Hurd160Engine-begin";
00257   os << beginMarker << "\nUvec\n";
00258   std::vector<unsigned long> v = put();
00259   for (unsigned int i=0; i<v.size(); ++i) {
00260      os <<  v[i] <<  "\n";
00261   }
00262   return os;  
00263 #ifdef REMOVED 
00264   char endMarker[]   = "Hurd160Engine-end";
00265   int pr = os.precision(20);
00266   os << " " << beginMarker << " ";
00267   os << theSeed  << " ";
00268   os << wordIndex << " ";
00269   for (int i = 0; i < 5; ++i) {
00270     os << words[i]  << "\n";
00271   }
00272   os << endMarker   << "\n ";
00273   os.precision(pr);
00274   return os;
00275 #endif
00276 }
00277 
00278 std::vector<unsigned long> Hurd160Engine::put () const {
00279   std::vector<unsigned long> v;
00280   v.push_back (engineIDulong<Hurd160Engine>());
00281   v.push_back(static_cast<unsigned long>(wordIndex));
00282   for (int i = 0; i < 5; ++i) {
00283     v.push_back(static_cast<unsigned long>(words[i]));
00284   }
00285   return v;
00286 }
00287 
00288 
00289 std::istream& Hurd160Engine::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,"Hurd160Engine-begin")) {
00297     is.clear(std::ios::badbit | is.rdstate());
00298     std::cerr << "\nInput mispositioned or"
00299               << "\nHurd160Engine state description missing or"
00300               << "\nwrong engine type found." << std::endl;
00301     return is;
00302   }
00303   return getState(is);
00304 }
00305 
00306 std::string Hurd160Engine::beginTag ( )  { 
00307   return "Hurd160Engine-begin"; 
00308 }
00309 
00310 std::istream& Hurd160Engine::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 << "\nHurd160Engine 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   is >> wordIndex;
00333   for (int i = 0; i < 5; ++i) {
00334     is >> words[i];
00335   }
00336   is >> std::ws;
00337   is.width(MarkerLen);
00338   is >> endMarker;
00339   if (strcmp(endMarker,"Hurd160Engine-end")) {
00340     is.clear(std::ios::badbit | is.rdstate());
00341     std::cerr << "\nHurd160Engine state description incomplete."
00342               << "\nInput stream is probably mispositioned now." << std::endl;
00343     return is;
00344   }
00345   return is;
00346 }
00347 
00348 
00349 bool Hurd160Engine::get (const std::vector<unsigned long> & v) {
00350   if ((v[0] & 0xffffffffUL) != engineIDulong<Hurd160Engine>()) {
00351     std::cerr << 
00352         "\nHurd160Engine get:state vector has wrong ID word - state unchanged\n";
00353     return false;
00354   }
00355   return getState(v);
00356 }
00357 
00358 bool Hurd160Engine::getState (const std::vector<unsigned long> & v) {
00359   if (v.size() != VECTOR_STATE_SIZE ) {
00360     std::cerr << 
00361         "\nHurd160Engine get:state vector has wrong length - state unchanged\n";
00362     return false;
00363   }
00364   wordIndex = v[1];
00365   for (int i = 0; i < 5; ++i) {
00366     words[i] = v[i+2];
00367   }
00368   return true;
00369 }
00370 
00371 
00372 }  // namespace CLHEP

Generated on 15 Nov 2012 for CLHEP by  doxygen 1.4.7