Geant4-11
Ranlux64Engine.cc
Go to the documentation of this file.
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"
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
68namespace CLHEP {
69
70namespace {
71 // Number of instances with automatic seed selection
73
74 // Maximum index into the seed table
75 const int maxIndex = 215;
76}
77
78static const int MarkerLen = 64; // Enough room to hold a begin or end marker.
79
80
81#ifndef WIN32
82namespace detail {
83
84template< std::size_t n,
85 bool = n < std::size_t(std::numeric_limits<unsigned long>::digits) >
86 struct do_right_shift;
87template< std::size_t n >
88 struct do_right_shift<n,true>
89{
90 unsigned long operator()(unsigned long value) { return value >> n; }
91};
92template< std::size_t n >
93 struct do_right_shift<n,false>
94{
95 unsigned long operator()(unsigned long) { return 0ul; }
96};
97
98template< 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
105std::string Ranlux64Engine::name() const {return "Ranlux64Engine";}
106
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
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
137Ranlux64Engine::Ranlux64Engine(int rowIndex, int, int lux)
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
153{
154 is >> *this;
155}
156
158
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
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
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;
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;
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
259void 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
376void Ranlux64Engine::flatArray(const int size, double* vect) {
377 for( int i=0; i < size; ++i ) {
378 vect[i] = flat();
379 }
380}
381
382void 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
458void 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){
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
532void 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
544void 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
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
597std::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
608std::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) {
614 v.push_back(t[0]); v.push_back(t[1]);
615 }
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
624std::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
642std::string Ranlux64Engine::beginTag ( ) {
643 return "Ranlux64Engine-begin";
644}
645
646std::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
688bool 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
697bool 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];
707 }
708 t[0] = v[25]; t[1] = v[26];
710 index = v[27];
711 luxury = v[28];
712 pDiscard = v[29];
713 return true;
714}
715
716} // namespace CLHEP
#define CLHEP_ATOMIC_INT_TYPE
Definition: atomic_int.h:14
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:47
static void getTheTableSeeds(long *seeds, int index)
Definition: Random.cc:254
std::string name() const
void setSeed(long seed, int lxr=1)
void restoreStatus(const char filename[]="Ranlux64.conf")
void advance(int dozens)
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)
Definition: DoubConv.h:17
bool possibleKeywordInput(IS &is, const std::string &key, T &t)
Definition: RandomEngine.h:166
static const int MarkerLen
Definition: DualRand.cc:70
static constexpr double ns
static constexpr double lux
static constexpr double m
static const G4LorentzVector zero(0., 0., 0., 0.)
unsigned long operator()(unsigned long)