X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=src%2Fbase%2Frandom.cc;h=7daa90b9cf98ed22757cc0a153dc239790c5d341;hb=2a1309f2134986edcbff846aff5951ec1e8df6e1;hp=e135b55f5b9b053ba7f9bb0d434ff357731006e6;hpb=3c95f5958fd1a90cf83d85e1b24fb700c07bae91;p=gem5.git diff --git a/src/base/random.cc b/src/base/random.cc index e135b55f5..7daa90b9c 100644 --- a/src/base/random.cc +++ b/src/base/random.cc @@ -29,72 +29,88 @@ * Ali Saidi */ -#include -#include - -#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"); + // default random seed taken from original source + init(5489); +} -Param -seed(¶mContext, "seed", "seed to random number generator", 1); +Random::Random(uint32_t s) +{ + init(s); +} -void -RandomContext::checkParams() +Random::Random(uint32_t init_key[], int key_length) { - ::srand48(seed); + init(init_key, key_length); } -long -getLong() +Random::~Random() { - return mrand48(); } -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; - return (int64_t)round(r); + 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) { - double r; - r = drand48() * (max-min) + min; - return (uint64_t)round(r); + 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) +{ + 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;