diff options
author | Ali Saidi <saidi@eecs.umich.edu> | 2007-10-31 01:21:54 -0400 |
---|---|---|
committer | Ali Saidi <saidi@eecs.umich.edu> | 2007-10-31 01:21:54 -0400 |
commit | 7597f87430bc25547c594dd09f10be4953f987c3 (patch) | |
tree | f1016e3df49d93020b8d2e0931872e17696a7bca /src/base/random.cc | |
parent | 04d1cfe31ce92809830722081f3223a4d61b05df (diff) | |
download | gem5-7597f87430bc25547c594dd09f10be4953f987c3.tar.xz |
Base: Rework the way M5 provides and creates random numbers.
--HG--
extra : convert_revision : 10ec3484647b3acb8e821f8520f97d535e41e861
Diffstat (limited to 'src/base/random.cc')
-rw-r--r-- | src/base/random.cc | 98 |
1 files changed, 63 insertions, 35 deletions
diff --git a/src/base/random.cc b/src/base/random.cc index 8a2e3c1c0..7daa90b9c 100644 --- a/src/base/random.cc +++ b/src/base/random.cc @@ -29,60 +29,88 @@ * Ali Saidi */ -#ifdef __SUNPRO_CC -#include <stdlib.h> -#include <math.h> -#endif - -#include <cstdlib> -#include <cmath> - #include "base/fenv.hh" +#include "base/intmath.hh" +#include "base/misc.hh" #include "base/random.hh" +#include "sim/serialize.hh" using namespace std; -uint32_t -getInt32() +Random::Random() { - return mrand48() & 0xffffffff; + // default random seed taken from original source + init(5489); } -double -getDouble() +Random::Random(uint32_t s) { - return drand48(); + init(s); } -double -m5round(double r) +Random::Random(uint32_t init_key[], int key_length) { -#if defined(__sun) - double val; - int oldrnd = m5_fegetround(); - m5_fesetround(M5_FE_TONEAREST); - val = rint(r); - m5_fesetround(oldrnd); - return val; -#else - return round(r); -#endif + init(init_key, key_length); } -int64_t -getUniform(int64_t min, int64_t max) +Random::~Random() { - double r; - r = drand48() * (max-min) + min; +} - return (int64_t)m5round(r); +// To preserve the uniform random distribution between min and max, +// and allow all numbers to be represented, we generate a uniform +// random number to the nearest power of two greater than max. If +// this number doesn't fall between 0 and max, we try again. Anything +// else would skew the distribution. +uint32_t +Random::genrand(uint32_t max) +{ + int log = ceilLog2(max); + int shift = (sizeof(uint32_t) * 8 - log); + uint32_t random; + + do { + random = genrand() >> shift; + } while (random > max); + + return random; } uint64_t -getUniformPos(uint64_t min, uint64_t max) +Random::genrand(uint64_t max) +{ + int log = ceilLog2(max); + int shift = (sizeof(uint64_t) * 8 - log); + uint64_t random; + + do { + random = (uint64_t)genrand() << 32 | (uint64_t)genrand(); + random = random >> shift; + } while (random > max); + + return random; +} + +void +Random::serialize(const string &base, ostream &os) { - double r; - r = drand48() * (max-min) + min; + int length = N; + paramOut(os, base + ".mti", mti); + paramOut(os, base + ".length", length); + arrayParamOut(os, base + ".data", mt, length); +} - return (uint64_t)m5round(r); +void +Random::unserialize(const string &base, Checkpoint *cp, const string §ion) +{ + int length; + + paramIn(cp, section, base + ".mti", mti); + paramIn(cp, section, base + ".length", length); + if (length != N) + panic("cant unserialize random number data. length != %d\n", length); + + arrayParamIn(cp, section, base + ".data", mt, length); } + +Random random_mt; |