# HG changeset patch # User deba # Date 1160839565 0 # Node ID 16523135943d4e7c9492385f138ae996e13ac411 # Parent 37e0966e43b62d8309d217f53e7cd72006255f6a New random interface Switching to the new interface diff -r 37e0966e43b6 -r 16523135943d benchmark/edge_lookup.cc --- a/benchmark/edge_lookup.cc Fri Oct 13 15:10:50 2006 +0000 +++ b/benchmark/edge_lookup.cc Sat Oct 14 15:26:05 2006 +0000 @@ -2,6 +2,7 @@ #include #include #include +#include using namespace lemon; @@ -100,7 +101,7 @@ std::vector v; for(int i=0;i +#include + #include #include #include @@ -37,7 +39,7 @@ int n = 10000000; vector data(n); for (int i = 0; i < n; ++i) { - data[i] = (int)(1000 * (rand() / (RAND_MAX + 1.0))) - 500; + data[i] = rnd[1000] - 500; } radixSort(data.begin(), data.end()); } @@ -47,7 +49,7 @@ int n = 10000000; vector data(n); for (int i = 0; i < n; ++i) { - data[i] = (int)(1000 * (rand() / (RAND_MAX + 1.0))) - 500; + data[i] = rnd[1000] - 500; } counterSort(data.begin(), data.end()); } @@ -56,7 +58,7 @@ int n = 10000000; vector data(n); for (int i = 0; i < n; ++i) { - data[i] = (int)(1000 * (rand() / (RAND_MAX + 1.0))) - 500; + data[i] = rnd[1000] - 500; } sort(data.begin(), data.end()); } @@ -65,7 +67,7 @@ int n = 10000000; vector data(n); for (int i = 0; i < n; ++i) { - data[i] = (int)(1000 * (rand() / (RAND_MAX + 1.0))) - 500; + data[i] = rnd[1000] - 500; } stable_sort(data.begin(), data.end()); } diff -r 37e0966e43b6 -r 16523135943d benchmark/swap_bipartite_bench.cc --- a/benchmark/swap_bipartite_bench.cc Fri Oct 13 15:10:50 2006 +0000 +++ b/benchmark/swap_bipartite_bench.cc Sat Oct 14 15:26:05 2006 +0000 @@ -12,6 +12,7 @@ #include #include +#include using namespace std; using namespace lemon; @@ -20,17 +21,6 @@ typedef ListBpUGraph LGraph; BPUGRAPH_TYPEDEFS(Graph); -int _urandom_init() { - int seed = time(0); - srand(seed); - return seed; -} - -int urandom(int n) { - static int seed = _urandom_init(); - ignore_unused_variable_warning(seed); - return (int)(rand() / (1.0 + RAND_MAX) * n); -} int main() { @@ -66,8 +56,8 @@ } for (int i = 0; i < e; ++i) { int a,b; - Node aNode = aNodes[a=urandom(n)]; - Node bNode = bNodes[b=urandom(m)]; + Node aNode = aNodes[a=rnd[n]]; + Node bNode = bNodes[b=rnd[m]]; graph.addEdge(aNode, bNode); LGraph::Node laNode = laNodes[a]; LGraph::Node lbNode = lbNodes[b]; diff -r 37e0966e43b6 -r 16523135943d demo/descriptor_map_demo.cc --- a/demo/descriptor_map_demo.cc Fri Oct 13 15:10:50 2006 +0000 +++ b/demo/descriptor_map_demo.cc Sat Oct 14 15:26:05 2006 +0000 @@ -32,11 +32,12 @@ #include #include +#include + #include -#include #include -#include + using namespace lemon; @@ -75,7 +76,6 @@ }; int main() { - std::srand(std::time(0)); typedef ListGraph Graph; typedef Graph::Node Node; typedef Graph::Edge Edge; @@ -105,8 +105,8 @@ // it holds reference to it. const int EDGE = (int)(NODE * std::log(double(NODE))); for (int i = 0; i < EDGE; ++i) { - int si = (int)(std::rand() / (RAND_MAX + 1.0) * NODE); - int ti = (int)(std::rand() / (RAND_MAX + 1.0) * NODE); + int si = rnd[NODE]; + int ti = rnd[NODE]; graph.addEdge(nodeInv[si], nodeInv[ti]); } diff -r 37e0966e43b6 -r 16523135943d demo/simann_maxcut_demo.cc --- a/demo/simann_maxcut_demo.cc Fri Oct 13 15:10:50 2006 +0000 +++ b/demo/simann_maxcut_demo.cc Sat Oct 14 15:26:05 2006 +0000 @@ -54,7 +54,7 @@ Entity(Graph& _g, Graph::EdgeMap& _w) : g(_g), w(_w), a(_g) {} double mutate() { static const int node_num = countNodes(g); - int i = 1 + (int) (node_num * (rand() / (RAND_MAX + 1.0))); + int i = 1 + rnd[node_num]; NodeIt n(g); int j = 1; while (j < i) { @@ -91,7 +91,7 @@ for (NodeIt n(g); n != INVALID; ++n) a[n] = false; for (NodeIt n(g); n != INVALID; ++n) - if (rand() < 0.5) a[n] = true; + if (rnd.boolean(0.5)) a[n] = true; sum = 0; for (EdgeIt e(g); e != INVALID; ++e) if (a[g.source(e)] != a[g.target(e)]) diff -r 37e0966e43b6 -r 16523135943d demo/topology_demo.cc --- a/demo/topology_demo.cc Fri Oct 13 15:10:50 2006 +0000 +++ b/demo/topology_demo.cc Sat Oct 14 15:26:05 2006 +0000 @@ -184,8 +184,6 @@ } int main() { - srand(time(0)); - drawConnectedComponents(); drawStronglyConnectedComponents(); drawNodeBiconnectedComponents(); diff -r 37e0966e43b6 -r 16523135943d lemon/hypercube_graph.h --- a/lemon/hypercube_graph.h Fri Oct 13 15:10:50 2006 +0000 +++ b/lemon/hypercube_graph.h Sat Oct 14 15:26:05 2006 +0000 @@ -260,8 +260,8 @@ /// HyperCubeGraph graph(DIM); /// dim2::Point base[DIM]; /// for (int k = 0; k < DIM; ++k) { - /// base[k].x = random.getReal(); - /// base[k].y = random.getReal(); + /// base[k].x = rnd(); + /// base[k].y = rnd(); /// } /// HyperCubeGraph::HyperMap > /// pos(graph, base, base + DIM, dim2::Point(0.0, 0.0)); diff -r 37e0966e43b6 -r 16523135943d lemon/random.h --- a/lemon/random.h Fri Oct 13 15:10:50 2006 +0000 +++ b/lemon/random.h Sat Oct 14 15:26:05 2006 +0000 @@ -20,6 +20,8 @@ #define LEMON_RANDOM_H #include +#include +#include #include #include @@ -33,46 +35,460 @@ namespace lemon { -#if WORD_BIT == 32 + namespace _random_bits { + + template ::digits> + struct RandomTraits {}; + + template + struct RandomTraits<_Word, 32> { + + typedef _Word Word; + static const int bits = 32; + + static const int length = 624; + static const int shift = 397; + + static const Word mul = 0x6c078965u; + static const Word arrayInit = 0x012BD6AAu; + static const Word arrayMul1 = 0x0019660Du; + static const Word arrayMul2 = 0x5D588B65u; + + static const Word mask = 0x9908B0DFu; + static const Word loMask = (1u << 31) - 1; + static const Word hiMask = ~loMask; + + + static Word tempering(Word rnd) { + rnd ^= (rnd >> 11); + rnd ^= (rnd << 7) & 0x9D2C5680u; + rnd ^= (rnd << 15) & 0xEFC60000u; + rnd ^= (rnd >> 18); + return rnd; + } + + }; + + template + struct RandomTraits<_Word, 64> { + + typedef _Word Word; + static const int bits = 64; + + static const int length = 312; + static const int shift = 156; + + static const Word mul = (Word)0x5851F42Du << 32 | (Word)0x4C957F2Du; + static const Word arrayInit = (Word)0x00000000u << 32 |(Word)0x012BD6AAu; + static const Word arrayMul1 = (Word)0x369DEA0Fu << 32 |(Word)0x31A53F85u; + static const Word arrayMul2 = (Word)0x27BB2EE6u << 32 |(Word)0x87B0B0FDu; + + static const Word mask = (Word)0xB5026F5Au << 32 | (Word)0xA96619E9u; + static const Word loMask = ((Word)1u << 31) - 1; + static const Word hiMask = ~loMask; + + static Word tempering(Word rnd) { + rnd ^= (rnd >> 29) & ((Word)0x55555555u << 32 | (Word)0x55555555u); + rnd ^= (rnd << 17) & ((Word)0x71D67FFFu << 32 | (Word)0xEDA60000u); + rnd ^= (rnd << 37) & ((Word)0xFFF7EEE0u << 32 | (Word)0x00000000u); + rnd ^= (rnd >> 43); + return rnd; + } + + }; + + template + class RandomCore { + public: + + typedef _Word Word; + + private: + + static const int bits = RandomTraits::bits; + + static const int length = RandomTraits::length; + static const int shift = RandomTraits::shift; + + public: + + void initState() { + static const Word seedArray[4] = { + 0x12345u, 0x23456u, 0x34567u, 0x45678u + }; + + initState(seedArray, seedArray + 4); + } + + void initState(Word seed) { + + static const Word mul = RandomTraits::mul; + + current = state; + + Word *curr = state + length - 1; + curr[0] = seed; --curr; + for (int i = 1; i < length; ++i) { + curr[0] = (mul * ( curr[1] ^ (curr[1] >> (bits - 2)) ) + i); + --curr; + } + } + + template + void initState(Iterator begin, Iterator end) { + + static const Word init = RandomTraits::arrayInit; + static const Word mul1 = RandomTraits::arrayMul1; + static const Word mul2 = RandomTraits::arrayMul2; + + + Word *curr = state + length - 1; --curr; + Iterator it = begin; int cnt = 0; + int num; + + initState(init); + + num = length > end - begin ? length : end - begin; + while (num--) { + curr[0] = (curr[0] ^ ((curr[1] ^ (curr[1] >> (bits - 2))) * mul1)) + + *it + cnt; + ++it; ++cnt; + if (it == end) { + it = begin; cnt = 0; + } + if (curr == state) { + curr = state + length - 1; curr[0] = state[0]; + } + --curr; + } + + num = length - 1; cnt = length - (curr - state) - 1; + while (num--) { + curr[0] = (curr[0] ^ ((curr[1] ^ (curr[1] >> (bits - 2))) * mul2)) + - cnt; + --curr; ++cnt; + if (curr == state) { + curr = state + length - 1; curr[0] = state[0]; --curr; + cnt = 1; + } + } + + state[length - 1] = (Word)1 << (bits - 1); + } + + void copyState(const RandomCore& other) { + std::copy(other.state, other.state + length, state); + current = state + (other.current - other.state); + } + + Word operator()() { + if (current == state) fillState(); + --current; + Word rnd = *current; + return RandomTraits::tempering(rnd); + } + + private: + + + void fillState() { + static const Word mask[2] = { 0x0ul, RandomTraits::mask }; + static const Word loMask = RandomTraits::loMask; + static const Word hiMask = RandomTraits::hiMask; + + current = state + length; + + register Word *curr = state + length - 1; + register long num; + + num = length - shift; + while (num--) { + curr[0] = (((curr[0] & hiMask) | (curr[-1] & loMask)) >> 1) ^ + curr[- shift] ^ mask[curr[-1] & 1ul]; + --curr; + } + num = shift - 1; + while (num--) { + curr[0] = (((curr[0] & hiMask) | (curr[-1] & loMask)) >> 1) ^ + curr[length - shift] ^ mask[curr[-1] & 1ul]; + --curr; + } + curr[0] = (((curr[0] & hiMask) | (curr[length - 1] & loMask)) >> 1) ^ + curr[length - shift] ^ mask[curr[length - 1] & 1ul]; + + } + + + Word *current; + Word state[length]; + + }; + + + template ::digits + 1) / 2> + struct Masker { + static Result mask(const Result& result) { + return Masker:: + mask((Result)(result | (result >> shift))); + } + }; + + template + struct Masker { + static Result mask(const Result& result) { + return (Result)(result | (result >> 1)); + } + }; + + template ::digits, int shift = 0, + bool last = rest <= std::numeric_limits::digits> + struct IntConversion { + static const int bits = std::numeric_limits::digits; + + static Result convert(RandomCore& rnd) { + return (Result)(rnd() >> (bits - rest)) << shift; + } + + }; + + template + struct IntConversion { + static const int bits = std::numeric_limits::digits; + + static Result convert(RandomCore& rnd) { + return ((Result)rnd() << shift) | + IntConversion::convert(rnd); + } + }; + + + template ::digits < + std::numeric_limits::digits> + struct Mapping { + static Result map(RandomCore& rnd, const Result& bound) { + Word max = (Word)(bound - 1); + Result mask = Masker::mask(bound - 1); + Result num; + do { + num = IntConversion::convert(rnd) & mask; + } while (num > max); + return num; + } + }; + + template + struct Mapping { + static Result map(RandomCore& rnd, const Result& bound) { + Word max = (Word)(bound - 1); + Word mask = Masker::digits + 1) / 2> + ::mask(max); + Word num; + do { + num = rnd() & mask; + } while (num > max); + return num; + } + }; + + template = 0)> + struct ShiftMultiplier { + static const Result multiplier() { + Result res = ShiftMultiplier::multiplier(); + res *= res; + if ((exp & 1) == 1) res *= (Result)2.0; + return res; + } + }; + + template + struct ShiftMultiplier { + static const Result multiplier() { + Result res = ShiftMultiplier::multiplier(); + res *= res; + if ((exp & 1) == 1) res *= (Result)0.5; + return res; + } + }; + + template + struct ShiftMultiplier { + static const Result multiplier() { + return (Result)1.0; + } + }; + + template + struct ShiftMultiplier { + static const Result multiplier() { + return (Result)(1.0/1048576.0); + } + }; + + template + struct ShiftMultiplier { + static const Result multiplier() { + return (Result)(1.0/424967296.0); + } + }; + + template + struct ShiftMultiplier { + static const Result multiplier() { + return (Result)(1.0/9007199254740992.0); + } + }; + + template + struct ShiftMultiplier { + static const Result multiplier() { + return (Result)(1.0/18446744073709551616.0); + } + }; + + template + struct Shifting { + static Result shift(const Result& result) { + return result * ShiftMultiplier::multiplier(); + } + }; + + template ::digits, int shift = 0, + bool last = rest <= std::numeric_limits::digits> + struct RealConversion{ + static const int bits = std::numeric_limits::digits; + + static Result convert(RandomCore& rnd) { + return Shifting:: + shift((Result)(rnd() >> (bits - rest))); + } + }; + + template + struct RealConversion { + static const int bits = std::numeric_limits::digits; + + static Result convert(RandomCore& rnd) { + return Shifting::shift((Result)rnd()) + + RealConversion::convert(rnd); + } + }; + + template + struct Initializer { + + template + static void init(RandomCore& rnd, Iterator begin, Iterator end) { + std::vector ws; + for (Iterator it = begin; it != end; ++it) { + ws.push_back((Word)*it); + } + rnd.initState(ws.begin(), ws.end()); + } + + template + static void init(RandomCore& rnd, Result seed) { + rnd.initState(seed); + } + }; + + template + struct BoolConversion { + static bool convert(RandomCore& rnd) { + return (rnd() & 1) == 1; + } + }; + + } /// \ingroup misc /// /// \brief Mersenne Twister random number generator /// /// The Mersenne Twister is a twisted generalized feedback - /// shift-register generator of Matsumoto and Nishimura. The period of - /// this generator is \f$ 2^{19937} - 1 \f$ and it is equi-distributed in - /// 623 dimensions. The time performance of this generator is comparable - /// to the commonly used generators. + /// shift-register generator of Matsumoto and Nishimura. The period + /// of this generator is \f$ 2^{19937} - 1 \f$ and it is + /// equi-distributed in 623 dimensions for 32-bit numbers. The time + /// performance of this generator is comparable to the commonly used + /// generators. + /// + /// This implementation is specialized for both 32-bit and 64-bit + /// architectures. The generators differ sligthly in the + /// initialization and generation phase so they produce two + /// completly different sequences. + /// + /// The generator gives back random numbers of serveral types. To + /// get a random number from a range of a floating point type you + /// can use one form of the \c operator(). If you want to get random + /// number from a the {0, 1, ..., n-1} integer range use the \c + /// operator[]. And to get random number from the whole range of an + /// integer type you can use the \c integer() or \c uinteger() + /// functions. After all you can get random bool with equal chance + /// or given probability with the \c boolean() member function. + /// + ///\code + /// int a = rnd[100000]; // 0..99999 + /// int b = rnd.uinteger(); // 0 .. 2^31 - 1 + /// int c = rnd.integer(); // - 2^31 .. 2^31 - 1 + /// double d = rnd(); // [0.0, 1.0) + /// double e = rnd(100.0); // [0.0, 100.0) + /// double f = rnd(1.0, 2.0); // [1.0, 2.0) + /// bool g = rnd.boolean(); // P(g = true) = 0.5 + /// bool h = rnd.boolean(0.8); // P(h = true) = 0.8 + ///\endcode + /// + /// The lemon provides a global instance of the random number generator + /// which name is \c rnd. Usually it is a good programming convenience + /// to use this global generator to get random numbers. /// /// \author Balazs Dezso class Random { + private: - static const int length = 624; - static const int shift = 397; +#if WORD_BIT == 32 + typedef unsigned int Word; +#elif WORD_BIT == 64 + typedef unsigned long Word; +#endif + + _random_bits::RandomCore core; public: - static const unsigned long min = 0ul; - static const unsigned long max = ~0ul; - /// \brief Constructor /// - /// Constructor with time dependent seeding. - Random() { initState(std::time(0)); } + /// Constructor with constant seeding. + Random() { core.initState(); } /// \brief Constructor /// - /// Constructor - Random(unsigned long seed) { initState(seed); } + /// Constructor with seed. The current number type will be converted + /// to the architecture word type. + template + Random(Number seed) { + _random_bits::Initializer::init(core, seed); + } + + /// \brief Constructor + /// + /// Constructor with array seeding. The given range should contain + /// any number type and the numbers will be converted to the + /// architecture word type. + template + Random(Iterator begin, Iterator end) { + typedef typename std::iterator_traits::value_type Number; + _random_bits::Initializer::init(core, begin, end); + } /// \brief Copy constructor /// /// Copy constructor. The generated sequence will be identical to /// the other sequence. - Random(const Random& other) { - std::copy(other.state, other.state + length, state); - current = state + (other.current - other.state); + Random(const Random& other) { + core.copyState(other.core); } /// \brief Assign operator @@ -81,429 +497,94 @@ /// the other sequence. Random& operator=(const Random& other) { if (&other != this) { - std::copy(other.state, other.state + length, state); - current = state + (other.current - other.state); + core.copyState(other.core); } return *this; } - /// \brief Returns an unsigned random number + /// \brief Returns a random real number /// - /// It returns an unsigned integer random number from the range - /// \f$ \{0, 1, \dots, 2^{32} - 1\} \f$. - unsigned long getUnsigned() { - if (current == state) fillState(); - --current; - unsigned long rnd = *current; - rnd ^= (rnd >> 11); - rnd ^= (rnd << 7) & 0x9D2C5680ul; - rnd ^= (rnd << 15) & 0xEFC60000ul; - rnd ^= (rnd >> 18); - return rnd; + /// It returns a random real number from the range [0, 1). The default + /// result type of this function is double. + template + Number operator()() { + return _random_bits::RealConversion::convert(core); } - /// \brief Returns a random number + double operator()() { + return operator()(); + } + + /// \brief Returns a random real number /// - /// It returns an integer random number from the range - /// \f$ \{-2^{31}, \dots, 2^{31} - 1\} \f$. - long getInt() { - return (long)getUnsigned(); + /// It returns a random real number from the range [0, b). + template + Number operator()(Number b) { + return operator()() * b; + } + + /// \brief Returns a random real number + /// + /// It returns a random real number from the range [a, b). + template + Number operator()(Number a, Number b) { + return operator()() * (b - a) + a; + } + + /// \brief Returns a random integer from a range + /// + /// It returns a random integer from the range {0, 1, ..., bound - 1}. + template + Number operator[](const Number& bound) { + return _random_bits::Mapping::map(core, bound); + } + + /// \brief Returns a random non-negative integer + /// + /// It returns a random non-negative integer uniformly from the + /// whole range of the current \c Number type. The default result + /// type of this function is unsigned int. + template + Number uinteger() { + return _random_bits::IntConversion::convert(core); + } + + unsigned int uinteger() { + return uinteger(); + } + + /// \brief Returns a random integer + /// + /// It returns a random integer uniformly from the whole range of + /// the current \c Number type. The default result type of this + /// function is int. + template + Number integer() { + static const int nb = std::numeric_limits::digits + + (std::numeric_limits::is_signed ? 1 : 0); + return _random_bits::IntConversion::convert(core); + } + + int integer() { + return integer(); } - /// \brief Returns an unsigned integer random number + /// \brief Returns a random bool /// - /// It returns an unsigned integer random number from the range - /// \f$ \{0, 1, \dots, 2^{31} - 1\} \f$. - long getNatural() { - return (long)(getUnsigned() >> 1); + /// It returns a random bool + bool boolean() { + return _random_bits::BoolConversion::convert(core); } /// \brief Returns a random bool /// - /// It returns a random bool. - bool getBool() { - return (bool)(getUnsigned() & 1); + /// It returns a random bool with given probability of true result + bool boolean(double p) { + return operator()() < p; } - - /// \brief Returns a real random number - /// - /// It returns a real random number from the range - /// \f$ [0, 1) \f$. The double will have 32 significant bits. - double getReal() { - return std::ldexp((double)getUnsigned(), -32); - } - - /// \brief Returns a real random number - /// - /// It returns a real random number from the range - /// \f$ [0, 1) \f$. The double will have 53 significant bits, - /// but it is slower than the \c getReal(). - double getPrecReal() { - return std::ldexp((double)(getUnsigned() >> 5), -27) + - std::ldexp((double)(getUnsigned() >> 6), -53); - } - - /// \brief Returns an unsigned random number from a given range - /// - /// It returns an unsigned integer random number from the range - /// \f$ \{0, 1, \dots, n - 1\} \f$. - unsigned long getUnsigned(unsigned long n) { - unsigned long mask = n - 1, rnd; - mask |= mask >> 1; - mask |= mask >> 2; - mask |= mask >> 4; - mask |= mask >> 8; - mask |= mask >> 16; - do rnd = getUnsigned() & mask; while (rnd >= n); - return rnd; - } - - /// \brief Returns a random number from a given range - /// - /// It returns an unsigned integer random number from the range - /// \f$ \{0, 1, \dots, n - 1\} \f$. - long getInt(long n) { - long mask = n - 1, rnd; - mask |= mask >> 1; - mask |= mask >> 2; - mask |= mask >> 4; - mask |= mask >> 8; - mask |= mask >> 16; - do rnd = getUnsigned() & mask; while (rnd >= n); - return rnd; - } - - private: - - void initState(unsigned long seed) { - static const unsigned long mul = 0x6c078965ul; - - current = state; - - unsigned long *curr = state + length - 1; - curr[0] = seed; --curr; - for (int i = 1; i < length; ++i) { - curr[0] = (mul * ( curr[1] ^ (curr[1] >> 30) ) + i); - --curr; - } - } - - void fillState() { - static const unsigned long mask[2] = { 0x0ul, 0x9908B0DFul }; - static const unsigned long loMask = (1ul << 31) - 1; - static const unsigned long hiMask = ~loMask; - - current = state + length; - - register unsigned long *curr = state + length - 1; - register long num; - - num = length - shift; - while (num--) { - curr[0] = (((curr[0] & hiMask) | (curr[-1] & loMask)) >> 1) ^ - curr[- shift] ^ mask[curr[-1] & 1ul]; - --curr; - } - num = shift - 1; - while (num--) { - curr[0] = (((curr[0] & hiMask) | (curr[-1] & loMask)) >> 1) ^ - curr[length - shift] ^ mask[curr[-1] & 1ul]; - --curr; - } - curr[0] = (((curr[0] & hiMask) | (curr[length - 1] & loMask)) >> 1) ^ - curr[length - shift] ^ mask[curr[length - 1] & 1ul]; - - } - - unsigned long *current; - unsigned long state[length]; }; -#elif WORD_BIT == 64 - - /// \ingroup misc - /// - /// \brief Mersenne Twister random number generator - /// - /// The Mersenne Twister is a twisted generalized feedback - /// shift-register generator of Matsumoto and Nishimura. The period of - /// this generator is \f$ 2^{19937} - 1 \f$ and it is equi-distributed in - /// 311 dimensions. The time performance of this generator is comparable - /// to the commonly used generators. - class Random { - - static const int length = 312; - static const int shift = 156; - - public: - - static const unsigned long min = 0ul; - static const unsigned long max = ~0ul; - - /// \brief Constructor - /// - /// Constructor with time dependent seeding. - Random() { initState(std::time(0)); } - - /// \brief Constructor - /// - /// Constructor - Random(unsigned long seed) { initState(seed); } - - /// \brief Copy constructor - /// - /// Copy constructor. The generated sequence will be identical to - /// the other sequence. - Random(const Random& other) { - std::copy(other.state, other.state + length, state); - current = state + (other.current - other.state); - } - - /// \brief Assign operator - /// - /// Assign operator. The generated sequence will be identical to - /// the other sequence. - Random& operator=(const Random& other) { - if (&other != this) { - std::copy(other.state, other.state + length, state); - current = state + (other.current - other.state); - } - return *this; - } - - /// \brief Returns an unsigned random number - /// - /// It returns an unsigned integer random number from the range - /// \f$ \{0, 1, \dots, 2^{64} - 1\} \f$. - unsigned long getUnsigned() { - if (current == state) fillState(); - --current; - unsigned long rnd = *current; - rnd ^= (rnd >> 29) & 0x5555555555555555ul; - rnd ^= (rnd << 17) & 0x71D67FFFEDA60000ul; - rnd ^= (rnd << 37) & 0xFFF7EEE000000000ul; - rnd ^= (rnd >> 43); - return rnd; - } - - /// \brief Returns a random number - /// - /// It returns an integer random number from the range - /// \f$ \{-2^{63}, \dots, 2^{63} - 1\} \f$. - long getInt() { - return (long)getUnsigned(); - } - - /// \brief Returns an unsigned integer random number - /// - /// It returns an unsigned integer random number from the range - /// \f$ \{0, 1, \dots, 2^{63} - 1\} \f$. - long getNatural() { - return (long)(getUnsigned() >> 1); - } - - /// \brief Returns a random bool - /// - /// It returns a random bool. - bool getBool() { - return (bool)(getUnsigned() & 1); - } - - /// \brief Returns a real random number - /// - /// It returns a real random number from the range - /// \f$ [0, 1) \f$. - double getReal() { - return std::ldexp((double)(getUnsigned() >> 11), -53); - } - - /// \brief Returns a real random number - /// - /// It returns a real random number from the range - /// \f$ [0, 1) \f$. This function is identical to the \c getReal(). - double getPrecReal() { - return getReal(); - } - - /// \brief Returns an unsigned random number from a given range - /// - /// It returns an unsigned integer random number from the range - /// \f$ \{0, 1, \dots, n - 1\} \f$. - unsigned long getUnsigned(unsigned long n) { - unsigned long mask = n - 1, rnd; - mask |= mask >> 1; - mask |= mask >> 2; - mask |= mask >> 4; - mask |= mask >> 8; - mask |= mask >> 16; - mask |= mask >> 32; - do rnd = getUnsigned() & mask; while (rnd >= n); - return rnd; - } - - /// \brief Returns a random number from a given range - /// - /// It returns an unsigned integer random number from the range - /// \f$ \{0, 1, \dots, n - 1\} \f$. - long getInt(long n) { - long mask = n - 1, rnd; - mask |= mask >> 1; - mask |= mask >> 2; - mask |= mask >> 4; - mask |= mask >> 8; - mask |= mask >> 16; - mask |= mask >> 32; - do rnd = getUnsigned() & mask; while (rnd >= n); - return rnd; - } - - private: - - void initState(unsigned long seed) { - - static const unsigned long mul = 0x5851F42D4C957F2Dul; - - current = state; - - unsigned long *curr = state + length - 1; - curr[0] = seed; --curr; - for (int i = 1; i < length; ++i) { - curr[0] = (mul * ( curr[1] ^ (curr[1] >> 62) ) + i); - --curr; - } - } - - void fillState() { - static const unsigned long mask[2] = { 0x0ul, 0xB5026F5AA96619E9ul }; - static const unsigned long loMask = (1ul << 31) - 1; - static const unsigned long hiMask = ~loMask; - - current = state + length; - - register unsigned long *curr = state + length - 1; - register int num; - - num = length - shift; - while (num--) { - curr[0] = (((curr[0] & hiMask) | (curr[-1] & loMask)) >> 1) ^ - curr[- shift] ^ mask[curr[-1] & 1ul]; - --curr; - } - num = shift - 1; - while (num--) { - curr[0] = (((curr[0] & hiMask) | (curr[-1] & loMask)) >> 1) ^ - curr[length - shift] ^ mask[curr[-1] & 1ul]; - --curr; - } - curr[0] = (((curr[0] & hiMask) | (curr[length - 1] & loMask)) >> 1) ^ - curr[length - shift] ^ mask[curr[length - 1] & 1ul]; - - } - - unsigned long *current; - unsigned long state[length]; - - }; - -#else - - /// \ingroup misc - /// - /// \brief Mersenne Twister random number generator - /// - /// The Mersenne Twister is a twisted generalized feedback - /// shift-register generator of Matsumoto and Nishimura. There is - /// two different implementation in the Lemon library, one for - /// 32-bit processors and one for 64-bit processors. The period of - /// the generated sequence is \f$ 2^{19937} - 1 \f$, the generated - /// sequence of 32-bit random numbers is equi-distributed in 623 - /// dimensions. The time performance of this generator is comparable - /// to the commonly used generators. - class Random { - public: - - static const unsigned long min = 0ul; - static const unsigned long max = ~0ul; - - /// \brief Constructor - /// - /// Constructor with time dependent seeding. - Random() {} - - /// \brief Constructor - /// - /// Constructor - Random(unsigned long seed) {} - - /// \brief Copy constructor - /// - /// Copy constructor. The generated sequence will be identical to - /// the other sequence. - Random(const Random& other) {} - - /// \brief Assign operator - /// - /// Assign operator. The generated sequence will be identical to - /// the other sequence. - Random& operator=(const Random& other) { return *this; } - - /// \brief Returns an unsigned random number - /// - /// It returns an unsigned integer random number from the range - /// \f$ \{0, 1, \dots, 2^{64} - 1\} \f$ for 64-bit processors and from - /// \f$ \{0, 1, \dots, 2^{32} - 1\} \f$ for 32-bit processors. - unsigned long getUnsigned() { return 0ul; } - - /// \brief Returns a random number - /// - /// It returns an integer random number from the range - /// \f$ \{-2^{63}, \dots, 2^{63} - 1\} \f$ for 64-bit processors and from - /// \f$ \{-2^{31}, \dots, 2^{31} - 1\} \f$ for 32-bit processors. - long getInt() { return 0l; } - - /// \brief Returns an unsigned integer random number - /// - /// It returns an unsigned integer random number from the range - /// \f$ \{0, 1, \dots, 2^{63} - 1\} \f$ for 64-bit processors and - /// from \f$ \{0, 1, \dots, 2^{31} - 1\} \f$ for 32-bit processors. - long getNatural() { return 0l; } - - /// \brief Returns a random bool - /// - /// It returns a random bool. - bool getBool() { return false; } - - /// \brief Returns a real random number - /// - /// It returns a real random number from the range - /// \f$ [0, 1) \f$. For 32-bit processors the generated random - /// number will just have 32 significant bits. - double getReal() { return 0.0; } - - /// \brief Returns a real random number - /// - /// It returns a real random number from the range - /// \f$ [0, 1) \f$. This function returns random numbers with 53 - /// significant bits for 32-bit processors. For 64-bit processors - /// it is identical to the \c getReal(). - double getPrecReal() { return 0.0; } - - /// \brief Returns an unsigned random number from a given range - /// - /// It returns an unsigned integer random number from the range - /// \f$ \{0, 1, \dots, n - 1\} \f$. - unsigned long getUnsigned(unsigned long n) { return 0; } - - /// \brief Returns a random number from a given range - /// - /// It returns an unsigned integer random number from the range - /// \f$ \{0, 1, \dots, n - 1\} \f$. - long getInt(long n) { return 0; } - - }; - -#endif /// \brief Global random number generator instance /// diff -r 37e0966e43b6 -r 16523135943d lemon/simann.h --- a/lemon/simann.h Fri Oct 13 15:10:50 2006 +0000 +++ b/lemon/simann.h Sat Oct 14 15:26:05 2006 +0000 @@ -257,7 +257,7 @@ /// \brief Decides whether to accept the current solution or not. bool accept() { double cost_diff = simann->getCurrCost() - simann->getPrevCost(); - return (rnd.getReal() <= exp(-(cost_diff / temp))); + return (rnd() <= exp(-(cost_diff / temp))); } /// \brief Destructor. virtual ~SimpleController() {} @@ -365,7 +365,7 @@ } else { double cost_diff = simann->getCurrCost() - simann->getPrevCost(); - return (rnd.getReal() <= exp(-(cost_diff / temp))); + return (rnd() <= exp(-(cost_diff / temp))); } } /// \brief Destructor. diff -r 37e0966e43b6 -r 16523135943d test/all_pairs_shortest_path_test.cc --- a/test/all_pairs_shortest_path_test.cc Fri Oct 13 15:10:50 2006 +0000 +++ b/test/all_pairs_shortest_path_test.cc Sat Oct 14 15:26:05 2006 +0000 @@ -36,19 +36,18 @@ using namespace std; int main(int argc, const char *argv[]) { - srand(time(0)); typedef SmartGraph Graph; typedef Graph::Node Node; typedef Graph::Edge Edge; typedef Graph::NodeIt NodeIt; typedef Graph::EdgeIt EdgeIt; - typedef Graph::EdgeMap LengthMap; - typedef Graph::NodeMap DistMap; + typedef Graph::EdgeMap LengthMap; + typedef Graph::NodeMap DistMap; const int n = argc > 1 ? atoi(argv[1]) : 20; const int e = argc > 2 ? atoi(argv[2]) : (int)(n * log((double)n)); - const double m = argc > 3 ? (double)atoi(argv[3]) : 100.0; + const int m = argc > 3 ? atoi(argv[3]) : 100; Graph graph; LengthMap length(graph); @@ -58,15 +57,14 @@ for (int i = 0; i < n; ++i) { Node node = graph.addNode(); nodes.push_back(node); - shift[node] = m * (double)rand() / (RAND_MAX + 1.0); + shift[node] = rnd[m]; } for (int i = 0; i < e; ++i) { - int s = (int)(n * (double)rand() / (RAND_MAX + 1.0)); - int t = (int)(n * (double)rand() / (RAND_MAX + 1.0)); - double c = m * (double)rand() / (RAND_MAX + 1.0); + int s = rnd[n]; + int t = rnd[n]; Edge edge = graph.addEdge(nodes[s], nodes[t]); - length[edge] = c - shift[nodes[s]] + shift[nodes[t]]; + length[edge] = rnd[m] - shift[nodes[s]] + shift[nodes[t]]; } Johnson johnson(graph, length); @@ -76,8 +74,8 @@ cout << "Johnson: " << timer << endl; } - typedef FibHeap > DoubleFibHeap; - Johnson::DefStandardHeap + typedef FibHeap > IntFibHeap; + Johnson::DefStandardHeap ::Create fibJohnson(graph, length); { Timer timer; diff -r 37e0966e43b6 -r 16523135943d test/arborescence_test.cc --- a/test/arborescence_test.cc Fri Oct 13 15:10:50 2006 +0000 +++ b/test/arborescence_test.cc Sat Oct 14 15:26:05 2006 +0000 @@ -47,7 +47,6 @@ int main() { - srand(time(0)); typedef SmartGraph Graph; GRAPH_TYPEDEFS(Graph); diff -r 37e0966e43b6 -r 16523135943d test/graph_utils_test.cc --- a/test/graph_utils_test.cc Fri Oct 13 15:10:50 2006 +0000 +++ b/test/graph_utils_test.cc Sat Oct 14 15:26:05 2006 +0000 @@ -116,7 +116,7 @@ std::vector edges(edgeNum); for (int i = 0; i < edgeNum; ++i) { edges[i] = - graph.addEdge(nodes[urandom(nodeNum)], nodes[urandom(nodeNum)]); + graph.addEdge(nodes[rnd[nodeNum]], nodes[rnd[nodeNum]]); } for (int i = 0; i < nodeNum; ++i) { check(inDeg[nodes[i]] == countInEdges(graph, nodes[i]), diff -r 37e0966e43b6 -r 16523135943d test/graph_utils_test.h --- a/test/graph_utils_test.h Fri Oct 13 15:10:50 2006 +0000 +++ b/test/graph_utils_test.h Sat Oct 14 15:26:05 2006 +0000 @@ -56,8 +56,8 @@ DescriptorMap nodes(graph); typename DescriptorMap::InverseMap invNodes(nodes); for (int i = 0; i < 100; ++i) { - int src = rnd.getInt(invNodes.size()); - int trg = rnd.getInt(invNodes.size()); + int src = rnd[invNodes.size()]; + int trg = rnd[invNodes.size()]; graph.addEdge(invNodes[src], invNodes[trg]); } typename Graph::template EdgeMap found(graph, false); diff -r 37e0966e43b6 -r 16523135943d test/heap_test.h --- a/test/heap_test.h Fri Oct 13 15:10:50 2006 +0000 +++ b/test/heap_test.h Sat Oct 14 15:26:05 2006 +0000 @@ -45,7 +45,7 @@ std::vector v(n); for (int i = 0; i < n; ++i) { - v[i] = rnd.getInt(1000); + v[i] = rnd[1000]; heap.push(i, v[i]); } std::sort(v.begin(), v.end()); @@ -65,11 +65,11 @@ std::vector v(n); for (int i = 0; i < n; ++i) { - v[i] = rnd.getInt(1000); + v[i] = rnd[1000]; heap.push(i, v[i]); } for (int i = 0; i < n; ++i) { - v[i] += rnd.getInt(1000); + v[i] += rnd[1000]; heap.increase(i, v[i]); } std::sort(v.begin(), v.end()); diff -r 37e0966e43b6 -r 16523135943d test/matrix_maps_test.cc --- a/test/matrix_maps_test.cc Fri Oct 13 15:10:50 2006 +0000 +++ b/test/matrix_maps_test.cc Sat Oct 14 15:26:05 2006 +0000 @@ -67,7 +67,7 @@ } for (Graph::NodeIt it(graph); it != INVALID; ++it) { for (Graph::NodeIt jt(graph); jt != INVALID; ++jt) { - int val = urandom(100); + int val = rnd[100]; matrix.set(it, jt, val); check(matrix(it, jt) == val, "Wrong assign"); check(matrix(it, jt) == matrixRowMap(matrix, it)[jt], "Wrong rowMap"); @@ -108,7 +108,7 @@ } for (Graph::NodeIt it(graph); it != INVALID; ++it) { for (Graph::NodeIt jt(graph); jt != INVALID; ++jt) { - int val = urandom(100); + int val = rnd[100]; matrix.set(it, jt, val); check(matrix(it, jt) == val, "Wrong assign"); check(matrix(jt, it) == val, "Wrong assign"); @@ -154,7 +154,7 @@ } for (Graph::NodeIt it(graph1); it != INVALID; ++it) { for (Graph::EdgeIt jt(graph2); jt != INVALID; ++jt) { - int val = urandom(100); + int val = rnd[100]; matrix.set(it, jt, val); check(matrix(it, jt) == val, "Wrong assign"); check(matrix(it, jt) == matrixRowMap(matrix, it)[jt], "Wrong rowMap"); @@ -198,7 +198,7 @@ } for (Graph::NodeIt it(graph); it != INVALID; ++it) { for (Graph::NodeIt jt(graph); jt != INVALID; ++jt) { - int val = urandom(100); + int val = rnd[100]; matrix.set(it, jt, val); check(matrix(it, jt) == val, "Wrong assign"); check(matrix(it, jt) == matrixRowMap(matrix, it)[jt], "Wrong rowMap"); diff -r 37e0966e43b6 -r 16523135943d test/radix_sort_test.cc --- a/test/radix_sort_test.cc Fri Oct 13 15:10:50 2006 +0000 +++ b/test/radix_sort_test.cc Sat Oct 14 15:26:05 2006 +0000 @@ -37,7 +37,7 @@ int n = 10000; vector data1(n), data2(n); for (int i = 0; i < n; ++i) { - data1[i] = data2[i] = (int)(1000 * (rand() / (RAND_MAX + 1.0))) - 500; + data1[i] = data2[i] = rnd[1000] - 500; } radixSort(data1.begin(), data1.end()); sort(data2.begin(), data2.end()); @@ -48,7 +48,7 @@ int n = 10000; vector data1(n), data2(n); for (int i = 0; i < n; ++i) { - data1[i] = data2[i] = (int)(200 * (rand() / (RAND_MAX + 1.0))); + data1[i] = data2[i] = rnd[(unsigned char)200]; } radixSort(data1.begin(), data1.end()); sort(data2.begin(), data2.end()); @@ -64,7 +64,7 @@ int n = 10000; vector data1(n), data2(n); for (int i = 0; i < n; ++i) { - data1[i] = data2[i] = (int)(1000 * (rand() / (RAND_MAX + 1.0))) - 500; + data1[i] = data2[i] = rnd[1000] - 500; } counterSort(data1.begin(), data1.end()); sort(data2.begin(), data2.end()); @@ -75,7 +75,7 @@ int n = 10000; vector data1(n), data2(n); for (int i = 0; i < n; ++i) { - data1[i] = data2[i] = (int)(200 * (rand() / (RAND_MAX + 1.0))); + data1[i] = data2[i] = rnd[(unsigned char)200]; } counterSort(data1.begin(), data1.end()); sort(data2.begin(), data2.end()); @@ -106,8 +106,8 @@ } vector edges; for (int i = 0; i < e; ++i) { - int s = (int)(n * (double)rand() / (RAND_MAX + 1.0)); - int t = (int)(n * (double)rand() / (RAND_MAX + 1.0)); + int s = rnd[n]; + int t = rnd[n]; edges.push_back(graph.addEdge(nodes[s], nodes[t])); } @@ -145,8 +145,8 @@ } vector edges; for (int i = 0; i < e; ++i) { - int s = (int)(n * (double)rand() / (RAND_MAX + 1.0)); - int t = (int)(n * (double)rand() / (RAND_MAX + 1.0)); + int s = rnd[n]; + int t = rnd[n]; edges.push_back(graph.addEdge(nodes[s], nodes[t])); } diff -r 37e0966e43b6 -r 16523135943d test/simann_test.cc --- a/test/simann_test.cc Fri Oct 13 15:10:50 2006 +0000 +++ b/test/simann_test.cc Sat Oct 14 15:26:05 2006 +0000 @@ -23,10 +23,10 @@ class MyEntity : public EntityBase { public: double d, prev_d; - MyEntity() : d(100000.0) { srand48(time(0)); } + MyEntity() : d(100000.0) {} double mutate() { prev_d = d; - if (drand48() < 0.8) { d += 1.0; } + if (rnd.boolean(0.8)) { d += 1.0; } else { d -= 1.0; } return d; } diff -r 37e0966e43b6 -r 16523135943d test/test_tools.h --- a/test/test_tools.h Fri Oct 13 15:10:50 2006 +0000 +++ b/test/test_tools.h Sat Oct 14 15:26:05 2006 +0000 @@ -174,12 +174,8 @@ n.chords.push_back(G.addEdge(n.outer[i],n.inner[i])); n.outcir.push_back(G.addEdge(n.outer[i],n.outer[(i+1)%5])); n.incir.push_back(G.addEdge(n.inner[i],n.inner[(i+2)%5])); - } + } return n; } -int urandom(int n) { - return rnd.getInt(n); -} - #endif