Commit ca8b580e authored by Lynn Garren's avatar Lynn Garren
Browse files

working test of StdRandom

parent 7e17e7b0
......@@ -27,7 +27,7 @@ TESTS = \
XFAIL_TESTS =
# Identify the dependencies on a per-test basis:
testStdRandom_SOURCES = testStdRandom.cc
testStdRandom_SOURCES = testStdRandom.cc SimpleRand.cc
# Identify input data file(s) and prototype output file(s):
#EXTRA_DIST =
......
//////////////////////////////////////////////////////////////////////////
// Since it is unfair to introduce a dependency on CLHEP Random for the sake
// of the test, we use a simple, non-robust, interface to random()
//////////////////////////////////////////////////////////////////////////
#include "SimpleRand.hh"
static const int MarkerLen = 64; // Enough room to hold a begin or end marker.
SimpleRand::SimpleRand(long seed)
: theSeed(seed), seq(0)
{
setSeed(theSeed);
seq = 0;
}
SimpleRand::SimpleRand()
: theSeed(197805031), seq(0)
{
setSeed(theSeed);
seq = 0;
}
SimpleRand::~SimpleRand() {}
void SimpleRand::setSeed(long seed)
{
theSeed = seed;
srand( int(seed) );
seq = 0;
}
void SimpleRand::saveStatus( std::ostream& os ) const
{
put(os);
}
std::ostream & SimpleRand::put ( std::ostream& os ) const
{
char beginMarker[] = "SimpleRand-begin";
char endMarker[] = "SimpleRand-end";
os << " " << beginMarker << "\n";
os << theSeed << " " << seq << " ";
os << endMarker << "\n";
return os;
}
void SimpleRand::restoreStatus( std::istream& is )
{
get( is );
}
std::istream & SimpleRand::get ( std::istream& is )
{
// The only way to restore the status of SimpleRand is to
// keep track of the number of shooted random sequences, reset
// the engine and re-shoot them again. The Rand algorithm does
// not provide any way of getting its internal status.
char beginMarker [MarkerLen];
is >> std::ws;
is.width(MarkerLen); // causes the next read to the char* to be <=
// that many bytes, INCLUDING A TERMINATION \0
// (Stroustrup, section 21.3.2)
is >> beginMarker;
if (strcmp(beginMarker,"SimpleRand-begin")) {
is.clear(std::ios::badbit | is.rdstate());
std::cout << "\nInput stream mispositioned or"
<< "\nSimpleRand state description missing or"
<< "\nwrong engine type found." << std::endl;
return is;
}
char endMarker [MarkerLen];
long count;
is >> theSeed;
is >> count;
is >> std::ws;
is.width(MarkerLen);
is >> endMarker;
if (strcmp(endMarker,"SimpleRand-end")) {
is.clear(std::ios::badbit | is.rdstate());
std::cerr << "\nSimpleRand state description incomplete."
<< "\nInput stream is probably mispositioned now." << std::endl;
return is;
}
setSeed(theSeed);
while (seq < count) flat();
return is;
}
void SimpleRand::showStatus() const
{
std::cout << std::endl;
std::cout << "---------- Rand engine status ----------" << std::endl;
std::cout << " Initial seed = " << theSeed << std::endl;
std::cout << " Shooted sequences = " << seq << std::endl;
std::cout << "----------------------------------------" << std::endl;
}
unsigned int SimpleRand::SimpleRandBuilder()
{ // RAND_MAX = 2**31 - 1
unsigned int x = rand() << 1; ++seq; // bits 31-1
x ^= ( (x>>23) ^ (x>>7) ) ^1; // bit 0 (weakly pseudo-random)
return x & 0xFFFFFFFF; // mask in case int is 64 bits
}
double SimpleRand::flat()
{
double r;
do { r = SimpleRandBuilder();
} while ( r == 0 );
return r/4294967296.0;
}
SimpleRand::operator unsigned int() {
return SimpleRandBuilder();
}
#ifndef SIMPLE_RAND_HH
#define SIMPLE_RAND_HH
//////////////////////////////////////////////////////////////////////////
// Since it is unfair to introduce a dependency on CLHEP Random for the sake
// of the test, we use a simple, non-robust, interface to random()
//////////////////////////////////////////////////////////////////////////
#include <iostream>
class SimpleRand {
public:
SimpleRand();
SimpleRand(long seed);
~SimpleRand();
// Constructors and destructor
double flat();
// It returns a pseudo random number between 0 and 1,
// according to the standard stdlib random function rand()
// but excluding the end points.
//
// WARNING: rand() is quite a weak generator on most systems, <
// will not pass several randomness tests, and does not give a <
// reproducible sequence of numbers. <
void setSeed(long seed);
// Sets the state of the algorithm according to seed.
std::ostream & put (std::ostream & os) const;
void saveStatus( std::ostream & os ) const;
std::istream & get (std::istream & is);
void restoreStatus( std::istream & is );
void showStatus() const;
// Dumps the engine status on the screen.
operator unsigned int(); // 32-bit flat value, quickest of all.
private:
unsigned int SimpleRandBuilder();
private:
long theSeed;
long seq;
};
#endif // SIMPLE_RAND_HH
......@@ -7,13 +7,19 @@
#include <vector>
#include <iostream>
#include <sstream>
#include <string>
#include "CLHEP/StdHep/StdRandom.hh"
#include "SimpleRand.hh"
int main() {
int status=0;
double d, saved;
StdHep::StdRandom rstate;
std::string state;
// fill and save an arbitrary vector just for grins
std::vector<unsigned long> rs;
......@@ -21,5 +27,43 @@ int main() {
rstate.putState( rs );
rstate.print();
// try using SimpleRand
SimpleRand* simp = new SimpleRand(4124123);
// throw
for( int i=0; i<12; ++i ) {
d = simp->flat();
// get and then save the state
std::ostringstream ostr;
simp->put(ostr);
state = ostr.str();
rstate.putState( state );
}
// this double is generated by the last saved state
d = simp->flat();
saved = d;
// throw some more
for( int i=0; i<14; ++i ) {
d = simp->flat();
}
// make sure we have gone beyond the saved state
if ( d == saved ) {
std::cout << "still at the same state, something is wrong " << std::endl;
status = 1;
}
// restore the saved state
state = rstate.getStateAsString();
std::istringstream ist(state);
simp->get(ist);
d = simp->flat();
if ( d == saved ) {
std::cout << "generated the same number" << std::endl;
status = 0;
} else {
std::cout << "saved double " << saved
<< " does not match generated double " << d << std::endl;
status = 1;
}
return status;
}
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment