CMS 3D CMS Logo

SprRanluxEngine.cc

Go to the documentation of this file.
00001 // $Id: SprRanluxEngine.cc,v 1.2 2007/09/21 22:32:10 narsky Exp $
00002 // -*- C++ -*-
00003 //
00004 // -----------------------------------------------------------------------
00005 //                             HEP Random
00006 //                        --- RanluxEngine ---
00007 //                      class implementation file
00008 // -----------------------------------------------------------------------
00009 // This file is part of Geant4 (simulation toolkit for HEP).
00010 //
00011 // Ranlux random number generator originally implemented in FORTRAN77
00012 // by Fred James as part of the MATHLIB HEP library.
00013 // 'RanluxEngine' is designed to fit into the CLHEP random number
00014 // class structure.
00015 
00016 // ===============================================================
00017 // Adeyemi Adesanya - Created: 6th November 1995
00018 // Gabriele Cosmo - Adapted & Revised: 22nd November 1995
00019 // Adeyemi Adesanya - Added setSeeds() method: 2nd February 1996
00020 // Gabriele Cosmo - Added flatArray() method: 8th February 1996
00021 //                - Minor corrections: 31st October 1996
00022 //                - Added methods for engine status: 19th November 1996
00023 //                - Fixed bug in setSeeds(): 15th September 1997
00024 // J.Marraffino   - Added stream operators and related constructor.
00025 //                  Added automatic seed selection from seed table and
00026 //                  engine counter: 14th Feb 1998
00027 //                - Fixed bug: setSeeds() requires a zero terminated
00028 //                  array of seeds: 19th Feb 1998
00029 // Ken Smith      - Added conversion operators:  6th Aug 1998
00030 // J. Marraffino  - Remove dependence on hepString class  13 May 1999
00031 // M. Fischler    - In restore, checkFile for file not found    03 Dec 2004
00032 // M. Fischler    - Methods put, getfor instance save/restore       12/8/04    
00033 // M. Fischler    - split get() into tag validation and 
00034 //                  getState() for anonymous restores           12/27/04    
00035 // M. Fischler    - put/get for vectors of ulongs               3/14/05
00036 // M. Fischler    - State-saving using only ints, for portability 4/12/05
00037 //
00038 // ===============================================================
00039 
00040 #include "SprRanluxEngine.hh"
00041 #include "SprSeedTable.hh"
00042 #include <cmath>        // for pow()
00043 #include <cstdlib>      // for abs() and div()
00044 //#include <iostream>
00045 
00046 using namespace std;
00047 
00048 
00049 const int SprRanluxEngine::int_modulus = 0x1000000;
00050 const double SprRanluxEngine::mantissa_bit_24 = pow(0.5,24.);
00051 const double SprRanluxEngine::mantissa_bit_12 = pow(0.5,12.);
00052 
00053 // Number of instances with automatic seed selection
00054 int SprRanluxEngine::numEngines = 0;
00055 
00056 // Maximum index into the seed table
00057 const int SprRanluxEngine::maxIndex = 215;
00058 
00059 SprRanluxEngine::SprRanluxEngine(long seed, int lux) {
00060    luxury = lux;
00061    setSeed(seed, luxury);
00062 }
00063 
00064 SprRanluxEngine::~SprRanluxEngine() {}
00065 
00066 void SprRanluxEngine::setSeed(long seed, int lux) {
00067 
00068   // default seed from seed table
00069   if (seed == 0) {
00070     div_t temp = div(numEngines, maxIndex);
00071     numEngines++;
00072     seed = seedTable[abs(temp.rem)][0] ^ ((abs(temp.quot) & 0x007fffff) << 8);
00073   }
00074 
00075 // The initialisation is carried out using a Multiplicative
00076 // Congruential generator using formula constants of L'Ecuyer 
00077 // as described in "A review of pseudorandom number generators"
00078 // (Fred James) published in Computer Physics Communications 60 (1990)
00079 // pages 329-344
00080 
00081   const int ecuyer_a = 53668;
00082   const int ecuyer_b = 40014;
00083   const int ecuyer_c = 12211;
00084   const int ecuyer_d = 2147483563;
00085 
00086   const int lux_levels[5] = {0,24,73,199,365};  
00087 
00088 // number of additional random numbers that need to be 'thrown away'
00089 // every 24 numbers is set using luxury level variable.
00090 
00091   theSeed = seed;
00092   if( (lux > 4)||(lux < 0) ){
00093      if(lux >= 24){
00094         nskip = lux - 24;
00095      }else{
00096         nskip = lux_levels[3]; // corresponds to default luxury level
00097      }
00098   }else{
00099      luxury = lux;
00100      nskip = lux_levels[luxury];
00101   }
00102 
00103    
00104   long next_seed = seed;
00105   for(int i = 0;i < 24;i++){
00106      long k_multiple = next_seed / ecuyer_a;
00107      next_seed = ecuyer_b * (next_seed - k_multiple * ecuyer_a) 
00108        - k_multiple * ecuyer_c ;
00109      if(next_seed < 0)next_seed += ecuyer_d;
00110      float_seed_table[i] = (next_seed % int_modulus) * mantissa_bit_24;
00111   }     
00112 
00113   i_lag = 23;
00114   j_lag = 9;
00115   carry = 0. ;
00116 
00117   if( float_seed_table[23] == 0. ) carry = mantissa_bit_24;
00118   
00119   count24 = 0;
00120 }
00121 
00122 double SprRanluxEngine::flat() {
00123 
00124   float next_random;
00125   float uni;
00126   int i;
00127 
00128   uni = float_seed_table[j_lag] - float_seed_table[i_lag] - carry;
00129   if(uni < 0. ){
00130      uni += 1.0;
00131      carry = mantissa_bit_24;
00132   }else{
00133      carry = 0.;
00134   }
00135 
00136   float_seed_table[i_lag] = uni;
00137   i_lag --;
00138   j_lag --;
00139   if(i_lag < 0) i_lag = 23;
00140   if(j_lag < 0) j_lag = 23;
00141 
00142   if( uni < mantissa_bit_12 ){
00143      uni += mantissa_bit_24 * float_seed_table[j_lag];
00144      if( uni == 0) uni = mantissa_bit_24 * mantissa_bit_24;
00145   }
00146   next_random = uni;
00147   count24 ++;
00148 
00149 // every 24th number generation, several random numbers are generated
00150 // and wasted depending upon the luxury level.
00151 
00152   if(count24 == 24 ){
00153      count24 = 0;
00154      for( i = 0; i != nskip ; i++){
00155          uni = float_seed_table[j_lag] - float_seed_table[i_lag] - carry;
00156          if(uni < 0. ){
00157             uni += 1.0;
00158             carry = mantissa_bit_24;
00159          }else{
00160             carry = 0.;
00161          }
00162          float_seed_table[i_lag] = uni;
00163          i_lag --;
00164          j_lag --;
00165          if(i_lag < 0)i_lag = 23;
00166          if(j_lag < 0) j_lag = 23;
00167       }
00168   } 
00169   return (double) next_random;
00170 }
00171 
00172 void SprRanluxEngine::flatArray(int size, double* vect)
00173 {
00174   float next_random;
00175   float uni;
00176   int i;
00177   int index;
00178 
00179   for (index=0; index<size; ++index) {
00180     uni = float_seed_table[j_lag] - float_seed_table[i_lag] - carry;
00181     if(uni < 0. ){
00182        uni += 1.0;
00183        carry = mantissa_bit_24;
00184     }else{
00185        carry = 0.;
00186     }
00187 
00188     float_seed_table[i_lag] = uni;
00189     i_lag --;
00190     j_lag --;
00191     if(i_lag < 0) i_lag = 23;
00192     if(j_lag < 0) j_lag = 23;
00193 
00194     if( uni < mantissa_bit_12 ){
00195        uni += mantissa_bit_24 * float_seed_table[j_lag];
00196        if( uni == 0) uni = mantissa_bit_24 * mantissa_bit_24;
00197     }
00198     next_random = uni;
00199     vect[index] = (double)next_random;
00200     count24 ++;
00201 
00202 // every 24th number generation, several random numbers are generated
00203 // and wasted depending upon the luxury level.
00204 
00205     if(count24 == 24 ){
00206        count24 = 0;
00207        for( i = 0; i != nskip ; i++){
00208            uni = float_seed_table[j_lag] - float_seed_table[i_lag] - carry;
00209            if(uni < 0. ){
00210               uni += 1.0;
00211               carry = mantissa_bit_24;
00212            }else{
00213               carry = 0.;
00214            }
00215            float_seed_table[i_lag] = uni;
00216            i_lag --;
00217            j_lag --;
00218            if(i_lag < 0)i_lag = 23;
00219            if(j_lag < 0) j_lag = 23;
00220         }
00221     }
00222   }
00223 } 

Generated on Tue Jun 9 17:42:03 2009 for CMSSW by  doxygen 1.5.4