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