Geant4-11
Public Member Functions | Private Attributes
CLHEP::DualRand::Tausworthe Class Reference

Public Member Functions

void get (std::istream &is)
 
bool get (std::vector< unsigned long >::const_iterator &iv)
 
 operator unsigned int ()
 
void put (std::ostream &os) const
 
void put (std::vector< unsigned long > &v) const
 
 Tausworthe ()
 
 Tausworthe (unsigned int seed)
 

Private Attributes

int wordIndex
 
unsigned int words [4]
 

Detailed Description

Definition at line 108 of file DualRand.h.

Constructor & Destructor Documentation

◆ Tausworthe() [1/2]

CLHEP::DualRand::Tausworthe::Tausworthe ( )

Definition at line 315 of file DualRand.cc.

315 {
316 words[0] = 1234567;
317 for (wordIndex = 1; wordIndex < 4; ++wordIndex) {
318 words[wordIndex] = 69607 * words[wordIndex-1] + 54329;
319 }
320}
unsigned int words[4]
Definition: DualRand.h:119

References wordIndex, and words.

◆ Tausworthe() [2/2]

CLHEP::DualRand::Tausworthe::Tausworthe ( unsigned int  seed)

Definition at line 322 of file DualRand.cc.

322 {
323 words[0] = seed;
324 for (wordIndex = 1; wordIndex < 4; ++wordIndex) {
325 words[wordIndex] = 69607 * words[wordIndex-1] + 54329;
326 }
327}

Member Function Documentation

◆ get() [1/2]

void CLHEP::DualRand::Tausworthe::get ( std::istream &  is)

Definition at line 408 of file DualRand.cc.

408 {
409 char beginMarker [MarkerLen];
410 char endMarker [MarkerLen];
411
412 is >> std::ws;
413 is.width(MarkerLen); // causes the next read to the char* to be <=
414 // that many bytes, INCLUDING A TERMINATION \0
415 // (Stroustrup, section 21.3.2)
416 is >> beginMarker;
417 if (strcmp(beginMarker,"Tausworthe-begin")) {
418 is.clear(std::ios::badbit | is.rdstate());
419 std::cerr << "\nInput mispositioned or"
420 << "\nTausworthe state description missing or"
421 << "\nwrong engine type found." << std::endl;
422 }
423 for (int i = 0; i < 4; ++i) {
424 is >> words[i];
425 }
426 is >> wordIndex;
427 is >> std::ws;
428 is.width(MarkerLen);
429 is >> endMarker;
430 if (strcmp(endMarker,"Tausworthe-end")) {
431 is.clear(std::ios::badbit | is.rdstate());
432 std::cerr << "\nTausworthe state description incomplete."
433 << "\nInput stream is probably mispositioned now." << std::endl;
434 }
435}
static const int MarkerLen
Definition: DualRand.cc:70

References CLHEP::MarkerLen.

Referenced by CLHEP::DualRand::getState(), and CLHEP::DualRand::restoreStatus().

◆ get() [2/2]

bool CLHEP::DualRand::Tausworthe::get ( std::vector< unsigned long >::const_iterator &  iv)

Definition at line 438 of file DualRand.cc.

438 {
439 for (int i = 0; i < 4; ++i) {
440 words[i] = *iv++;
441 }
442 wordIndex = *iv++;
443 return true;
444}

◆ operator unsigned int()

CLHEP::DualRand::Tausworthe::operator unsigned int ( )

Definition at line 329 of file DualRand.cc.

329 {
330
331// Mathematically: Consider a sequence of bits b[n]. Repeatedly form
332// b[0]' = b[127] ^ b[97]; b[n]' = b[n-1]. This sequence will have a very
333// long period (2**127-1 according to Tausworthe's work).
334
335// The actual method used relies on the fact that the operations needed to
336// form bit 0 for up to 96 iterations never depend on the results of the
337// previous ones. So you can actually compute many bits at once. In fact
338// you can compute 32 at once -- despite 127 - 97 < 32 -- but 24 was used in
339// the method used in Canopy, where they wanted only single-precision float
340// randoms. I will do 32 here.
341
342// When you do it this way, this looks disturbingly like the dread lagged XOR
343// Fibonacci. And indeed, it is a lagged Fibonacii, F(4,3, op) with the op
344// being the XOR of a combination of shifts of the two numbers. Although
345// Tausworthe asserted excellent properties, I would be scared to death.
346// However, the shifting and bit swapping really does randomize this in a
347// serious way.
348
349// Statements have been made to the effect that shift register sequences fail
350// the parking lot test because they achieve randomness by multiple foldings,
351// and this produces a characteristic pattern. We observe that in this
352// specific algorithm, which has a fairly long lever arm, the foldings become
353// effectively random. This is evidenced by the fact that the generator
354// does pass the Diehard tests, including the parking lot test.
355
356// To avoid shuffling of variables in memory, you either have to use circular
357// pointers (and those give you ifs, which are also costly) or compute at least
358// a few iterations at once. We do the latter. Although there is a possible
359// trade of room for more speed, by computing and saving 256 instead of 128
360// bits at once, I will stop at this level of optimization.
361
362// To remind: Each (32-bit) step takes the XOR of bits [127-96] with bits
363// [95-64] and places it in bits [0-31]. But in the first step, we designate
364// word0 as bits [0-31], in the second step, word 1 (since the bits it holds
365// will no longer be needed), then word 2, then word 3. After this, the
366// stream contains 128 random bits which we will use as 4 valid 32-bit
367// random numbers.
368
369// Thus at the start of the first step, word[0] contains the newest (used)
370// 32-bit random, and word[3] the oldest. After four steps, word[0] again
371// contains the newest (now unused) random, and word[3] the oldest.
372// Bit 0 of word[0] is logically the newest bit, and bit 31 of word[3]
373// the oldest.
374
375 if (wordIndex <= 0) {
376 for (wordIndex = 0; wordIndex < 4; ++wordIndex) {
377 words[wordIndex] = ( (words[(wordIndex+1) & 3] << 1 ) |
378 (words[wordIndex] >> 31) )
379 ^ ( (words[(wordIndex+1) & 3] << 31) |
380 (words[wordIndex] >> 1) );
381 }
382 }
383 return words[--wordIndex] & 0xffffffff;
384}

◆ put() [1/2]

void CLHEP::DualRand::Tausworthe::put ( std::ostream &  os) const

Definition at line 386 of file DualRand.cc.

386 {
387 char beginMarker[] = "Tausworthe-begin";
388 char endMarker[] = "Tausworthe-end";
389
390 int pr=os.precision(20);
391 os << " " << beginMarker << " ";
392 for (int i = 0; i < 4; ++i) {
393 os << words[i] << " ";
394 }
395 os << wordIndex;
396 os << " " << endMarker << " ";
397 os << std::endl;
398 os.precision(pr);
399}

Referenced by CLHEP::DualRand::put(), and CLHEP::DualRand::showStatus().

◆ put() [2/2]

void CLHEP::DualRand::Tausworthe::put ( std::vector< unsigned long > &  v) const

Definition at line 401 of file DualRand.cc.

401 {
402 for (int i = 0; i < 4; ++i) {
403 v.push_back(static_cast<unsigned long>(words[i]));
404 }
405 v.push_back(static_cast<unsigned long>(wordIndex));
406}

Field Documentation

◆ wordIndex

int CLHEP::DualRand::Tausworthe::wordIndex
private

Definition at line 118 of file DualRand.h.

Referenced by Tausworthe().

◆ words

unsigned int CLHEP::DualRand::Tausworthe::words[4]
private

Definition at line 119 of file DualRand.h.

Referenced by Tausworthe().


The documentation for this class was generated from the following files: