X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fbase%2Frandom.cc;h=7daa90b9cf98ed22757cc0a153dc239790c5d341;hb=2a1309f2134986edcbff846aff5951ec1e8df6e1;hp=82c9e356621ca8907855d29eff53a4e22831e454;hpb=b82fa633bb9a9bf72b724dcf202985f37ab1d8b8;p=gem5.git diff --git a/src/base/random.cc b/src/base/random.cc index 82c9e3566..7daa90b9c 100644 --- a/src/base/random.cc +++ b/src/base/random.cc @@ -29,92 +29,88 @@ * Ali Saidi */ -#include -#include - -#if defined(__sun__) -#include -#endif - -#include "sim/param.hh" +#include "base/fenv.hh" +#include "base/intmath.hh" +#include "base/misc.hh" #include "base/random.hh" -#include "base/trace.hh" +#include "sim/serialize.hh" using namespace std; -class RandomContext : public ParamContext +Random::Random() { - public: - RandomContext(const string &_iniSection) - : ::ParamContext(_iniSection) {} - ~RandomContext() {} - - void checkParams(); -}; - -RandomContext paramContext("random"); - -Param -seed(¶mContext, "seed", "seed to random number generator", 1); + // default random seed taken from original source + init(5489); +} -void -RandomContext::checkParams() +Random::Random(uint32_t s) { - ::srand48(seed); + init(s); } -long -getLong() +Random::Random(uint32_t init_key[], int key_length) { - return mrand48(); + init(init_key, key_length); } -double -m5round(double r) +Random::~Random() { -#if defined(__sun__) - double val; - fp_rnd oldrnd = fpsetround(FP_RN); - val = rint(r); - fpsetround(oldrnd); - return val; -#else - return round(r); -#endif } -int64_t -getUniform(int64_t min, int64_t max) +// 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) { - double r; - r = drand48() * (max-min) + min; + int log = ceilLog2(max); + int shift = (sizeof(uint32_t) * 8 - log); + uint32_t random; - return (int64_t)m5round(r); + do { + random = genrand() >> shift; + } while (random > max); + + return random; } uint64_t -getUniformPos(uint64_t min, uint64_t max) +Random::genrand(uint64_t max) { - double r; - r = drand48() * (max-min) + min; + 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 (uint64_t)m5round(r); + return random; } +void +Random::serialize(const string &base, ostream &os) +{ + int length = N; + paramOut(os, base + ".mti", mti); + paramOut(os, base + ".length", length); + arrayParamOut(os, base + ".data", mt, length); +} -// idea for generating a double from erand48 -double -getDouble() +void +Random::unserialize(const string &base, Checkpoint *cp, const string §ion) { - union { - uint32_t _long[2]; - uint16_t _short[4]; - }; + int length; - _long[0] = mrand48(); - _long[1] = mrand48(); + 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); - return ldexp((double) _short[0], -48) + - ldexp((double) _short[1], -32) + - ldexp((double) _short[2], -16); + arrayParamIn(cp, section, base + ".data", mt, length); } + +Random random_mt;