stats: cleanup a few small problems in stats
[gem5.git] / src / base / random.cc
index 8a2e3c1c0c8a47db4a761abc720c09a393ee1004..7daa90b9cf98ed22757cc0a153dc239790c5d341 100644 (file)
  *          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 &section)
+{
+    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;