56 #include "CLHEP/Random/Random.h"
57 #include "CLHEP/Random/Ranlux64Engine.h"
58 #include "CLHEP/Random/engineIDulong.h"
59 #include "CLHEP/Random/DoubConv.h"
70 int Ranlux64Engine::numEngines = 0;
73 int Ranlux64Engine::maxIndex = 215;
78 template< std::size_t
n,
79 bool = n < std::size_t(std::numeric_limits<unsigned long>::digits) >
80 struct do_right_shift;
81 template< std::
size_t n >
82 struct do_right_shift<n,true>
84 unsigned long operator()(
unsigned long value) {
return value >>
n; }
86 template< std::
size_t n >
87 struct do_right_shift<n,false>
92 template< std::
size_t nbits >
93 unsigned long rshift(
unsigned long value )
94 {
return do_right_shift<nbits>()(value); }
101 Ranlux64Engine::Ranlux64Engine()
105 int cycle = std::abs(
int(numEngines/maxIndex));
106 int curIndex = std::abs(
int(numEngines%maxIndex));
108 long mask = ((cycle & 0x007fffff) << 8);
110 HepRandom::getTheTableSeeds( seedlist, curIndex );
120 Ranlux64Engine::Ranlux64Engine(
long seed,
int lux)
124 long seedlist[2]={seed,0};
126 advance ( 2*lux + 1 );
130 Ranlux64Engine::Ranlux64Engine(
int rowIndex,
int,
int lux)
134 int cycle = std::abs(
int(rowIndex/maxIndex));
135 int row = std::abs(
int(rowIndex%maxIndex));
136 long mask = (( cycle & 0x000007ff ) << 20 );
138 HepRandom::getTheTableSeeds( seedlist, row );
144 Ranlux64Engine::Ranlux64Engine( std::istream& is )
150 Ranlux64Engine::~Ranlux64Engine() {}
158 if (index <= 0) update();
159 return randoms[--index] + twoToMinus_49();
162 void Ranlux64Engine::update() {
191 if ( endIters == 1 ) {
192 y1 = randoms[ 4] - randoms[11] - carry;
195 carry = twoToMinus_48();
199 randoms[11] = randoms[10];
200 randoms[10] = randoms[ 9];
201 randoms[ 9] = randoms[ 8];
202 randoms[ 8] = randoms[ 7];
203 randoms[ 7] = randoms[ 6];
204 randoms[ 6] = randoms[ 5];
205 randoms[ 5] = randoms[ 4];
206 randoms[ 4] = randoms[ 3];
207 randoms[ 3] = randoms[ 2];
208 randoms[ 2] = randoms[ 1];
209 randoms[ 1] = randoms[ 0];
215 for ( m = 0, nr = 11, ns = 4; m < endIters; ++
m, --nr ) {
216 y1 = randoms [
ns] - randoms[nr] - carry;
219 carry = twoToMinus_48();
231 for (m=0; m<12; m++) {
236 for (m=11; m>=0; --
m) {
237 randoms[
m] = temp[
ns];
252 void Ranlux64Engine::advance(
int dozens) {
254 register double y1, y2, y3;
255 register double cValue = twoToMinus_48();
256 register double zero = 0.0;
257 register double one = 1.0;
278 for ( k = dozens; k > 0; --k ) {
280 y1 = randoms[ 4] - randoms[11] - carry;
282 y2 = randoms[ 3] - randoms[10];
289 y3 = randoms[ 2] - randoms[ 9];
296 y1 = randoms[ 1] - randoms[ 8];
303 y2 = randoms[ 0] - randoms[ 7];
310 y3 = randoms[11] - randoms[ 6];
317 y1 = randoms[10] - randoms[ 5];
324 y2 = randoms[ 9] - randoms[ 4];
331 y3 = randoms[ 8] - randoms[ 3];
338 y1 = randoms[ 7] - randoms[ 2];
345 y2 = randoms[ 6] - randoms[ 1];
352 y3 = randoms[ 5] - randoms[ 0];
369 void Ranlux64Engine::flatArray(
const int size,
double* vect) {
370 for(
int i=0; i < size; ++i ) {
375 void Ranlux64Engine::setSeed(
long seed,
int lux) {
383 const int ecuyer_a(53668);
384 const int ecuyer_b(40014);
385 const int ecuyer_c(12211);
386 const int ecuyer_d(2147483563);
388 const int lux_levels[3] = {109, 202, 397};
391 if( (lux > 2)||(lux < 0) ){
392 pDiscard = (lux >= 12) ? (lux-12) : lux_levels[1];
394 pDiscard = lux_levels[luxury];
396 pDozens = pDiscard / 12;
397 endIters = pDiscard % 12;
400 long next_seed = seed;
403 next_seed &= 0xffffffff;
404 while( next_seed >= ecuyer_d ) {
405 next_seed -= ecuyer_d;
408 for(i = 0;i != 24;i++){
409 k_multiple = next_seed / ecuyer_a;
410 next_seed = ecuyer_b * (next_seed - k_multiple * ecuyer_a)
411 - k_multiple * ecuyer_c;
413 next_seed += ecuyer_d;
415 next_seed &= 0xffffffff;
416 init_table[i] = next_seed;
419 if(
sizeof(
long) >= 8 ) {
420 long topbits1, topbits2;
422 topbits1 = ( seed >> 32) & 0xffff ;
423 topbits2 = ( seed >> 48) & 0xffff ;
425 topbits1 = detail::rshift<32>(seed) & 0xffff ;
426 topbits2 = detail::rshift<48>(seed) & 0xffff ;
428 init_table[0] ^= topbits1;
429 init_table[2] ^= topbits2;
434 for(i = 0;i < 12; i++){
435 randoms[i] = (init_table[2*i ] ) * 2.0 * twoToMinus_32() +
436 (init_table[2*i+1] >> 15) * twoToMinus_48();
445 if ( randoms[11] == 0. ) carry = twoToMinus_48();
458 const int ecuyer_a = 53668;
459 const int ecuyer_b = 40014;
460 const int ecuyer_c = 12211;
461 const int ecuyer_d = 2147483563;
463 const int lux_levels[3] = {109, 202, 397};
470 setSeed(theSeed,lux);
480 if( (lux > 2)||(lux < 0) ){
481 pDiscard = (lux >= 12) ? (lux-12) : lux_levels[1];
483 pDiscard = lux_levels[luxury];
485 pDozens = pDiscard / 12;
486 endIters = pDiscard % 12;
489 long next_seed = *seeds;
493 for( i = 0;(i != 24)&&(*seedptr != 0);i++){
494 init_table[i] = *seedptr & 0xffffffff;
499 next_seed = init_table[i-1];
501 k_multiple = next_seed / ecuyer_a;
502 next_seed = ecuyer_b * (next_seed - k_multiple * ecuyer_a)
503 - k_multiple * ecuyer_c;
505 next_seed += ecuyer_d;
507 next_seed &= 0xffffffff;
508 init_table[i] = next_seed;
512 for(i = 0;i < 12; i++){
513 randoms[i] = (init_table[2*i ] ) * 2.0 * twoToMinus_32() +
514 (init_table[2*i+1] >> 15) * twoToMinus_48();
518 if ( randoms[11] == 0. ) carry = twoToMinus_48();
523 void Ranlux64Engine::saveStatus(
const char filename[] )
const
525 std::ofstream
outFile( filename, std::ios::out ) ;
528 std::vector<unsigned long> v = put();
529 for (
unsigned int i=0; i<v.size(); ++i) {
535 void Ranlux64Engine::restoreStatus(
const char filename[] )
537 std::ifstream inFile( filename, std::ios::in);
538 if (!checkFile ( inFile, filename, engineName(),
"restoreStatus" )) {
539 std::cerr <<
" -- Engine state remains unchanged\n";
542 if ( possibleKeywordInput ( inFile,
"Uvec", theSeed ) ) {
543 std::vector<unsigned long> v;
545 for (
unsigned int ivec=0; ivec < VECTOR_STATE_SIZE; ++ivec) {
548 inFile.clear(std::ios::badbit | inFile.rdstate());
549 std::cerr <<
"\nJamesRandom state (vector) description improper."
550 <<
"\nrestoreStatus has failed."
551 <<
"\nInput stream is probably mispositioned now." << std::endl;
560 if (!inFile.bad() && !inFile.eof()) {
562 for (
int i=0; i<12; ++i) {
563 inFile >> randoms[i];
565 inFile >> carry; inFile >> index;
566 inFile >> luxury; inFile >> pDiscard;
567 pDozens = pDiscard / 12;
568 endIters = pDiscard % 12;
572 void Ranlux64Engine::showStatus()
const
574 std::cout << std::endl;
575 std::cout <<
"--------- Ranlux engine status ---------" << std::endl;
576 std::cout <<
" Initial seed = " << theSeed << std::endl;
577 std::cout <<
" randoms[] = ";
578 for (
int i=0; i<12; ++i) {
579 std::cout << randoms[i] << std::endl;
581 std::cout << std::endl;
582 std::cout <<
" carry = " << carry <<
", index = " << index << std::endl;
583 std::cout <<
" luxury = " << luxury <<
" pDiscard = "
584 << pDiscard << std::endl;
585 std::cout <<
"----------------------------------------" << std::endl;
588 std::ostream & Ranlux64Engine::put( std::ostream& os )
const
590 char beginMarker[] =
"Ranlux64Engine-begin";
591 os << beginMarker <<
"\nUvec\n";
592 std::vector<unsigned long> v = put();
593 for (
unsigned int i=0; i<v.size(); ++i) {
599 std::vector<unsigned long> Ranlux64Engine::put ()
const {
600 std::vector<unsigned long> v;
601 v.push_back (engineIDulong<Ranlux64Engine>());
602 std::vector<unsigned long> t;
603 for (
int i=0; i<12; ++i) {
604 t = DoubConv::dto2longs(randoms[i]);
605 v.push_back(t[0]); v.push_back(t[1]);
607 t = DoubConv::dto2longs(carry);
608 v.push_back(t[0]); v.push_back(t[1]);
609 v.push_back(static_cast<unsigned long>(index));
610 v.push_back(static_cast<unsigned long>(luxury));
611 v.push_back(static_cast<unsigned long>(pDiscard));
615 std::istream & Ranlux64Engine::get ( std::istream& is )
623 if (strcmp(beginMarker,
"Ranlux64Engine-begin")) {
624 is.clear(std::ios::badbit | is.rdstate());
625 std::cerr <<
"\nInput stream mispositioned or"
626 <<
"\nRanlux64Engine state description missing or"
627 <<
"\nwrong engine type found." << std::endl;
633 std::string Ranlux64Engine::beginTag ( ) {
634 return "Ranlux64Engine-begin";
637 std::istream & Ranlux64Engine::getState ( std::istream& is )
639 if ( possibleKeywordInput ( is,
"Uvec", theSeed ) ) {
640 std::vector<unsigned long> v;
642 for (
unsigned int ivec=0; ivec < VECTOR_STATE_SIZE; ++ivec) {
645 is.clear(std::ios::badbit | is.rdstate());
646 std::cerr <<
"\nRanlux64Engine state (vector) description improper."
647 <<
"\ngetState() has failed."
648 <<
"\nInput stream is probably mispositioned now." << std::endl;
660 for (
int i=0; i<12; ++i) {
663 is >> carry; is >> index;
664 is >> luxury; is >> pDiscard;
665 pDozens = pDiscard / 12;
666 endIters = pDiscard % 12;
670 if (strcmp(endMarker,
"Ranlux64Engine-end")) {
671 is.clear(std::ios::badbit | is.rdstate());
672 std::cerr <<
"\nRanlux64Engine state description incomplete."
673 <<
"\nInput stream is probably mispositioned now." << std::endl;
679 bool Ranlux64Engine::get (
const std::vector<unsigned long> & v) {
680 if ((v[0] & 0xffffffffUL) != engineIDulong<Ranlux64Engine>()) {
682 "\nRanlux64Engine get:state vector has wrong ID word - state unchanged\n";
688 bool Ranlux64Engine::getState (
const std::vector<unsigned long> & v) {
689 if (v.size() != VECTOR_STATE_SIZE ) {
691 "\nRanlux64Engine get:state vector has wrong length - state unchanged\n";
694 std::vector<unsigned long> t(2);
695 for (
int i=0; i<12; ++i) {
696 t[0] = v[2*i+1]; t[1] = v[2*i+2];
697 randoms[i] = DoubConv::longs2double(t);
699 t[0] = v[25]; t[1] = v[26];
700 carry = DoubConv::longs2double(t);
unsigned long rshift(unsigned long value)
static const int MarkerLen
unsigned long operator()(unsigned long)
void setSeeds(const SeedVector &sv)
Set the seeds of the current generator.