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