Geant4 Cross Reference |
>> 1 // $Id:$ 1 // -*- C++ -*- 2 // -*- C++ -*- 2 // 3 // 3 // ------------------------------------------- 4 // ----------------------------------------------------------------------- 4 // HEP Random 5 // HEP Random 5 // --- Ranlux64Engine -- 6 // --- Ranlux64Engine --- 6 // class implementation f 7 // class implementation file 7 // ------------------------------------------- 8 // ----------------------------------------------------------------------- 8 // A double-precision implementation of the Ra 9 // A double-precision implementation of the RanluxEngine generator as 9 // decsribed by the notes of the original ranl 10 // decsribed by the notes of the original ranlux author (Martin Luscher) 10 // 11 // 11 // See the note by Martin Luscher, December 19 12 // See the note by Martin Luscher, December 1997, entitiled 12 // Double-precision implementation of the rand 13 // Double-precision implementation of the random number generator ranlux 13 // 14 // 14 // =========================================== 15 // ======================================================================= 15 // Ken Smith - Initial draft: 14th Jul 19 16 // Ken Smith - Initial draft: 14th Jul 1998 16 // - Removed pow() from flat me 17 // - Removed pow() from flat method 14th Jul 1998 17 // - Added conversion operators 18 // - Added conversion operators: 6th Aug 1998 18 // 19 // 19 // Mark Fischler The following were modified 20 // Mark Fischler The following were modified mostly to make the routine 20 // exactly match the Luscher algorithm in 21 // exactly match the Luscher algorithm in generating 48-bit 21 // randoms: 22 // randoms: 22 // 9/9/98 - Substantial changes in what used 23 // 9/9/98 - Substantial changes in what used to be flat() to match 23 // algorithm in Luscher's ranlxd.c 24 // algorithm in Luscher's ranlxd.c 24 // - Added update() method for 12 numbers 25 // - Added update() method for 12 numbers, making flat() trivial 25 // - Added advance() method to hold the u 26 // - Added advance() method to hold the unrolled loop for update 26 // - Distinction between three forms of s 27 // - Distinction between three forms of seeding such that it 27 // is impossible to get same sequence f 28 // is impossible to get same sequence from different forms - 28 // done by discarding some fraction of 29 // done by discarding some fraction of one macro cycle which 29 // is different for the three cases 30 // is different for the three cases 30 // - Change the misnomer "seed_table" to 31 // - Change the misnomer "seed_table" to the more accurate 31 // "randoms" 32 // "randoms" 32 // - Removed the no longer needed count12 33 // - Removed the no longer needed count12, i_lag, j_lag, etc. 33 // - Corrected seed procedure which had b 34 // - Corrected seed procedure which had been filling bits past 34 // 2^-48. This actually was very bad, 35 // 2^-48. This actually was very bad, invalidating the 35 // number theory behind the proof that 36 // number theory behind the proof that ranlxd is good. 36 // - Addition of 2**(-49) to generated nu 37 // - Addition of 2**(-49) to generated number to prevent zero 37 // from being returned; this does not a 38 // from being returned; this does not affect the sequence 38 // itself. 39 // itself. 39 // - Corrected ecu seeding, which had bee 40 // - Corrected ecu seeding, which had been supplying only 40 // numbers less than 1/2. This is prob 41 // numbers less than 1/2. This is probably moot. 41 // 9/15/98 - Modified use of the various ex 42 // 9/15/98 - Modified use of the various exponents of 2 42 // to avoid per-instance spac 43 // to avoid per-instance space overhead. Note that these 43 // are initialized in setSeed, which EV 44 // are initialized in setSeed, which EVERY constructor 44 // must invoke. 45 // must invoke. 45 // J. Marraffino - Remove dependence on hepSt 46 // J. Marraffino - Remove dependence on hepString class 13 May 1999 46 // M. Fischler - In restore, checkFile for 47 // M. Fischler - In restore, checkFile for file not found 03 Dec 2004 47 // M. Fischler - put get Methods for distri 48 // M. Fischler - put get Methods for distrib instance save/restore 12/8/04 48 // M. Fischler - split get() into tag valid 49 // M. Fischler - split get() into tag validation and 49 // getState() for anonymous r 50 // getState() for anonymous restores 12/27/04 50 // M. Fischler - put/get for vectors of ulo 51 // M. Fischler - put/get for vectors of ulongs 3/14/05 51 // M. Fischler - State-saving using only in 52 // M. Fischler - State-saving using only ints, for portability 4/12/05 52 // 53 // 53 // =========================================== 54 // ======================================================================= 54 55 55 #include "CLHEP/Random/Random.h" 56 #include "CLHEP/Random/Random.h" 56 #include "CLHEP/Random/Ranlux64Engine.h" 57 #include "CLHEP/Random/Ranlux64Engine.h" 57 #include "CLHEP/Random/engineIDulong.h" 58 #include "CLHEP/Random/engineIDulong.h" 58 #include "CLHEP/Random/DoubConv.h" 59 #include "CLHEP/Random/DoubConv.h" 59 #include "CLHEP/Utility/atomic_int.h" 60 #include "CLHEP/Utility/atomic_int.h" 60 61 61 #include <atomic> << 62 #include <string.h> // for strcmp 62 #include <cstdlib> // for std::abs(int) 63 #include <cstdlib> // for std::abs(int) 63 #include <iostream> << 64 #include <limits> // for numeric_limits 64 #include <limits> // for numeric_limits 65 #include <string.h> // for strcmp << 66 #include <vector> << 67 65 68 namespace CLHEP { 66 namespace CLHEP { 69 67 70 namespace { 68 namespace { 71 // Number of instances with automatic seed s 69 // Number of instances with automatic seed selection 72 CLHEP_ATOMIC_INT_TYPE numberOfEngines(0); 70 CLHEP_ATOMIC_INT_TYPE numberOfEngines(0); 73 71 74 // Maximum index into the seed table 72 // Maximum index into the seed table 75 const int maxIndex = 215; 73 const int maxIndex = 215; 76 } 74 } 77 75 78 static const int MarkerLen = 64; // Enough roo 76 static const int MarkerLen = 64; // Enough room to hold a begin or end marker. 79 77 80 78 81 #ifndef WIN32 79 #ifndef WIN32 82 namespace detail { 80 namespace detail { 83 81 84 template< std::size_t n, 82 template< std::size_t n, 85 bool = n < std::size_t(std::numeric_ 83 bool = n < std::size_t(std::numeric_limits<unsigned long>::digits) > 86 struct do_right_shift; 84 struct do_right_shift; 87 template< std::size_t n > 85 template< std::size_t n > 88 struct do_right_shift<n,true> 86 struct do_right_shift<n,true> 89 { 87 { 90 unsigned long operator()(unsigned long value 88 unsigned long operator()(unsigned long value) { return value >> n; } 91 }; 89 }; 92 template< std::size_t n > 90 template< std::size_t n > 93 struct do_right_shift<n,false> 91 struct do_right_shift<n,false> 94 { 92 { 95 unsigned long operator()(unsigned long) { re 93 unsigned long operator()(unsigned long) { return 0ul; } 96 }; 94 }; 97 95 98 template< std::size_t nbits > 96 template< std::size_t nbits > 99 unsigned long rshift( unsigned long value ) 97 unsigned long rshift( unsigned long value ) 100 { return do_right_shift<nbits>()(value); } 98 { return do_right_shift<nbits>()(value); } 101 99 102 } // namespace detail 100 } // namespace detail 103 #endif 101 #endif 104 102 105 std::string Ranlux64Engine::name() const {retu 103 std::string Ranlux64Engine::name() const {return "Ranlux64Engine";} 106 104 107 Ranlux64Engine::Ranlux64Engine() 105 Ranlux64Engine::Ranlux64Engine() 108 : HepRandomEngine() 106 : HepRandomEngine() 109 { 107 { 110 luxury = 1; 108 luxury = 1; 111 int numEngines = numberOfEngines++; 109 int numEngines = numberOfEngines++; 112 int cycle = std::abs(int(numEngines/maxI 110 int cycle = std::abs(int(numEngines/maxIndex)); 113 int curIndex = std::abs(int(numEngines%maxI 111 int curIndex = std::abs(int(numEngines%maxIndex)); 114 112 115 long mask = ((cycle & 0x007fffff) << 8); 113 long mask = ((cycle & 0x007fffff) << 8); 116 long seedlist[2]; 114 long seedlist[2]; 117 HepRandom::getTheTableSeeds( seedlist, curI 115 HepRandom::getTheTableSeeds( seedlist, curIndex ); 118 seedlist[0] ^= mask; 116 seedlist[0] ^= mask; 119 seedlist[1] = 0; 117 seedlist[1] = 0; 120 118 121 setSeeds(seedlist, luxury); 119 setSeeds(seedlist, luxury); 122 advance ( 8 ); // Discard some iteratio 120 advance ( 8 ); // Discard some iterations and ensure that 123 // this sequence won't match one where 121 // this sequence won't match one where seeds 124 // were provided. 122 // were provided. 125 } 123 } 126 124 127 Ranlux64Engine::Ranlux64Engine(long seed, int 125 Ranlux64Engine::Ranlux64Engine(long seed, int lux) 128 : HepRandomEngine() 126 : HepRandomEngine() 129 { 127 { 130 luxury = lux; 128 luxury = lux; 131 long seedlist[2]={seed,0}; 129 long seedlist[2]={seed,0}; 132 setSeeds(seedlist, lux); 130 setSeeds(seedlist, lux); 133 advance ( 2*lux + 1 ); // Discard some it 131 advance ( 2*lux + 1 ); // Discard some iterations to use a different 134 // point in the sequence. 132 // point in the sequence. 135 } 133 } 136 134 137 Ranlux64Engine::Ranlux64Engine(int rowIndex, i 135 Ranlux64Engine::Ranlux64Engine(int rowIndex, int, int lux) 138 : HepRandomEngine() 136 : HepRandomEngine() 139 { 137 { 140 luxury = lux; 138 luxury = lux; 141 int cycle = std::abs(int(rowIndex/maxIndex) 139 int cycle = std::abs(int(rowIndex/maxIndex)); 142 int row = std::abs(int(rowIndex%maxIndex) 140 int row = std::abs(int(rowIndex%maxIndex)); 143 long mask = (( cycle & 0x000007ff ) << 20 ) 141 long mask = (( cycle & 0x000007ff ) << 20 ); 144 long seedlist[2]; 142 long seedlist[2]; 145 HepRandom::getTheTableSeeds( seedlist, row 143 HepRandom::getTheTableSeeds( seedlist, row ); 146 seedlist[0] ^= mask; 144 seedlist[0] ^= mask; 147 seedlist[1]= 0; 145 seedlist[1]= 0; 148 setSeeds(seedlist, lux); 146 setSeeds(seedlist, lux); 149 } 147 } 150 148 151 Ranlux64Engine::Ranlux64Engine( std::istream& 149 Ranlux64Engine::Ranlux64Engine( std::istream& is ) 152 : HepRandomEngine() 150 : HepRandomEngine() 153 { 151 { 154 is >> *this; 152 is >> *this; 155 } 153 } 156 154 157 Ranlux64Engine::~Ranlux64Engine() {} 155 Ranlux64Engine::~Ranlux64Engine() {} 158 156 159 double Ranlux64Engine::flat() { 157 double Ranlux64Engine::flat() { 160 // Luscher improves the speed by computing s 158 // Luscher improves the speed by computing several numbers in a shot, 161 // in a manner similar to that of the Tauswo 159 // in a manner similar to that of the Tausworth in DualRand or the Hurd 162 // engines. Thus, the real work is done in 160 // engines. Thus, the real work is done in update(). Here we merely ensure 163 // that zero, which the algorithm can produc 161 // that zero, which the algorithm can produce, is never returned by flat(). 164 162 165 if (index <= 0) update(); 163 if (index <= 0) update(); 166 return randoms[--index] + twoToMinus_49(); 164 return randoms[--index] + twoToMinus_49(); 167 } 165 } 168 166 169 void Ranlux64Engine::update() { 167 void Ranlux64Engine::update() { 170 // Update the stash of twelve random numbers 168 // Update the stash of twelve random numbers. 171 // When this routione is entered, index is a 169 // When this routione is entered, index is always 0. The randoms 172 // contains the last 12 numbers in the seque 170 // contains the last 12 numbers in the sequents: s[0] is x[a+11], 173 // s[1] is x[a+10] ... and s[11] is x[a] for 171 // s[1] is x[a+10] ... and s[11] is x[a] for some a. Carry contains 174 // the last carry value (c[a+11]). 172 // the last carry value (c[a+11]). 175 // 173 // 176 // The recursion relation (3) in Luscher's n 174 // The recursion relation (3) in Luscher's note says 177 // delta[n] = x[n-s] = x[n-r] -c[n-1] or f 175 // delta[n] = x[n-s] = x[n-r] -c[n-1] or for n=a+12, 178 // delta[a+12] = x[a+7] - x[a] -c[a+11] wh 176 // delta[a+12] = x[a+7] - x[a] -c[a+11] where we use r=12, s=5 per eqn. (7) 179 // This reduces to 177 // This reduces to 180 // s[11] = s[4] - s[11] - carry. 178 // s[11] = s[4] - s[11] - carry. 181 // The next number similarly will be given b 179 // The next number similarly will be given by s[10] = s[3] - s[10] - carry, 182 // and so forth until s[0] is filled. 180 // and so forth until s[0] is filled. 183 // 181 // 184 // However, we need to skip 397, 202 or 109 182 // However, we need to skip 397, 202 or 109 numbers - these are not divisible 185 // by 12 - to "fare well in the spectral tes 183 // by 12 - to "fare well in the spectral test". 186 184 187 advance(pDozens); 185 advance(pDozens); 188 186 189 // Since we wish at the end to have the 12 l 187 // Since we wish at the end to have the 12 last numbers in the order of 190 // s[11] first, till s[0] last, we will have 188 // s[11] first, till s[0] last, we will have to do 1, 10, or 1 iterations 191 // and then re-arrange to place to get the o 189 // and then re-arrange to place to get the oldest one in s[11]. 192 // Generically, this will imply re-arranging 190 // Generically, this will imply re-arranging the s array at the end, 193 // but we can treat the special case of endI 191 // but we can treat the special case of endIters = 1 separately for superior 194 // efficiency in the cases of levels 0 and 2 192 // efficiency in the cases of levels 0 and 2. 195 193 196 double y1; 194 double y1; 197 195 198 if ( endIters == 1 ) { // Luxury levels 0 196 if ( endIters == 1 ) { // Luxury levels 0 and 2 will go here 199 y1 = randoms[ 4] - randoms[11] - carry; 197 y1 = randoms[ 4] - randoms[11] - carry; 200 if ( y1 < 0.0 ) { 198 if ( y1 < 0.0 ) { 201 y1 += 1.0; 199 y1 += 1.0; 202 carry = twoToMinus_48(); 200 carry = twoToMinus_48(); 203 } else { 201 } else { 204 carry = 0.0; 202 carry = 0.0; 205 } 203 } 206 randoms[11] = randoms[10]; 204 randoms[11] = randoms[10]; 207 randoms[10] = randoms[ 9]; 205 randoms[10] = randoms[ 9]; 208 randoms[ 9] = randoms[ 8]; 206 randoms[ 9] = randoms[ 8]; 209 randoms[ 8] = randoms[ 7]; 207 randoms[ 8] = randoms[ 7]; 210 randoms[ 7] = randoms[ 6]; 208 randoms[ 7] = randoms[ 6]; 211 randoms[ 6] = randoms[ 5]; 209 randoms[ 6] = randoms[ 5]; 212 randoms[ 5] = randoms[ 4]; 210 randoms[ 5] = randoms[ 4]; 213 randoms[ 4] = randoms[ 3]; 211 randoms[ 4] = randoms[ 3]; 214 randoms[ 3] = randoms[ 2]; 212 randoms[ 3] = randoms[ 2]; 215 randoms[ 2] = randoms[ 1]; 213 randoms[ 2] = randoms[ 1]; 216 randoms[ 1] = randoms[ 0]; 214 randoms[ 1] = randoms[ 0]; 217 randoms[ 0] = y1; 215 randoms[ 0] = y1; 218 216 219 } else { 217 } else { 220 218 221 int m, nr, ns; 219 int m, nr, ns; 222 for ( m = 0, nr = 11, ns = 4; m < endIters 220 for ( m = 0, nr = 11, ns = 4; m < endIters; ++m, --nr ) { 223 y1 = randoms [ns] - randoms[nr] - carry; 221 y1 = randoms [ns] - randoms[nr] - carry; 224 if ( y1 < 0.0 ) { 222 if ( y1 < 0.0 ) { 225 y1 += 1.0; 223 y1 += 1.0; 226 carry = twoToMinus_48(); 224 carry = twoToMinus_48(); 227 } else { 225 } else { 228 carry = 0.0; 226 carry = 0.0; 229 } 227 } 230 randoms[nr] = y1; 228 randoms[nr] = y1; 231 --ns; 229 --ns; 232 if ( ns < 0 ) { 230 if ( ns < 0 ) { 233 ns = 11; 231 ns = 11; 234 } 232 } 235 } // loop on m 233 } // loop on m 236 234 237 double temp[12]; 235 double temp[12]; 238 for (m=0; m<12; m++) { 236 for (m=0; m<12; m++) { 239 temp[m]=randoms[m]; 237 temp[m]=randoms[m]; 240 } 238 } 241 239 242 ns = 11 - endIters; 240 ns = 11 - endIters; 243 for (m=11; m>=0; --m) { 241 for (m=11; m>=0; --m) { 244 randoms[m] = temp[ns]; 242 randoms[m] = temp[ns]; 245 --ns; 243 --ns; 246 if ( ns < 0 ) { 244 if ( ns < 0 ) { 247 ns = 11; 245 ns = 11; 248 } 246 } 249 } 247 } 250 248 251 } 249 } 252 250 253 // Now when we return, there are 12 fresh us 251 // Now when we return, there are 12 fresh usable numbers in s[11] ... s[0] 254 252 255 index = 12; << 253 index = 11; 256 254 257 } // update() 255 } // update() 258 256 259 void Ranlux64Engine::advance(int dozens) { 257 void Ranlux64Engine::advance(int dozens) { 260 258 261 double y1, y2, y3; 259 double y1, y2, y3; 262 double cValue = twoToMinus_48(); 260 double cValue = twoToMinus_48(); 263 double zero = 0.0; 261 double zero = 0.0; 264 double one = 1.0; 262 double one = 1.0; 265 263 266 // Technical note: We use Luscher's trick 264 // Technical note: We use Luscher's trick to only do the 267 // carry subtraction when we really have t 265 // carry subtraction when we really have to. Like him, we use 268 // three registers instead of two so that 266 // three registers instead of two so that we avoid sequences 269 // like storing y1 then immediately replac 267 // like storing y1 then immediately replacing its value: 270 // some architectures lose time when this 268 // some architectures lose time when this is done. 271 269 272 // Luscher's ranlxd.c fills the stash go 270 // Luscher's ranlxd.c fills the stash going 273 // upward. We fill it downward to save a 271 // upward. We fill it downward to save a bit of time in the 274 // flat() routine at no cost later. This 272 // flat() routine at no cost later. This means that while 275 // Luscher's ir is jr+5, our n-r is (n-s)- 273 // Luscher's ir is jr+5, our n-r is (n-s)-5. (Note that 276 // though ranlxd.c initializes ir and jr t 274 // though ranlxd.c initializes ir and jr to 11 and 7, ir as 277 // used is 5 more than jr because update i 275 // used is 5 more than jr because update is entered after 278 // incrementing ir.) 276 // incrementing ir.) 279 // 277 // 280 278 281 // I have CAREFULLY checked that the algor 279 // I have CAREFULLY checked that the algorithms do match 282 // in all details. 280 // in all details. 283 281 284 int k; 282 int k; 285 for ( k = dozens; k > 0; --k ) { 283 for ( k = dozens; k > 0; --k ) { 286 284 287 y1 = randoms[ 4] - randoms[11] - carry; 285 y1 = randoms[ 4] - randoms[11] - carry; 288 286 289 y2 = randoms[ 3] - randoms[10]; 287 y2 = randoms[ 3] - randoms[10]; 290 if ( y1 < zero ) { 288 if ( y1 < zero ) { 291 y1 += one; 289 y1 += one; 292 y2 -= cValue; 290 y2 -= cValue; 293 } 291 } 294 randoms[11] = y1; 292 randoms[11] = y1; 295 293 296 y3 = randoms[ 2] - randoms[ 9]; 294 y3 = randoms[ 2] - randoms[ 9]; 297 if ( y2 < zero ) { 295 if ( y2 < zero ) { 298 y2 += one; 296 y2 += one; 299 y3 -= cValue; 297 y3 -= cValue; 300 } 298 } 301 randoms[10] = y2; 299 randoms[10] = y2; 302 300 303 y1 = randoms[ 1] - randoms[ 8]; 301 y1 = randoms[ 1] - randoms[ 8]; 304 if ( y3 < zero ) { 302 if ( y3 < zero ) { 305 y3 += one; 303 y3 += one; 306 y1 -= cValue; 304 y1 -= cValue; 307 } 305 } 308 randoms[ 9] = y3; 306 randoms[ 9] = y3; 309 307 310 y2 = randoms[ 0] - randoms[ 7]; 308 y2 = randoms[ 0] - randoms[ 7]; 311 if ( y1 < zero ) { 309 if ( y1 < zero ) { 312 y1 += one; 310 y1 += one; 313 y2 -= cValue; 311 y2 -= cValue; 314 } 312 } 315 randoms[ 8] = y1; 313 randoms[ 8] = y1; 316 314 317 y3 = randoms[11] - randoms[ 6]; 315 y3 = randoms[11] - randoms[ 6]; 318 if ( y2 < zero ) { 316 if ( y2 < zero ) { 319 y2 += one; 317 y2 += one; 320 y3 -= cValue; 318 y3 -= cValue; 321 } 319 } 322 randoms[ 7] = y2; 320 randoms[ 7] = y2; 323 321 324 y1 = randoms[10] - randoms[ 5]; 322 y1 = randoms[10] - randoms[ 5]; 325 if ( y3 < zero ) { 323 if ( y3 < zero ) { 326 y3 += one; 324 y3 += one; 327 y1 -= cValue; 325 y1 -= cValue; 328 } 326 } 329 randoms[ 6] = y3; 327 randoms[ 6] = y3; 330 328 331 y2 = randoms[ 9] - randoms[ 4]; 329 y2 = randoms[ 9] - randoms[ 4]; 332 if ( y1 < zero ) { 330 if ( y1 < zero ) { 333 y1 += one; 331 y1 += one; 334 y2 -= cValue; 332 y2 -= cValue; 335 } 333 } 336 randoms[ 5] = y1; 334 randoms[ 5] = y1; 337 335 338 y3 = randoms[ 8] - randoms[ 3]; 336 y3 = randoms[ 8] - randoms[ 3]; 339 if ( y2 < zero ) { 337 if ( y2 < zero ) { 340 y2 += one; 338 y2 += one; 341 y3 -= cValue; 339 y3 -= cValue; 342 } 340 } 343 randoms[ 4] = y2; 341 randoms[ 4] = y2; 344 342 345 y1 = randoms[ 7] - randoms[ 2]; 343 y1 = randoms[ 7] - randoms[ 2]; 346 if ( y3 < zero ) { 344 if ( y3 < zero ) { 347 y3 += one; 345 y3 += one; 348 y1 -= cValue; 346 y1 -= cValue; 349 } 347 } 350 randoms[ 3] = y3; 348 randoms[ 3] = y3; 351 349 352 y2 = randoms[ 6] - randoms[ 1]; 350 y2 = randoms[ 6] - randoms[ 1]; 353 if ( y1 < zero ) { 351 if ( y1 < zero ) { 354 y1 += one; 352 y1 += one; 355 y2 -= cValue; 353 y2 -= cValue; 356 } 354 } 357 randoms[ 2] = y1; 355 randoms[ 2] = y1; 358 356 359 y3 = randoms[ 5] - randoms[ 0]; 357 y3 = randoms[ 5] - randoms[ 0]; 360 if ( y2 < zero ) { 358 if ( y2 < zero ) { 361 y2 += one; 359 y2 += one; 362 y3 -= cValue; 360 y3 -= cValue; 363 } 361 } 364 randoms[ 1] = y2; 362 randoms[ 1] = y2; 365 363 366 if ( y3 < zero ) { 364 if ( y3 < zero ) { 367 y3 += one; 365 y3 += one; 368 carry = cValue; 366 carry = cValue; 369 } 367 } 370 randoms[ 0] = y3; 368 randoms[ 0] = y3; 371 369 372 } // End of major k loop doing 12 numbers at 370 } // End of major k loop doing 12 numbers at each cycle 373 371 374 } // advance(dozens) 372 } // advance(dozens) 375 373 376 void Ranlux64Engine::flatArray(const int size, 374 void Ranlux64Engine::flatArray(const int size, double* vect) { 377 for( int i=0; i < size; ++i ) { 375 for( int i=0; i < size; ++i ) { 378 vect[i] = flat(); 376 vect[i] = flat(); 379 } 377 } 380 } 378 } 381 379 382 void Ranlux64Engine::setSeed(long seed, int lu 380 void Ranlux64Engine::setSeed(long seed, int lux) { 383 381 384 // The initialization is carried out using a M 382 // The initialization is carried out using a Multiplicative 385 // Congruential generator using formula consta 383 // Congruential generator using formula constants of L'Ecuyer 386 // as described in "A review of pseudorandom n 384 // as described in "A review of pseudorandom number generators" 387 // (Fred James) published in Computer Physics 385 // (Fred James) published in Computer Physics Communications 60 (1990) 388 // pages 329-344 386 // pages 329-344 389 387 390 const int ecuyer_a(53668); 388 const int ecuyer_a(53668); 391 const int ecuyer_b(40014); 389 const int ecuyer_b(40014); 392 const int ecuyer_c(12211); 390 const int ecuyer_c(12211); 393 const int ecuyer_d(2147483563); 391 const int ecuyer_d(2147483563); 394 392 395 const int lux_levels[3] = {109, 202, 397}; 393 const int lux_levels[3] = {109, 202, 397}; 396 theSeed = seed; 394 theSeed = seed; 397 395 398 if( (lux > 2)||(lux < 0) ){ 396 if( (lux > 2)||(lux < 0) ){ 399 pDiscard = (lux >= 12) ? (lux-12) : lux_l 397 pDiscard = (lux >= 12) ? (lux-12) : lux_levels[1]; 400 }else{ 398 }else{ 401 pDiscard = lux_levels[luxury]; 399 pDiscard = lux_levels[luxury]; 402 } 400 } 403 pDozens = pDiscard / 12; 401 pDozens = pDiscard / 12; 404 endIters = pDiscard % 12; 402 endIters = pDiscard % 12; 405 403 406 long init_table[24]; 404 long init_table[24]; 407 long next_seed = seed; 405 long next_seed = seed; 408 long k_multiple; 406 long k_multiple; 409 int i; 407 int i; 410 next_seed &= 0xffffffff; 408 next_seed &= 0xffffffff; 411 while( next_seed >= ecuyer_d ) { 409 while( next_seed >= ecuyer_d ) { 412 next_seed -= ecuyer_d; 410 next_seed -= ecuyer_d; 413 } 411 } 414 412 415 for(i = 0;i != 24;i++){ 413 for(i = 0;i != 24;i++){ 416 k_multiple = next_seed / ecuyer_a; 414 k_multiple = next_seed / ecuyer_a; 417 next_seed = ecuyer_b * (next_seed - k_mul 415 next_seed = ecuyer_b * (next_seed - k_multiple * ecuyer_a) 418 - k_mul 416 - k_multiple * ecuyer_c; 419 if(next_seed < 0) { 417 if(next_seed < 0) { 420 next_seed += ecuyer_d; 418 next_seed += ecuyer_d; 421 } 419 } 422 next_seed &= 0xffffffff; 420 next_seed &= 0xffffffff; 423 init_table[i] = next_seed; 421 init_table[i] = next_seed; 424 } 422 } 425 // are we on a 64bit machine? 423 // are we on a 64bit machine? 426 if( sizeof(long) >= 8 ) { 424 if( sizeof(long) >= 8 ) { 427 int64_t topbits1, topbits2; << 425 long topbits1, topbits2; 428 #ifdef WIN32 426 #ifdef WIN32 429 topbits1 = ( (int64_t) seed >> 32) & 0xff << 427 topbits1 = ( seed >> 32) & 0xffff ; 430 topbits2 = ( (int64_t) seed >> 48) & 0xff << 428 topbits2 = ( seed >> 48) & 0xffff ; 431 #else 429 #else 432 topbits1 = detail::rshift<32>(seed) & 0xf 430 topbits1 = detail::rshift<32>(seed) & 0xffff ; 433 topbits2 = detail::rshift<48>(seed) & 0xf 431 topbits2 = detail::rshift<48>(seed) & 0xffff ; 434 #endif 432 #endif 435 init_table[0] ^= topbits1; 433 init_table[0] ^= topbits1; 436 init_table[2] ^= topbits2; 434 init_table[2] ^= topbits2; 437 //std::cout << " init_table[0] " << init_ 435 //std::cout << " init_table[0] " << init_table[0] << " from " << topbits1 << std::endl; 438 //std::cout << " init_table[2] " << init_ 436 //std::cout << " init_table[2] " << init_table[2] << " from " << topbits2 << std::endl; 439 } 437 } 440 438 441 for(i = 0;i < 12; i++){ 439 for(i = 0;i < 12; i++){ 442 randoms[i] = (init_table[2*i ] ) * 440 randoms[i] = (init_table[2*i ] ) * 2.0 * twoToMinus_32() + 443 (init_table[2*i+1] >> 15) * 441 (init_table[2*i+1] >> 15) * twoToMinus_48(); 444 //if( randoms[i] < 0. || randoms[i] > 1. 442 //if( randoms[i] < 0. || randoms[i] > 1. ) { 445 //std::cout << "setSeed: init_table " << 443 //std::cout << "setSeed: init_table " << init_table[2*i ] << std::endl; 446 //std::cout << "setSeed: init_table " << 444 //std::cout << "setSeed: init_table " << init_table[2*i+1] << std::endl; 447 //std::cout << "setSeed: random " << i < 445 //std::cout << "setSeed: random " << i << " is " << randoms[i] << std::endl; 448 //} 446 //} 449 } 447 } 450 448 451 carry = 0.0; 449 carry = 0.0; 452 if ( randoms[11] == 0. ) carry = twoToMinus_ 450 if ( randoms[11] == 0. ) carry = twoToMinus_48(); 453 // Perform an update before returning the fi << 451 index = 11; 454 index = -1; << 455 452 456 } // setSeed() 453 } // setSeed() 457 454 458 void Ranlux64Engine::setSeeds(const long * see 455 void Ranlux64Engine::setSeeds(const long * seeds, int lux) { 459 // old code only uses the first long in seeds 456 // old code only uses the first long in seeds 460 // setSeed( *seeds ? *seeds : 32767, lux ); 457 // setSeed( *seeds ? *seeds : 32767, lux ); 461 // theSeeds = seeds; 458 // theSeeds = seeds; 462 459 463 // using code from Ranlux - even those are 32b 460 // using code from Ranlux - even those are 32bit seeds, 464 // that is good enough to completely different 461 // that is good enough to completely differentiate the sequences 465 462 466 const int ecuyer_a = 53668; 463 const int ecuyer_a = 53668; 467 const int ecuyer_b = 40014; 464 const int ecuyer_b = 40014; 468 const int ecuyer_c = 12211; 465 const int ecuyer_c = 12211; 469 const int ecuyer_d = 2147483563; 466 const int ecuyer_d = 2147483563; 470 467 471 const int lux_levels[3] = {109, 202, 397}; 468 const int lux_levels[3] = {109, 202, 397}; 472 const long *seedptr; 469 const long *seedptr; 473 470 474 theSeeds = seeds; 471 theSeeds = seeds; 475 seedptr = seeds; 472 seedptr = seeds; 476 473 477 if(seeds == 0){ 474 if(seeds == 0){ 478 setSeed(theSeed,lux); 475 setSeed(theSeed,lux); 479 theSeeds = &theSeed; 476 theSeeds = &theSeed; 480 return; 477 return; 481 } 478 } 482 479 483 theSeed = *seeds; 480 theSeed = *seeds; 484 481 485 // number of additional random numbers that ne 482 // number of additional random numbers that need to be 'thrown away' 486 // every 24 numbers is set using luxury level 483 // every 24 numbers is set using luxury level variable. 487 484 488 if( (lux > 2)||(lux < 0) ){ 485 if( (lux > 2)||(lux < 0) ){ 489 pDiscard = (lux >= 12) ? (lux-12) : lux_l 486 pDiscard = (lux >= 12) ? (lux-12) : lux_levels[1]; 490 }else{ 487 }else{ 491 pDiscard = lux_levels[luxury]; 488 pDiscard = lux_levels[luxury]; 492 } 489 } 493 pDozens = pDiscard / 12; 490 pDozens = pDiscard / 12; 494 endIters = pDiscard % 12; 491 endIters = pDiscard % 12; 495 492 496 long init_table[24]; 493 long init_table[24]; 497 long next_seed = *seeds; 494 long next_seed = *seeds; 498 long k_multiple; 495 long k_multiple; 499 int i; 496 int i; 500 497 501 for( i = 0;(i != 24)&&(*seedptr != 0);i++){ 498 for( i = 0;(i != 24)&&(*seedptr != 0);i++){ 502 init_table[i] = *seedptr & 0xffffffff; 499 init_table[i] = *seedptr & 0xffffffff; 503 seedptr++; 500 seedptr++; 504 } 501 } 505 502 506 if(i != 24){ 503 if(i != 24){ 507 next_seed = init_table[i-1]; 504 next_seed = init_table[i-1]; 508 for(;i != 24;i++){ 505 for(;i != 24;i++){ 509 k_multiple = next_seed / ecuyer_a; 506 k_multiple = next_seed / ecuyer_a; 510 next_seed = ecuyer_b * (next_seed - k_multip 507 next_seed = ecuyer_b * (next_seed - k_multiple * ecuyer_a) 511 - k_multip 508 - k_multiple * ecuyer_c; 512 if(next_seed < 0) { 509 if(next_seed < 0) { 513 next_seed += ecuyer_d; 510 next_seed += ecuyer_d; 514 } 511 } 515 next_seed &= 0xffffffff; 512 next_seed &= 0xffffffff; 516 init_table[i] = next_seed; 513 init_table[i] = next_seed; 517 } 514 } 518 } 515 } 519 516 520 for(i = 0;i < 12; i++){ 517 for(i = 0;i < 12; i++){ 521 randoms[i] = (init_table[2*i ] ) * 518 randoms[i] = (init_table[2*i ] ) * 2.0 * twoToMinus_32() + 522 (init_table[2*i+1] >> 15) * 519 (init_table[2*i+1] >> 15) * twoToMinus_48(); 523 } 520 } 524 521 525 carry = 0.0; 522 carry = 0.0; 526 if ( randoms[11] == 0. ) carry = twoToMinus_ 523 if ( randoms[11] == 0. ) carry = twoToMinus_48(); 527 // Perform an update before returning the fi << 524 index = 11; 528 index = -1; << 529 525 530 } 526 } 531 527 532 void Ranlux64Engine::saveStatus( const char fi 528 void Ranlux64Engine::saveStatus( const char filename[] ) const 533 { 529 { 534 std::ofstream outFile( filename, std::ios:: 530 std::ofstream outFile( filename, std::ios::out ) ; 535 if (!outFile.bad()) { 531 if (!outFile.bad()) { 536 outFile << "Uvec\n"; 532 outFile << "Uvec\n"; 537 std::vector<unsigned long> v = put(); 533 std::vector<unsigned long> v = put(); 538 for (unsigned int i=0; i<v.size(); ++i) { 534 for (unsigned int i=0; i<v.size(); ++i) { 539 outFile << v[i] << "\n"; 535 outFile << v[i] << "\n"; 540 } 536 } 541 } 537 } 542 } 538 } 543 539 544 void Ranlux64Engine::restoreStatus( const char 540 void Ranlux64Engine::restoreStatus( const char filename[] ) 545 { 541 { 546 std::ifstream inFile( filename, std::ios::i 542 std::ifstream inFile( filename, std::ios::in); 547 if (!checkFile ( inFile, filename, engineNa 543 if (!checkFile ( inFile, filename, engineName(), "restoreStatus" )) { 548 std::cerr << " -- Engine state remains u 544 std::cerr << " -- Engine state remains unchanged\n"; 549 return; 545 return; 550 } 546 } 551 if ( possibleKeywordInput ( inFile, "Uvec", 547 if ( possibleKeywordInput ( inFile, "Uvec", theSeed ) ) { 552 std::vector<unsigned long> v; 548 std::vector<unsigned long> v; 553 unsigned long xin; 549 unsigned long xin; 554 for (unsigned int ivec=0; ivec < VECTOR_ST 550 for (unsigned int ivec=0; ivec < VECTOR_STATE_SIZE; ++ivec) { 555 inFile >> xin; 551 inFile >> xin; 556 if (!inFile) { 552 if (!inFile) { 557 inFile.clear(std::ios::badbit | inFile 553 inFile.clear(std::ios::badbit | inFile.rdstate()); 558 std::cerr << "\nJamesRandom state (vec 554 std::cerr << "\nJamesRandom state (vector) description improper." 559 << "\nrestoreStatus has failed." 555 << "\nrestoreStatus has failed." 560 << "\nInput stream is probably mispos 556 << "\nInput stream is probably mispositioned now." << std::endl; 561 return; 557 return; 562 } 558 } 563 v.push_back(xin); 559 v.push_back(xin); 564 } 560 } 565 getState(v); 561 getState(v); 566 return; 562 return; 567 } 563 } 568 564 569 if (!inFile.bad() && !inFile.eof()) { 565 if (!inFile.bad() && !inFile.eof()) { 570 // inFile >> theSeed; removed -- encompas 566 // inFile >> theSeed; removed -- encompased by possibleKeywordInput 571 for (int i=0; i<12; ++i) { 567 for (int i=0; i<12; ++i) { 572 inFile >> randoms[i]; 568 inFile >> randoms[i]; 573 } 569 } 574 inFile >> carry; inFile >> index; 570 inFile >> carry; inFile >> index; 575 inFile >> luxury; inFile >> pDiscard; 571 inFile >> luxury; inFile >> pDiscard; 576 pDozens = pDiscard / 12; 572 pDozens = pDiscard / 12; 577 endIters = pDiscard % 12; 573 endIters = pDiscard % 12; 578 } 574 } 579 } 575 } 580 576 581 void Ranlux64Engine::showStatus() const 577 void Ranlux64Engine::showStatus() const 582 { 578 { 583 std::cout << std::endl; 579 std::cout << std::endl; 584 std::cout << "--------- Ranlux engine statu 580 std::cout << "--------- Ranlux engine status ---------" << std::endl; 585 std::cout << " Initial seed = " << theSeed 581 std::cout << " Initial seed = " << theSeed << std::endl; 586 std::cout << " randoms[] = "; 582 std::cout << " randoms[] = "; 587 for (int i=0; i<12; ++i) { 583 for (int i=0; i<12; ++i) { 588 std::cout << randoms[i] << std::endl; 584 std::cout << randoms[i] << std::endl; 589 } 585 } 590 std::cout << std::endl; 586 std::cout << std::endl; 591 std::cout << " carry = " << carry << ", ind 587 std::cout << " carry = " << carry << ", index = " << index << std::endl; 592 std::cout << " luxury = " << luxury << " pD 588 std::cout << " luxury = " << luxury << " pDiscard = " 593 << pDiscard << std::endl; 589 << pDiscard << std::endl; 594 std::cout << "----------------------------- 590 std::cout << "----------------------------------------" << std::endl; 595 } 591 } 596 592 597 std::ostream & Ranlux64Engine::put( std::ostre 593 std::ostream & Ranlux64Engine::put( std::ostream& os ) const 598 { 594 { 599 char beginMarker[] = "Ranlux64Engine-begin" 595 char beginMarker[] = "Ranlux64Engine-begin"; 600 os << beginMarker << "\nUvec\n"; 596 os << beginMarker << "\nUvec\n"; 601 std::vector<unsigned long> v = put(); 597 std::vector<unsigned long> v = put(); 602 for (unsigned int i=0; i<v.size(); ++i) { 598 for (unsigned int i=0; i<v.size(); ++i) { 603 os << v[i] << "\n"; 599 os << v[i] << "\n"; 604 } 600 } 605 return os; 601 return os; 606 } 602 } 607 603 608 std::vector<unsigned long> Ranlux64Engine::put 604 std::vector<unsigned long> Ranlux64Engine::put () const { 609 std::vector<unsigned long> v; 605 std::vector<unsigned long> v; 610 v.push_back (engineIDulong<Ranlux64Engine>() 606 v.push_back (engineIDulong<Ranlux64Engine>()); 611 std::vector<unsigned long> t; 607 std::vector<unsigned long> t; 612 for (int i=0; i<12; ++i) { 608 for (int i=0; i<12; ++i) { 613 t = DoubConv::dto2longs(randoms[i]); 609 t = DoubConv::dto2longs(randoms[i]); 614 v.push_back(t[0]); v.push_back(t[1]); 610 v.push_back(t[0]); v.push_back(t[1]); 615 } 611 } 616 t = DoubConv::dto2longs(carry); 612 t = DoubConv::dto2longs(carry); 617 v.push_back(t[0]); v.push_back(t[1]); 613 v.push_back(t[0]); v.push_back(t[1]); 618 v.push_back(static_cast<unsigned long>(index 614 v.push_back(static_cast<unsigned long>(index)); 619 v.push_back(static_cast<unsigned long>(luxur 615 v.push_back(static_cast<unsigned long>(luxury)); 620 v.push_back(static_cast<unsigned long>(pDisc 616 v.push_back(static_cast<unsigned long>(pDiscard)); 621 return v; 617 return v; 622 } 618 } 623 619 624 std::istream & Ranlux64Engine::get ( std::istr 620 std::istream & Ranlux64Engine::get ( std::istream& is ) 625 { 621 { 626 char beginMarker [MarkerLen]; 622 char beginMarker [MarkerLen]; 627 is >> std::ws; 623 is >> std::ws; 628 is.width(MarkerLen); // causes the next rea 624 is.width(MarkerLen); // causes the next read to the char* to be <= 629 // that many bytes, INCLUDING A TERMINAT 625 // that many bytes, INCLUDING A TERMINATION \0 630 // (Stroustrup, section 21.3.2) 626 // (Stroustrup, section 21.3.2) 631 is >> beginMarker; 627 is >> beginMarker; 632 if (strcmp(beginMarker,"Ranlux64Engine-begin 628 if (strcmp(beginMarker,"Ranlux64Engine-begin")) { 633 is.clear(std::ios::badbit | is.rdstate()) 629 is.clear(std::ios::badbit | is.rdstate()); 634 std::cerr << "\nInput stream mispositione 630 std::cerr << "\nInput stream mispositioned or" 635 << "\nRanlux64Engine state descriptio 631 << "\nRanlux64Engine state description missing or" 636 << "\nwrong engine type found." << st 632 << "\nwrong engine type found." << std::endl; 637 return is; 633 return is; 638 } 634 } 639 return getState(is); 635 return getState(is); 640 } 636 } 641 637 642 std::string Ranlux64Engine::beginTag ( ) { 638 std::string Ranlux64Engine::beginTag ( ) { 643 return "Ranlux64Engine-begin"; 639 return "Ranlux64Engine-begin"; 644 } 640 } 645 641 646 std::istream & Ranlux64Engine::getState ( std: 642 std::istream & Ranlux64Engine::getState ( std::istream& is ) 647 { 643 { 648 if ( possibleKeywordInput ( is, "Uvec", theS 644 if ( possibleKeywordInput ( is, "Uvec", theSeed ) ) { 649 std::vector<unsigned long> v; 645 std::vector<unsigned long> v; 650 unsigned long uu; 646 unsigned long uu; 651 for (unsigned int ivec=0; ivec < VECTOR_ST 647 for (unsigned int ivec=0; ivec < VECTOR_STATE_SIZE; ++ivec) { 652 is >> uu; 648 is >> uu; 653 if (!is) { 649 if (!is) { 654 is.clear(std::ios::badbit | is.rdstate 650 is.clear(std::ios::badbit | is.rdstate()); 655 std::cerr << "\nRanlux64Engine state ( 651 std::cerr << "\nRanlux64Engine state (vector) description improper." 656 << "\ngetState() has failed." 652 << "\ngetState() has failed." 657 << "\nInput stream is probably mispos 653 << "\nInput stream is probably mispositioned now." << std::endl; 658 return is; 654 return is; 659 } 655 } 660 v.push_back(uu); 656 v.push_back(uu); 661 } 657 } 662 getState(v); 658 getState(v); 663 return (is); 659 return (is); 664 } 660 } 665 661 666 // is >> theSeed; Removed, encompassed by po 662 // is >> theSeed; Removed, encompassed by possibleKeywordInput() 667 663 668 char endMarker [MarkerLen]; 664 char endMarker [MarkerLen]; 669 for (int i=0; i<12; ++i) { 665 for (int i=0; i<12; ++i) { 670 is >> randoms[i]; 666 is >> randoms[i]; 671 } 667 } 672 is >> carry; is >> index; 668 is >> carry; is >> index; 673 is >> luxury; is >> pDiscard; 669 is >> luxury; is >> pDiscard; 674 pDozens = pDiscard / 12; 670 pDozens = pDiscard / 12; 675 endIters = pDiscard % 12; 671 endIters = pDiscard % 12; 676 is >> std::ws; 672 is >> std::ws; 677 is.width(MarkerLen); 673 is.width(MarkerLen); 678 is >> endMarker; 674 is >> endMarker; 679 if (strcmp(endMarker,"Ranlux64Engine-end")) 675 if (strcmp(endMarker,"Ranlux64Engine-end")) { 680 is.clear(std::ios::badbit | is.rdstate()) 676 is.clear(std::ios::badbit | is.rdstate()); 681 std::cerr << "\nRanlux64Engine state desc 677 std::cerr << "\nRanlux64Engine state description incomplete." 682 << "\nInput stream is probably mispos 678 << "\nInput stream is probably mispositioned now." << std::endl; 683 return is; 679 return is; 684 } 680 } 685 return is; 681 return is; 686 } 682 } 687 683 688 bool Ranlux64Engine::get (const std::vector<un 684 bool Ranlux64Engine::get (const std::vector<unsigned long> & v) { 689 if ((v[0] & 0xffffffffUL) != engineIDulong<R 685 if ((v[0] & 0xffffffffUL) != engineIDulong<Ranlux64Engine>()) { 690 std::cerr << 686 std::cerr << 691 "\nRanlux64Engine get:state vector has w 687 "\nRanlux64Engine get:state vector has wrong ID word - state unchanged\n"; 692 return false; 688 return false; 693 } 689 } 694 return getState(v); 690 return getState(v); 695 } 691 } 696 692 697 bool Ranlux64Engine::getState (const std::vect 693 bool Ranlux64Engine::getState (const std::vector<unsigned long> & v) { 698 if (v.size() != VECTOR_STATE_SIZE ) { 694 if (v.size() != VECTOR_STATE_SIZE ) { 699 std::cerr << 695 std::cerr << 700 "\nRanlux64Engine get:state vector has w 696 "\nRanlux64Engine get:state vector has wrong length - state unchanged\n"; 701 return false; 697 return false; 702 } 698 } 703 std::vector<unsigned long> t(2); 699 std::vector<unsigned long> t(2); 704 for (int i=0; i<12; ++i) { 700 for (int i=0; i<12; ++i) { 705 t[0] = v[2*i+1]; t[1] = v[2*i+2]; 701 t[0] = v[2*i+1]; t[1] = v[2*i+2]; 706 randoms[i] = DoubConv::longs2double(t); 702 randoms[i] = DoubConv::longs2double(t); 707 } 703 } 708 t[0] = v[25]; t[1] = v[26]; 704 t[0] = v[25]; t[1] = v[26]; 709 carry = DoubConv::longs2double(t); 705 carry = DoubConv::longs2double(t); 710 index = (int)v[27]; << 706 index = v[27]; 711 luxury = (int)v[28]; << 707 luxury = v[28]; 712 pDiscard = (int)v[29]; << 708 pDiscard = v[29]; 713 return true; 709 return true; 714 } 710 } 715 711 716 } // namespace CLHEP 712 } // namespace CLHEP 717 713