CLHEP VERSION Reference Documentation
CLHEP Home Page CLHEP Documentation CLHEP Bug Reports |
00001 // $Id: RanluxEngine.cc,v 1.6 2010/06/16 17:24:53 garren Exp $ 00002 // -*- C++ -*- 00003 // 00004 // ----------------------------------------------------------------------- 00005 // HEP Random 00006 // --- RanluxEngine --- 00007 // class implementation file 00008 // ----------------------------------------------------------------------- 00009 // This file is part of Geant4 (simulation toolkit for HEP). 00010 // 00011 // Ranlux random number generator originally implemented in FORTRAN77 00012 // by Fred James as part of the MATHLIB HEP library. 00013 // 'RanluxEngine' is designed to fit into the CLHEP random number 00014 // class structure. 00015 00016 // =============================================================== 00017 // Adeyemi Adesanya - Created: 6th November 1995 00018 // Gabriele Cosmo - Adapted & Revised: 22nd November 1995 00019 // Adeyemi Adesanya - Added setSeeds() method: 2nd February 1996 00020 // Gabriele Cosmo - Added flatArray() method: 8th February 1996 00021 // - Minor corrections: 31st October 1996 00022 // - Added methods for engine status: 19th November 1996 00023 // - Fixed bug in setSeeds(): 15th September 1997 00024 // J.Marraffino - Added stream operators and related constructor. 00025 // Added automatic seed selection from seed table and 00026 // engine counter: 14th Feb 1998 00027 // - Fixed bug: setSeeds() requires a zero terminated 00028 // array of seeds: 19th Feb 1998 00029 // Ken Smith - Added conversion operators: 6th Aug 1998 00030 // J. Marraffino - Remove dependence on hepString class 13 May 1999 00031 // M. Fischler - In restore, checkFile for file not found 03 Dec 2004 00032 // M. Fischler - Methods put, getfor instance save/restore 12/8/04 00033 // M. Fischler - split get() into tag validation and 00034 // getState() for anonymous restores 12/27/04 00035 // M. Fischler - put/get for vectors of ulongs 3/14/05 00036 // M. Fischler - State-saving using only ints, for portability 4/12/05 00037 // 00038 // =============================================================== 00039 00040 #include "CLHEP/Random/defs.h" 00041 #include "CLHEP/Random/Random.h" 00042 #include "CLHEP/Random/RanluxEngine.h" 00043 #include "CLHEP/Random/engineIDulong.h" 00044 #include "CLHEP/Utility/atomic_int.h" 00045 00046 #include <string.h> // for strcmp 00047 #include <cstdlib> // for std::abs(int) 00048 00049 #ifdef TRACE_IO 00050 #include "CLHEP/Random/DoubConv.hh" 00051 bool flat_trace = false; 00052 #endif 00053 00054 namespace CLHEP { 00055 00056 namespace { 00057 // Number of instances with automatic seed selection 00058 CLHEP_ATOMIC_INT_TYPE numberOfEngines(0); 00059 00060 // Maximum index into the seed table 00061 const int maxIndex = 215; 00062 } 00063 00064 static const int MarkerLen = 64; // Enough room to hold a begin or end marker. 00065 00066 std::string RanluxEngine::name() const {return "RanluxEngine";} 00067 00068 RanluxEngine::RanluxEngine(long seed, int lux) 00069 : HepRandomEngine() 00070 { 00071 long seedlist[2]={0,0}; 00072 00073 luxury = lux; 00074 setSeed(seed, luxury); 00075 00076 // setSeeds() wants a zero terminated array! 00077 seedlist[0]=theSeed; 00078 seedlist[1]=0; 00079 setSeeds(seedlist, luxury); 00080 } 00081 00082 RanluxEngine::RanluxEngine() 00083 : HepRandomEngine() 00084 { 00085 long seed; 00086 long seedlist[2]={0,0}; 00087 00088 luxury = 3; 00089 int numEngines = numberOfEngines++; 00090 int cycle = std::abs(int(numEngines/maxIndex)); 00091 int curIndex = std::abs(int(numEngines%maxIndex)); 00092 00093 long mask = ((cycle & 0x007fffff) << 8); 00094 HepRandom::getTheTableSeeds( seedlist, curIndex ); 00095 seed = seedlist[0]^mask; 00096 setSeed(seed, luxury); 00097 00098 // setSeeds() wants a zero terminated array! 00099 seedlist[0]=theSeed; 00100 seedlist[1]=0; 00101 setSeeds(seedlist, luxury); 00102 } 00103 00104 RanluxEngine::RanluxEngine(int rowIndex, int colIndex, int lux) 00105 : HepRandomEngine() 00106 { 00107 long seed; 00108 long seedlist[2]={0,0}; 00109 00110 luxury = lux; 00111 int cycle = std::abs(int(rowIndex/maxIndex)); 00112 int row = std::abs(int(rowIndex%maxIndex)); 00113 int col = std::abs(int(colIndex%2)); 00114 long mask = (( cycle & 0x000007ff ) << 20 ); 00115 HepRandom::getTheTableSeeds( seedlist, row ); 00116 seed = ( seedlist[col] )^mask; 00117 setSeed(seed, luxury); 00118 00119 // setSeeds() wants a zero terminated array! 00120 seedlist[0]=theSeed; 00121 seedlist[1]=0; 00122 setSeeds(seedlist, luxury); 00123 } 00124 00125 RanluxEngine::RanluxEngine( std::istream& is ) 00126 : HepRandomEngine() 00127 { 00128 is >> *this; 00129 } 00130 00131 RanluxEngine::~RanluxEngine() {} 00132 00133 void RanluxEngine::setSeed(long seed, int lux) { 00134 00135 // The initialisation is carried out using a Multiplicative 00136 // Congruential generator using formula constants of L'Ecuyer 00137 // as described in "A review of pseudorandom number generators" 00138 // (Fred James) published in Computer Physics Communications 60 (1990) 00139 // pages 329-344 00140 00141 const int ecuyer_a = 53668; 00142 const int ecuyer_b = 40014; 00143 const int ecuyer_c = 12211; 00144 const int ecuyer_d = 2147483563; 00145 00146 const int lux_levels[5] = {0,24,73,199,365}; 00147 00148 long int_seed_table[24]; 00149 long next_seed = seed; 00150 long k_multiple; 00151 int i; 00152 00153 // number of additional random numbers that need to be 'thrown away' 00154 // every 24 numbers is set using luxury level variable. 00155 00156 theSeed = seed; 00157 if( (lux > 4)||(lux < 0) ){ 00158 if(lux >= 24){ 00159 nskip = lux - 24; 00160 }else{ 00161 nskip = lux_levels[3]; // corresponds to default luxury level 00162 } 00163 }else{ 00164 luxury = lux; 00165 nskip = lux_levels[luxury]; 00166 } 00167 00168 00169 for(i = 0;i != 24;i++){ 00170 k_multiple = next_seed / ecuyer_a; 00171 next_seed = ecuyer_b * (next_seed - k_multiple * ecuyer_a) 00172 - k_multiple * ecuyer_c ; 00173 if(next_seed < 0)next_seed += ecuyer_d; 00174 int_seed_table[i] = next_seed % int_modulus; 00175 } 00176 00177 for(i = 0;i != 24;i++) 00178 float_seed_table[i] = int_seed_table[i] * mantissa_bit_24(); 00179 00180 i_lag = 23; 00181 j_lag = 9; 00182 carry = 0. ; 00183 00184 if( float_seed_table[23] == 0. ) carry = mantissa_bit_24(); 00185 00186 count24 = 0; 00187 } 00188 00189 void RanluxEngine::setSeeds(const long *seeds, int lux) { 00190 00191 const int ecuyer_a = 53668; 00192 const int ecuyer_b = 40014; 00193 const int ecuyer_c = 12211; 00194 const int ecuyer_d = 2147483563; 00195 00196 const int lux_levels[5] = {0,24,73,199,365}; 00197 int i; 00198 long int_seed_table[24]; 00199 long k_multiple,next_seed; 00200 const long *seedptr; 00201 00202 theSeeds = seeds; 00203 seedptr = seeds; 00204 00205 if(seeds == 0){ 00206 setSeed(theSeed,lux); 00207 theSeeds = &theSeed; 00208 return; 00209 } 00210 00211 theSeed = *seeds; 00212 00213 // number of additional random numbers that need to be 'thrown away' 00214 // every 24 numbers is set using luxury level variable. 00215 00216 if( (lux > 4)||(lux < 0) ){ 00217 if(lux >= 24){ 00218 nskip = lux - 24; 00219 }else{ 00220 nskip = lux_levels[3]; // corresponds to default luxury level 00221 } 00222 }else{ 00223 luxury = lux; 00224 nskip = lux_levels[luxury]; 00225 } 00226 00227 for( i = 0;(i != 24)&&(*seedptr != 0);i++){ 00228 int_seed_table[i] = *seedptr % int_modulus; 00229 seedptr++; 00230 } 00231 00232 if(i != 24){ 00233 next_seed = int_seed_table[i-1]; 00234 for(;i != 24;i++){ 00235 k_multiple = next_seed / ecuyer_a; 00236 next_seed = ecuyer_b * (next_seed - k_multiple * ecuyer_a) 00237 - k_multiple * ecuyer_c ; 00238 if(next_seed < 0)next_seed += ecuyer_d; 00239 int_seed_table[i] = next_seed % int_modulus; 00240 } 00241 } 00242 00243 for(i = 0;i != 24;i++) 00244 float_seed_table[i] = int_seed_table[i] * mantissa_bit_24(); 00245 00246 i_lag = 23; 00247 j_lag = 9; 00248 carry = 0. ; 00249 00250 if( float_seed_table[23] == 0. ) carry = mantissa_bit_24(); 00251 00252 count24 = 0; 00253 } 00254 00255 void RanluxEngine::saveStatus( const char filename[] ) const 00256 { 00257 std::ofstream outFile( filename, std::ios::out ) ; 00258 if (!outFile.bad()) { 00259 outFile << "Uvec\n"; 00260 std::vector<unsigned long> v = put(); 00261 #ifdef TRACE_IO 00262 std::cout << "Result of v = put() is:\n"; 00263 #endif 00264 for (unsigned int i=0; i<v.size(); ++i) { 00265 outFile << v[i] << "\n"; 00266 #ifdef TRACE_IO 00267 std::cout << v[i] << " "; 00268 if (i%6==0) std::cout << "\n"; 00269 #endif 00270 } 00271 #ifdef TRACE_IO 00272 std::cout << "\n"; 00273 #endif 00274 } 00275 #ifdef REMOVED 00276 if (!outFile.bad()) { 00277 outFile << theSeed << std::endl; 00278 for (int i=0; i<24; ++i) 00279 outFile <<std::setprecision(20) << float_seed_table[i] << " "; 00280 outFile << std::endl; 00281 outFile << i_lag << " " << j_lag << std::endl; 00282 outFile << std::setprecision(20) << carry << " " << count24 << std::endl; 00283 outFile << luxury << " " << nskip << std::endl; 00284 } 00285 #endif 00286 } 00287 00288 void RanluxEngine::restoreStatus( const char filename[] ) 00289 { 00290 std::ifstream inFile( filename, std::ios::in); 00291 if (!checkFile ( inFile, filename, engineName(), "restoreStatus" )) { 00292 std::cerr << " -- Engine state remains unchanged\n"; 00293 return; 00294 } 00295 if ( possibleKeywordInput ( inFile, "Uvec", theSeed ) ) { 00296 std::vector<unsigned long> v; 00297 unsigned long xin; 00298 for (unsigned int ivec=0; ivec < VECTOR_STATE_SIZE; ++ivec) { 00299 inFile >> xin; 00300 #ifdef TRACE_IO 00301 std::cout << "ivec = " << ivec << " xin = " << xin << " "; 00302 if (ivec%3 == 0) std::cout << "\n"; 00303 #endif 00304 if (!inFile) { 00305 inFile.clear(std::ios::badbit | inFile.rdstate()); 00306 std::cerr << "\nRanluxEngine state (vector) description improper." 00307 << "\nrestoreStatus has failed." 00308 << "\nInput stream is probably mispositioned now." << std::endl; 00309 return; 00310 } 00311 v.push_back(xin); 00312 } 00313 getState(v); 00314 return; 00315 } 00316 00317 if (!inFile.bad() && !inFile.eof()) { 00318 // inFile >> theSeed; removed -- encompased by possibleKeywordInput 00319 for (int i=0; i<24; ++i) 00320 inFile >> float_seed_table[i]; 00321 inFile >> i_lag; inFile >> j_lag; 00322 inFile >> carry; inFile >> count24; 00323 inFile >> luxury; inFile >> nskip; 00324 } 00325 } 00326 00327 void RanluxEngine::showStatus() const 00328 { 00329 std::cout << std::endl; 00330 std::cout << "--------- Ranlux engine status ---------" << std::endl; 00331 std::cout << " Initial seed = " << theSeed << std::endl; 00332 std::cout << " float_seed_table[] = "; 00333 for (int i=0; i<24; ++i) 00334 std::cout << float_seed_table[i] << " "; 00335 std::cout << std::endl; 00336 std::cout << " i_lag = " << i_lag << ", j_lag = " << j_lag << std::endl; 00337 std::cout << " carry = " << carry << ", count24 = " << count24 << std::endl; 00338 std::cout << " luxury = " << luxury << " nskip = " << nskip << std::endl; 00339 std::cout << "----------------------------------------" << std::endl; 00340 } 00341 00342 double RanluxEngine::flat() { 00343 00344 float next_random; 00345 float uni; 00346 int i; 00347 00348 uni = float_seed_table[j_lag] - float_seed_table[i_lag] - carry; 00349 #ifdef TRACE_IO 00350 if (flat_trace) { 00351 std::cout << "float_seed_table[" << j_lag << "] = " 00352 << float_seed_table[j_lag] 00353 << " float_seed_table[" << i_lag << "] = " << float_seed_table[i_lag] 00354 << " uni = " << uni << "\n"; 00355 std::cout << float_seed_table[j_lag] 00356 << " - " << float_seed_table[i_lag] 00357 << " - " << carry << " = " 00358 << (double)float_seed_table[j_lag] 00359 - (double) float_seed_table[i_lag] - (double)carry 00360 << "\n"; 00361 } 00362 #endif 00363 if(uni < 0. ){ 00364 uni += 1.0; 00365 carry = mantissa_bit_24(); 00366 }else{ 00367 carry = 0.; 00368 } 00369 00370 float_seed_table[i_lag] = uni; 00371 i_lag --; 00372 j_lag --; 00373 if(i_lag < 0) i_lag = 23; 00374 if(j_lag < 0) j_lag = 23; 00375 00376 if( uni < mantissa_bit_12() ){ 00377 uni += mantissa_bit_24() * float_seed_table[j_lag]; 00378 if( uni == 0) uni = mantissa_bit_24() * mantissa_bit_24(); 00379 } 00380 next_random = uni; 00381 count24 ++; 00382 00383 // every 24th number generation, several random numbers are generated 00384 // and wasted depending upon the luxury level. 00385 00386 if(count24 == 24 ){ 00387 count24 = 0; 00388 #ifdef TRACE_IO 00389 if (flat_trace) { 00390 std::cout << "carry = " << carry << "\n"; 00391 } 00392 #endif 00393 for( i = 0; i != nskip ; i++){ 00394 uni = float_seed_table[j_lag] - float_seed_table[i_lag] - carry; 00395 if(uni < 0. ){ 00396 uni += 1.0; 00397 carry = mantissa_bit_24(); 00398 }else{ 00399 carry = 0.; 00400 } 00401 float_seed_table[i_lag] = uni; 00402 #ifdef TRACE_IO 00403 if (flat_trace) { 00404 double xfst = float_seed_table[i_lag]; 00405 std::cout << "fst[" << i_lag << "] = " 00406 << DoubConv::d2x(xfst) << "\n"; 00407 } 00408 #endif 00409 i_lag --; 00410 j_lag --; 00411 if(i_lag < 0)i_lag = 23; 00412 if(j_lag < 0) j_lag = 23; 00413 } 00414 } 00415 #ifdef TRACE_IO 00416 if (flat_trace) { 00417 std::cout << "next_random = " << next_random << "\n"; 00418 // flat_trace = false; 00419 } 00420 #endif 00421 return (double) next_random; 00422 } 00423 00424 void RanluxEngine::flatArray(const int size, double* vect) 00425 { 00426 float next_random; 00427 float uni; 00428 int i; 00429 int index; 00430 00431 for (index=0; index<size; ++index) { 00432 uni = float_seed_table[j_lag] - float_seed_table[i_lag] - carry; 00433 if(uni < 0. ){ 00434 uni += 1.0; 00435 carry = mantissa_bit_24(); 00436 }else{ 00437 carry = 0.; 00438 } 00439 00440 float_seed_table[i_lag] = uni; 00441 i_lag --; 00442 j_lag --; 00443 if(i_lag < 0) i_lag = 23; 00444 if(j_lag < 0) j_lag = 23; 00445 00446 if( uni < mantissa_bit_12() ){ 00447 uni += mantissa_bit_24() * float_seed_table[j_lag]; 00448 if( uni == 0) uni = mantissa_bit_24() * mantissa_bit_24(); 00449 } 00450 next_random = uni; 00451 vect[index] = (double)next_random; 00452 count24 ++; 00453 00454 // every 24th number generation, several random numbers are generated 00455 // and wasted depending upon the luxury level. 00456 00457 if(count24 == 24 ){ 00458 count24 = 0; 00459 for( i = 0; i != nskip ; i++){ 00460 uni = float_seed_table[j_lag] - float_seed_table[i_lag] - carry; 00461 if(uni < 0. ){ 00462 uni += 1.0; 00463 carry = mantissa_bit_24(); 00464 }else{ 00465 carry = 0.; 00466 } 00467 float_seed_table[i_lag] = uni; 00468 i_lag --; 00469 j_lag --; 00470 if(i_lag < 0)i_lag = 23; 00471 if(j_lag < 0) j_lag = 23; 00472 } 00473 } 00474 } 00475 } 00476 00477 RanluxEngine::operator unsigned int() { 00478 return ((unsigned int)(flat() * exponent_bit_32()) & 0xffffffff) | 00479 (((unsigned int)(float_seed_table[i_lag]*exponent_bit_32())>>16) & 0xff); 00480 // needed because Ranlux doesn't fill all bits of the double 00481 // which therefore doesn't fill all bits of the integer. 00482 } 00483 00484 std::ostream & RanluxEngine::put ( std::ostream& os ) const 00485 { 00486 char beginMarker[] = "RanluxEngine-begin"; 00487 os << beginMarker << "\nUvec\n"; 00488 std::vector<unsigned long> v = put(); 00489 for (unsigned int i=0; i<v.size(); ++i) { 00490 os << v[i] << "\n"; 00491 } 00492 return os; 00493 #ifdef REMOVED 00494 char endMarker[] = "RanluxEngine-end"; 00495 int pr = os.precision(20); 00496 os << " " << beginMarker << " "; 00497 os << theSeed << "\n"; 00498 for (int i=0; i<24; ++i) { 00499 os << float_seed_table[i] << "\n"; 00500 } 00501 os << i_lag << " " << j_lag << "\n"; 00502 os << carry << " " << count24 << " "; 00503 os << luxury << " " << nskip << "\n"; 00504 os << endMarker << "\n"; 00505 os.precision(pr); 00506 return os; 00507 #endif 00508 } 00509 00510 std::vector<unsigned long> RanluxEngine::put () const { 00511 std::vector<unsigned long> v; 00512 v.push_back (engineIDulong<RanluxEngine>()); 00513 #ifdef TRACE_IO 00514 std::cout << "RanluxEngine put: ID is " << v[0] << "\n"; 00515 #endif 00516 for (int i=0; i<24; ++i) { 00517 v.push_back 00518 (static_cast<unsigned long>(float_seed_table[i]/mantissa_bit_24())); 00519 #ifdef TRACE_IO 00520 std::cout << "v[" << i+1 << "] = " << v[i+1] << 00521 " float_seed_table[" << i << "] = " << float_seed_table[i] << "\n"; 00522 #endif 00523 } 00524 v.push_back(static_cast<unsigned long>(i_lag)); 00525 v.push_back(static_cast<unsigned long>(j_lag)); 00526 v.push_back(static_cast<unsigned long>(carry/mantissa_bit_24())); 00527 v.push_back(static_cast<unsigned long>(count24)); 00528 v.push_back(static_cast<unsigned long>(luxury)); 00529 v.push_back(static_cast<unsigned long>(nskip)); 00530 #ifdef TRACE_IO 00531 std::cout << "i_lag: " << v[25] << " j_lag: " << v[26] 00532 << " carry: " << v[27] << "\n"; 00533 std::cout << "count24: " << v[28] << " luxury: " << v[29] 00534 << " nskip: " << v[30] << "\n"; 00535 #endif 00536 #ifdef TRACE_IO 00537 flat_trace = true; 00538 #endif 00539 return v; 00540 } 00541 00542 std::istream & RanluxEngine::get ( std::istream& is ) 00543 { 00544 char beginMarker [MarkerLen]; 00545 is >> std::ws; 00546 is.width(MarkerLen); // causes the next read to the char* to be <= 00547 // that many bytes, INCLUDING A TERMINATION \0 00548 // (Stroustrup, section 21.3.2) 00549 is >> beginMarker; 00550 if (strcmp(beginMarker,"RanluxEngine-begin")) { 00551 is.clear(std::ios::badbit | is.rdstate()); 00552 std::cerr << "\nInput stream mispositioned or" 00553 << "\nRanluxEngine state description missing or" 00554 << "\nwrong engine type found." << std::endl; 00555 return is; 00556 } 00557 return getState(is); 00558 } 00559 00560 std::string RanluxEngine::beginTag ( ) { 00561 return "RanluxEngine-begin"; 00562 } 00563 00564 std::istream & RanluxEngine::getState ( std::istream& is ) 00565 { 00566 if ( possibleKeywordInput ( is, "Uvec", theSeed ) ) { 00567 std::vector<unsigned long> v; 00568 unsigned long uu; 00569 for (unsigned int ivec=0; ivec < VECTOR_STATE_SIZE; ++ivec) { 00570 is >> uu; 00571 if (!is) { 00572 is.clear(std::ios::badbit | is.rdstate()); 00573 std::cerr << "\nRanluxEngine state (vector) description improper." 00574 << "\ngetState() has failed." 00575 << "\nInput stream is probably mispositioned now." << std::endl; 00576 return is; 00577 } 00578 v.push_back(uu); 00579 #ifdef TRACE_IO 00580 std::cout << "RanluxEngine::getState -- v[" << v.size()-1 00581 << "] = " << v[v.size()-1] << "\n"; 00582 #endif 00583 } 00584 getState(v); 00585 return (is); 00586 } 00587 00588 // is >> theSeed; Removed, encompassed by possibleKeywordInput() 00589 00590 char endMarker [MarkerLen]; 00591 for (int i=0; i<24; ++i) { 00592 is >> float_seed_table[i]; 00593 } 00594 is >> i_lag; is >> j_lag; 00595 is >> carry; is >> count24; 00596 is >> luxury; is >> nskip; 00597 is >> std::ws; 00598 is.width(MarkerLen); 00599 is >> endMarker; 00600 if (strcmp(endMarker,"RanluxEngine-end")) { 00601 is.clear(std::ios::badbit | is.rdstate()); 00602 std::cerr << "\nRanluxEngine state description incomplete." 00603 << "\nInput stream is probably mispositioned now." << std::endl; 00604 return is; 00605 } 00606 return is; 00607 } 00608 00609 bool RanluxEngine::get (const std::vector<unsigned long> & v) { 00610 if ((v[0] & 0xffffffffUL) != engineIDulong<RanluxEngine>()) { 00611 std::cerr << 00612 "\nRanluxEngine get:state vector has wrong ID word - state unchanged\n"; 00613 return false; 00614 } 00615 return getState(v); 00616 } 00617 00618 bool RanluxEngine::getState (const std::vector<unsigned long> & v) { 00619 if (v.size() != VECTOR_STATE_SIZE ) { 00620 std::cerr << 00621 "\nRanluxEngine get:state vector has wrong length - state unchanged\n"; 00622 return false; 00623 } 00624 for (int i=0; i<24; ++i) { 00625 float_seed_table[i] = v[i+1]*mantissa_bit_24(); 00626 #ifdef TRACE_IO 00627 std::cout << 00628 "float_seed_table[" << i << "] = " << float_seed_table[i] << "\n"; 00629 #endif 00630 } 00631 i_lag = v[25]; 00632 j_lag = v[26]; 00633 carry = v[27]*mantissa_bit_24(); 00634 count24 = v[28]; 00635 luxury = v[29]; 00636 nskip = v[30]; 00637 #ifdef TRACE_IO 00638 std::cout << "i_lag: " << i_lag << " j_lag: " << j_lag 00639 << " carry: " << carry << "\n"; 00640 std::cout << "count24: " << count24 << " luxury: " << luxury 00641 << " nskip: " << nskip << "\n"; 00642 00643 #endif 00644 #ifdef TRACE_IO 00645 flat_trace = true; 00646 #endif 00647 return true; 00648 } 00649 00650 } // namespace CLHEP