/*
+ * Copyright (c) 2014 ARM Limited
+ * All rights reserved
+ *
+ * The license below extends only to copyright in the software and shall
+ * not be construed as granting a license to any other intellectual
+ * property including but not limited to intellectual property relating
+ * to a hardware implementation of the functionality of the software
+ * licensed hereunder. You may use the software subject to the license
+ * terms below provided that you ensure that this notice is replicated
+ * unmodified and in its entirety in all distributions of the software,
+ * modified or unmodified, in source code or in binary form.
+ *
* Copyright (c) 2003-2005 The Regents of The University of Michigan
* All rights reserved.
*
*
* Authors: Nathan Binkert
* Ali Saidi
+ * Andreas Hansson
+ */
+
+/*
+ * Mersenne twister random number generator.
*/
#ifndef __BASE_RANDOM_HH__
#define __BASE_RANDOM_HH__
-#include "sim/host.hh"
-
-long getLong();
-double getDouble();
-double m5random(double r);
-uint64_t getUniformPos(uint64_t min, uint64_t max);
-int64_t getUniform(int64_t min, int64_t max);
-
-template <typename T>
-struct Random;
-
-template<> struct Random<int8_t>
-{
- static int8_t get()
- { return getLong() & (int8_t)-1; }
-
- static int8_t uniform(int8_t min, int8_t max)
- { return getUniform(min, max); }
-};
-
-template<> struct Random<uint8_t>
-{
- static uint8_t get()
- { return getLong() & (uint8_t)-1; }
-
- static uint8_t uniform(uint8_t min, uint8_t max)
- { return getUniformPos(min, max); }
-};
-
-template<> struct Random<int16_t>
-{
- static int16_t get()
- { return getLong() & (int16_t)-1; }
-
- static int16_t uniform(int16_t min, int16_t max)
- { return getUniform(min, max); }
-};
-
-template<> struct Random<uint16_t>
-{
- static uint16_t get()
- { return getLong() & (uint16_t)-1; }
-
- static uint16_t uniform(uint16_t min, uint16_t max)
- { return getUniformPos(min, max); }
-};
-
-template<> struct Random<int32_t>
-{
- static int32_t get()
- { return (int32_t)getLong(); }
+#include <random>
+#include <string>
+#include <type_traits>
- static int32_t uniform(int32_t min, int32_t max)
- { return getUniform(min, max); }
-};
+#include "base/types.hh"
-template<> struct Random<uint32_t>
-{
- static uint32_t get()
- { return (uint32_t)getLong(); }
-
- static uint32_t uniform(uint32_t min, uint32_t max)
- { return getUniformPos(min, max); }
-};
+class Checkpoint;
-template<> struct Random<int64_t>
+class Random
{
- static int64_t get()
- { return (int64_t)getLong() << 32 || (uint64_t)getLong(); }
- static int64_t uniform(int64_t min, int64_t max)
- { return getUniform(min, max); }
+ private:
+
+ std::mt19937_64 gen;
+
+ public:
+
+ Random();
+ Random(uint32_t s);
+ ~Random();
+
+ void init(uint32_t s);
+
+ /**
+ * Use the SFINAE idiom to choose an implementation based on
+ * whether the type is integral or floating point.
+ */
+ template <typename T>
+ typename std::enable_if<std::is_integral<T>::value, T>::type
+ random()
+ {
+ // [0, max_value] for integer types
+ std::uniform_int_distribution<T> dist;
+ return dist(gen);
+ }
+
+ template <typename T>
+ typename std::enable_if<std::is_floating_point<T>::value, T>::type
+ random()
+ {
+ // [0, 1) for real types
+ std::uniform_real_distribution<T> dist;
+ return dist(gen);
+ }
+
+ template <typename T>
+ typename std::enable_if<std::is_integral<T>::value, T>::type
+ random(T min, T max)
+ {
+ std::uniform_int_distribution<T> dist(min, max);
+ return dist(gen);
+ }
+
+ void serialize(std::ostream &os);
+ void unserialize(Checkpoint *cp, const std::string §ion);
};
-template<> struct Random<uint64_t>
-{
- static uint64_t get()
- { return (uint64_t)getLong() << 32 || (uint64_t)getLong(); }
-
- static uint64_t uniform(uint64_t min, uint64_t max)
- { return getUniformPos(min, max); }
-};
-
-template<> struct Random<float>
-{
- static float get()
- { return getDouble(); }
-};
-
-template<> struct Random<double>
-{
- static double get()
- { return getDouble(); }
-};
+extern Random random_mt;
#endif // __BASE_RANDOM_HH__