40 #include "CLHEP/Random/Random.h"
41 #include "CLHEP/Random/RanluxEngine.h"
42 #include "CLHEP/Random/engineIDulong.h"
43 #include "CLHEP/Utility/atomic_int.h"
52 CLHEP_ATOMIC_INT_TYPE numberOfEngines(0);
55 const int maxIndex = 215;
62 RanluxEngine::RanluxEngine(
long seed,
int lux)
65 long seedlist[2]={0,0};
68 setSeed(seed, luxury);
76 RanluxEngine::RanluxEngine()
80 long seedlist[2]={0,0};
83 int numEngines = numberOfEngines++;
84 int cycle = std::abs(
int(numEngines/maxIndex));
85 int curIndex = std::abs(
int(numEngines%maxIndex));
87 long mask = ((cycle & 0x007fffff) << 8);
88 HepRandom::getTheTableSeeds( seedlist, curIndex );
89 seed = seedlist[0]^
mask;
90 setSeed(seed, luxury);
98 RanluxEngine::RanluxEngine(
int rowIndex,
int colIndex,
int lux)
102 long seedlist[2]={0,0};
105 int cycle = std::abs(
int(rowIndex/maxIndex));
106 int row = std::abs(
int(rowIndex%maxIndex));
107 int col = std::abs(
int(colIndex%2));
108 long mask = (( cycle & 0x000007ff ) << 20 );
109 HepRandom::getTheTableSeeds( seedlist, row );
110 seed = ( seedlist[col] )^mask;
111 setSeed(seed, luxury);
119 RanluxEngine::RanluxEngine( std::istream& is )
125 RanluxEngine::~RanluxEngine() {}
127 void RanluxEngine::setSeed(
long seed,
int lux) {
135 const int ecuyer_a = 53668;
136 const int ecuyer_b = 40014;
137 const int ecuyer_c = 12211;
138 const int ecuyer_d = 2147483563;
140 const int lux_levels[5] = {0,24,73,199,365};
142 long int_seed_table[24];
143 long next_seed =
seed;
151 if( (lux > 4)||(lux < 0) ){
155 nskip = lux_levels[3];
159 nskip = lux_levels[luxury];
163 for(i = 0;i != 24;i++){
164 k_multiple = next_seed / ecuyer_a;
165 next_seed = ecuyer_b * (next_seed - k_multiple * ecuyer_a)
166 - k_multiple * ecuyer_c ;
167 if(next_seed < 0)next_seed += ecuyer_d;
168 int_seed_table[i] = next_seed % int_modulus;
171 for(i = 0;i != 24;i++)
172 float_seed_table[i] = int_seed_table[i] * mantissa_bit_24();
178 if( float_seed_table[23] == 0. ) carry = mantissa_bit_24();
185 const int ecuyer_a = 53668;
186 const int ecuyer_b = 40014;
187 const int ecuyer_c = 12211;
188 const int ecuyer_d = 2147483563;
190 const int lux_levels[5] = {0,24,73,199,365};
192 long int_seed_table[24];
193 long k_multiple,next_seed;
200 setSeed(theSeed,lux);
210 if( (lux > 4)||(lux < 0) ){
214 nskip = lux_levels[3];
218 nskip = lux_levels[luxury];
221 for( i = 0;(i != 24)&&(*seedptr != 0);i++){
222 int_seed_table[i] = *seedptr % int_modulus;
227 next_seed = int_seed_table[i-1];
229 k_multiple = next_seed / ecuyer_a;
230 next_seed = ecuyer_b * (next_seed - k_multiple * ecuyer_a)
231 - k_multiple * ecuyer_c ;
232 if(next_seed < 0)next_seed += ecuyer_d;
233 int_seed_table[i] = next_seed % int_modulus;
237 for(i = 0;i != 24;i++)
238 float_seed_table[i] = int_seed_table[i] * mantissa_bit_24();
244 if( float_seed_table[23] == 0. ) carry = mantissa_bit_24();
249 void RanluxEngine::saveStatus(
const char filename[] )
const
251 std::ofstream outFile( filename, std::ios::out ) ;
252 if (!outFile.bad()) {
254 std::vector<unsigned long> v = put();
255 for (
unsigned int i=0; i<v.size(); ++i) {
256 outFile << v[i] <<
"\n";
261 void RanluxEngine::restoreStatus(
const char filename[] )
263 std::ifstream inFile( filename, std::ios::in);
264 if (!checkFile ( inFile, filename, engineName(),
"restoreStatus" )) {
265 std::cerr <<
" -- Engine state remains unchanged\n";
268 if ( possibleKeywordInput ( inFile,
"Uvec", theSeed ) ) {
269 std::vector<unsigned long> v;
271 for (
unsigned int ivec=0; ivec < VECTOR_STATE_SIZE; ++ivec) {
274 inFile.clear(std::ios::badbit | inFile.rdstate());
275 std::cerr <<
"\nRanluxEngine state (vector) description improper."
276 <<
"\nrestoreStatus has failed."
277 <<
"\nInput stream is probably mispositioned now." << std::endl;
286 if (!inFile.bad() && !inFile.eof()) {
288 for (
int i=0; i<24; ++i)
289 inFile >> float_seed_table[i];
290 inFile >> i_lag; inFile >> j_lag;
291 inFile >> carry; inFile >> count24;
292 inFile >> luxury; inFile >> nskip;
296 void RanluxEngine::showStatus()
const
298 std::cout << std::endl;
299 std::cout <<
"--------- Ranlux engine status ---------" << std::endl;
300 std::cout <<
" Initial seed = " << theSeed << std::endl;
301 std::cout <<
" float_seed_table[] = ";
302 for (
int i=0; i<24; ++i)
303 std::cout << float_seed_table[i] <<
" ";
304 std::cout << std::endl;
305 std::cout <<
" i_lag = " << i_lag <<
", j_lag = " << j_lag << std::endl;
306 std::cout <<
" carry = " << carry <<
", count24 = " << count24 << std::endl;
307 std::cout <<
" luxury = " << luxury <<
" nskip = " << nskip << std::endl;
308 std::cout <<
"----------------------------------------" << std::endl;
317 uni = float_seed_table[j_lag] - float_seed_table[i_lag] - carry;
320 carry = mantissa_bit_24();
325 float_seed_table[i_lag] = uni;
328 if(i_lag < 0) i_lag = 23;
329 if(j_lag < 0) j_lag = 23;
331 if( uni < mantissa_bit_12() ){
332 uni += mantissa_bit_24() * float_seed_table[j_lag];
333 if( uni == 0) uni = mantissa_bit_24() * mantissa_bit_24();
343 for( i = 0; i != nskip ; i++){
344 uni = float_seed_table[j_lag] - float_seed_table[i_lag] - carry;
347 carry = mantissa_bit_24();
351 float_seed_table[i_lag] = uni;
354 if(i_lag < 0)i_lag = 23;
355 if(j_lag < 0) j_lag = 23;
358 return (
double) next_random;
361 void RanluxEngine::flatArray(
const int size,
double* vect)
368 for (index=0; index<size; ++index) {
369 uni = float_seed_table[j_lag] - float_seed_table[i_lag] - carry;
372 carry = mantissa_bit_24();
377 float_seed_table[i_lag] = uni;
380 if(i_lag < 0) i_lag = 23;
381 if(j_lag < 0) j_lag = 23;
383 if( uni < mantissa_bit_12() ){
384 uni += mantissa_bit_24() * float_seed_table[j_lag];
385 if( uni == 0) uni = mantissa_bit_24() * mantissa_bit_24();
388 vect[index] = (double)next_random;
396 for( i = 0; i != nskip ; i++){
397 uni = float_seed_table[j_lag] - float_seed_table[i_lag] - carry;
400 carry = mantissa_bit_24();
404 float_seed_table[i_lag] = uni;
407 if(i_lag < 0)i_lag = 23;
408 if(j_lag < 0) j_lag = 23;
414 RanluxEngine::operator
unsigned int() {
415 return ((
unsigned int)(
flat() * exponent_bit_32()) & 0xffffffff) |
416 (((
unsigned int)(float_seed_table[i_lag]*exponent_bit_32())>>16) & 0xff);
421 std::ostream & RanluxEngine::put ( std::ostream& os )
const
423 char beginMarker[] =
"RanluxEngine-begin";
424 os << beginMarker <<
"\nUvec\n";
425 std::vector<unsigned long> v = put();
426 for (
unsigned int i=0; i<v.size(); ++i) {
432 std::vector<unsigned long> RanluxEngine::put ()
const {
433 std::vector<unsigned long> v;
434 v.push_back (engineIDulong<RanluxEngine>());
435 for (
int i=0; i<24; ++i) {
437 (static_cast<unsigned long>(float_seed_table[i]/mantissa_bit_24()));
439 v.push_back(static_cast<unsigned long>(i_lag));
440 v.push_back(static_cast<unsigned long>(j_lag));
441 v.push_back(static_cast<unsigned long>(carry/mantissa_bit_24()));
442 v.push_back(static_cast<unsigned long>(count24));
443 v.push_back(static_cast<unsigned long>(luxury));
444 v.push_back(static_cast<unsigned long>(nskip));
448 std::istream & RanluxEngine::get ( std::istream& is )
456 if (strcmp(beginMarker,
"RanluxEngine-begin")) {
457 is.clear(std::ios::badbit | is.rdstate());
458 std::cerr <<
"\nInput stream mispositioned or"
459 <<
"\nRanluxEngine state description missing or"
460 <<
"\nwrong engine type found." << std::endl;
466 std::string RanluxEngine::beginTag ( ) {
467 return "RanluxEngine-begin";
470 std::istream & RanluxEngine::getState ( std::istream& is )
472 if ( possibleKeywordInput ( is,
"Uvec", theSeed ) ) {
473 std::vector<unsigned long> v;
475 for (
unsigned int ivec=0; ivec < VECTOR_STATE_SIZE; ++ivec) {
478 is.clear(std::ios::badbit | is.rdstate());
479 std::cerr <<
"\nRanluxEngine state (vector) description improper."
480 <<
"\ngetState() has failed."
481 <<
"\nInput stream is probably mispositioned now." << std::endl;
493 for (
int i=0; i<24; ++i) {
494 is >> float_seed_table[i];
496 is >> i_lag; is >> j_lag;
497 is >> carry; is >> count24;
498 is >> luxury; is >> nskip;
502 if (strcmp(endMarker,
"RanluxEngine-end")) {
503 is.clear(std::ios::badbit | is.rdstate());
504 std::cerr <<
"\nRanluxEngine state description incomplete."
505 <<
"\nInput stream is probably mispositioned now." << std::endl;
511 bool RanluxEngine::get (
const std::vector<unsigned long> & v) {
512 if ((v[0] & 0xffffffffUL) != engineIDulong<RanluxEngine>()) {
514 "\nRanluxEngine get:state vector has wrong ID word - state unchanged\n";
520 bool RanluxEngine::getState (
const std::vector<unsigned long> & v) {
521 if (v.size() != VECTOR_STATE_SIZE ) {
523 "\nRanluxEngine get:state vector has wrong length - state unchanged\n";
526 for (
int i=0; i<24; ++i) {
527 float_seed_table[i] = v[i+1]*mantissa_bit_24();
531 carry = v[27]*mantissa_bit_24();
static const int MarkerLen
static constexpr double lux
const char * name(G4int ptype)
void setSeeds(const SeedVector &sv)
Set the seeds of the current generator.