random.hh revision 7771
12SN/A/*
21762SN/A * Copyright (c) 2003-2005 The Regents of The University of Michigan
32SN/A * All rights reserved.
42SN/A *
52SN/A * Redistribution and use in source and binary forms, with or without
62SN/A * modification, are permitted provided that the following conditions are
72SN/A * met: redistributions of source code must retain the above copyright
82SN/A * notice, this list of conditions and the following disclaimer;
92SN/A * redistributions in binary form must reproduce the above copyright
102SN/A * notice, this list of conditions and the following disclaimer in the
112SN/A * documentation and/or other materials provided with the distribution;
122SN/A * neither the name of the copyright holders nor the names of its
132SN/A * contributors may be used to endorse or promote products derived from
142SN/A * this software without specific prior written permission.
152SN/A *
162SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
172SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
182SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
192SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
202SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
212SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
222SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
232SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
242SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
252SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
262SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
272665Ssaidi@eecs.umich.edu *
282665Ssaidi@eecs.umich.edu * Authors: Nathan Binkert
292665Ssaidi@eecs.umich.edu *          Ali Saidi
302SN/A */
312SN/A
327771Snate@binkert.org/*
337771Snate@binkert.org * Mersenne Twister random number generator has a period of
347771Snate@binkert.org * 2^19937-1.
357771Snate@binkert.org *
367771Snate@binkert.org * The actual math is in its own file to keep the license clear.
377771Snate@binkert.org */
387771Snate@binkert.org
391296SN/A#ifndef __BASE_RANDOM_HH__
401296SN/A#define __BASE_RANDOM_HH__
412SN/A
425190Ssaidi@eecs.umich.edu#include <ios>
435190Ssaidi@eecs.umich.edu#include <string>
445190Ssaidi@eecs.umich.edu
455190Ssaidi@eecs.umich.edu#include "base/range.hh"
466214Snate@binkert.org#include "base/types.hh"
472SN/A
485190Ssaidi@eecs.umich.educlass Checkpoint;
492SN/A
505190Ssaidi@eecs.umich.educlass Random
515190Ssaidi@eecs.umich.edu{
525190Ssaidi@eecs.umich.edu  protected:
535190Ssaidi@eecs.umich.edu    static const int N = 624;
545190Ssaidi@eecs.umich.edu    static const int M = 397;
555190Ssaidi@eecs.umich.edu    static const uint32_t MATRIX_A = (uint32_t)0x9908b0df;
565190Ssaidi@eecs.umich.edu    static const uint32_t UPPER_MASK = (uint32_t)0x80000000;
575190Ssaidi@eecs.umich.edu    static const uint32_t LOWER_MASK = (uint32_t)0x7fffffff;
582SN/A
595190Ssaidi@eecs.umich.edu    uint32_t mt[N];
605190Ssaidi@eecs.umich.edu    int mti;
611954SN/A
625190Ssaidi@eecs.umich.edu    uint32_t genrand();
635190Ssaidi@eecs.umich.edu    uint32_t genrand(uint32_t max);
645190Ssaidi@eecs.umich.edu    uint64_t genrand(uint64_t max);
655190Ssaidi@eecs.umich.edu
665190Ssaidi@eecs.umich.edu    void
675190Ssaidi@eecs.umich.edu    _random(int8_t &value)
685190Ssaidi@eecs.umich.edu    {
695190Ssaidi@eecs.umich.edu        value = genrand() & (int8_t)-1;
705190Ssaidi@eecs.umich.edu    }
715190Ssaidi@eecs.umich.edu
725190Ssaidi@eecs.umich.edu    void
735190Ssaidi@eecs.umich.edu    _random(int16_t &value)
745190Ssaidi@eecs.umich.edu    {
755190Ssaidi@eecs.umich.edu        value = genrand() & (int16_t)-1;
765190Ssaidi@eecs.umich.edu    }
775190Ssaidi@eecs.umich.edu
785190Ssaidi@eecs.umich.edu    void
795190Ssaidi@eecs.umich.edu    _random(int32_t &value)
805190Ssaidi@eecs.umich.edu    {
815190Ssaidi@eecs.umich.edu        value = (int32_t)genrand();
825190Ssaidi@eecs.umich.edu    }
835190Ssaidi@eecs.umich.edu
845190Ssaidi@eecs.umich.edu    void
855190Ssaidi@eecs.umich.edu    _random(int64_t &value)
865190Ssaidi@eecs.umich.edu    {
875190Ssaidi@eecs.umich.edu        value = (int64_t)genrand() << 32 | (int64_t)genrand();
885190Ssaidi@eecs.umich.edu    }
895190Ssaidi@eecs.umich.edu
905190Ssaidi@eecs.umich.edu    void
915190Ssaidi@eecs.umich.edu    _random(uint8_t &value)
925190Ssaidi@eecs.umich.edu    {
935190Ssaidi@eecs.umich.edu        value = genrand() & (uint8_t)-1;
945190Ssaidi@eecs.umich.edu    }
955190Ssaidi@eecs.umich.edu
965190Ssaidi@eecs.umich.edu    void
975190Ssaidi@eecs.umich.edu    _random(uint16_t &value)
985190Ssaidi@eecs.umich.edu    {
995190Ssaidi@eecs.umich.edu        value = genrand() & (uint16_t)-1;
1005190Ssaidi@eecs.umich.edu    }
1015190Ssaidi@eecs.umich.edu
1025190Ssaidi@eecs.umich.edu    void
1035190Ssaidi@eecs.umich.edu    _random(uint32_t &value)
1045190Ssaidi@eecs.umich.edu    {
1055190Ssaidi@eecs.umich.edu        value = genrand();
1065190Ssaidi@eecs.umich.edu    }
1075190Ssaidi@eecs.umich.edu
1085190Ssaidi@eecs.umich.edu    void
1095190Ssaidi@eecs.umich.edu    _random(uint64_t &value)
1105190Ssaidi@eecs.umich.edu    {
1115190Ssaidi@eecs.umich.edu        value = (uint64_t)genrand() << 32 | (uint64_t)genrand();
1125190Ssaidi@eecs.umich.edu    }
1135190Ssaidi@eecs.umich.edu
1145190Ssaidi@eecs.umich.edu    // [0,1]
1155190Ssaidi@eecs.umich.edu    void
1165190Ssaidi@eecs.umich.edu    _random(float &value)
1175190Ssaidi@eecs.umich.edu    {
1185190Ssaidi@eecs.umich.edu        // ieee floats have 23 bits of mantissa
1195190Ssaidi@eecs.umich.edu        value = (genrand() >> 9) / 8388608.0;
1205190Ssaidi@eecs.umich.edu    }
1215190Ssaidi@eecs.umich.edu
1225190Ssaidi@eecs.umich.edu    // [0,1]
1235190Ssaidi@eecs.umich.edu    void
1245190Ssaidi@eecs.umich.edu    _random(double &value)
1255190Ssaidi@eecs.umich.edu    {
1265190Ssaidi@eecs.umich.edu        double number = genrand() * 2097152.0 + (genrand() >> 11);
1275190Ssaidi@eecs.umich.edu        value = number / 9007199254740992.0;
1285190Ssaidi@eecs.umich.edu    }
1295190Ssaidi@eecs.umich.edu
1305190Ssaidi@eecs.umich.edu
1315190Ssaidi@eecs.umich.edu    // Range based versions of the random number generator
1325190Ssaidi@eecs.umich.edu    int8_t
1335190Ssaidi@eecs.umich.edu    _random(int8_t min, int8_t max)
1345190Ssaidi@eecs.umich.edu    {
1355190Ssaidi@eecs.umich.edu        uint32_t diff = max - min;
1365190Ssaidi@eecs.umich.edu        return static_cast<int8_t>(min + genrand(diff));
1375190Ssaidi@eecs.umich.edu    }
1385190Ssaidi@eecs.umich.edu
1395190Ssaidi@eecs.umich.edu    int16_t
1405190Ssaidi@eecs.umich.edu    _random(int16_t min, int16_t max)
1415190Ssaidi@eecs.umich.edu    {
1425190Ssaidi@eecs.umich.edu        uint32_t diff = max - min;
1435190Ssaidi@eecs.umich.edu        return static_cast<int16_t>(min + genrand(diff));
1445190Ssaidi@eecs.umich.edu    }
1455190Ssaidi@eecs.umich.edu
1465190Ssaidi@eecs.umich.edu    int32_t
1475190Ssaidi@eecs.umich.edu    _random(int32_t min, int32_t max)
1485190Ssaidi@eecs.umich.edu    {
1495190Ssaidi@eecs.umich.edu        uint32_t diff = max - min;
1505190Ssaidi@eecs.umich.edu        return static_cast<int32_t>(min + genrand(diff));
1515190Ssaidi@eecs.umich.edu    }
1525190Ssaidi@eecs.umich.edu
1535190Ssaidi@eecs.umich.edu    int64_t
1545190Ssaidi@eecs.umich.edu    _random(int64_t min, int64_t max)
1555190Ssaidi@eecs.umich.edu    {
1565190Ssaidi@eecs.umich.edu        uint64_t diff = max - min;
1575190Ssaidi@eecs.umich.edu        return static_cast<int64_t>(min + genrand(diff));
1585190Ssaidi@eecs.umich.edu    }
1595190Ssaidi@eecs.umich.edu
1605190Ssaidi@eecs.umich.edu    uint8_t
1615190Ssaidi@eecs.umich.edu    _random(uint8_t min, uint8_t max)
1625190Ssaidi@eecs.umich.edu    {
1635190Ssaidi@eecs.umich.edu        uint32_t diff = max - min;
1645190Ssaidi@eecs.umich.edu        return static_cast<uint8_t>(min + genrand(diff));
1655190Ssaidi@eecs.umich.edu    }
1665190Ssaidi@eecs.umich.edu
1675190Ssaidi@eecs.umich.edu    uint16_t
1685190Ssaidi@eecs.umich.edu    _random(uint16_t min, uint16_t max)
1695190Ssaidi@eecs.umich.edu    {
1705190Ssaidi@eecs.umich.edu        uint32_t diff = max - min;
1715190Ssaidi@eecs.umich.edu        return static_cast<uint16_t>(min + genrand(diff));
1725190Ssaidi@eecs.umich.edu    }
1735190Ssaidi@eecs.umich.edu
1745190Ssaidi@eecs.umich.edu    uint32_t
1755190Ssaidi@eecs.umich.edu    _random(uint32_t min, uint32_t max)
1765190Ssaidi@eecs.umich.edu    {
1775190Ssaidi@eecs.umich.edu        uint32_t diff = max - min;
1785190Ssaidi@eecs.umich.edu        return static_cast<uint32_t>(min + genrand(diff));
1795190Ssaidi@eecs.umich.edu    }
1805190Ssaidi@eecs.umich.edu
1815190Ssaidi@eecs.umich.edu    uint64_t
1825190Ssaidi@eecs.umich.edu    _random(uint64_t min, uint64_t max)
1835190Ssaidi@eecs.umich.edu    {
1845190Ssaidi@eecs.umich.edu        uint64_t diff = max - min;
1855190Ssaidi@eecs.umich.edu        return static_cast<uint64_t>(min + genrand(diff));
1865190Ssaidi@eecs.umich.edu    }
1875190Ssaidi@eecs.umich.edu
1885190Ssaidi@eecs.umich.edu  public:
1895190Ssaidi@eecs.umich.edu    Random();
1905190Ssaidi@eecs.umich.edu    Random(uint32_t s);
1915190Ssaidi@eecs.umich.edu    Random(uint32_t init_key[], int key_length);
1925190Ssaidi@eecs.umich.edu    ~Random();
1935190Ssaidi@eecs.umich.edu
1945190Ssaidi@eecs.umich.edu    void init(uint32_t s);
1955190Ssaidi@eecs.umich.edu    void init(uint32_t init_key[], int key_length);
1965190Ssaidi@eecs.umich.edu
1975190Ssaidi@eecs.umich.edu    template <typename T>
1985190Ssaidi@eecs.umich.edu    T
1995190Ssaidi@eecs.umich.edu    random()
2005190Ssaidi@eecs.umich.edu    {
2015190Ssaidi@eecs.umich.edu        T value;
2025190Ssaidi@eecs.umich.edu        _random(value);
2035190Ssaidi@eecs.umich.edu        return value;
2045190Ssaidi@eecs.umich.edu    }
2055190Ssaidi@eecs.umich.edu
2065190Ssaidi@eecs.umich.edu    template <typename T>
2075190Ssaidi@eecs.umich.edu    T
2085190Ssaidi@eecs.umich.edu    random(T min, T max)
2095190Ssaidi@eecs.umich.edu    {
2105190Ssaidi@eecs.umich.edu        return _random(min, max);
2115190Ssaidi@eecs.umich.edu    }
2125190Ssaidi@eecs.umich.edu
2135190Ssaidi@eecs.umich.edu    template <typename T>
2145190Ssaidi@eecs.umich.edu    T
2155190Ssaidi@eecs.umich.edu    random(const Range<T> &range)
2165190Ssaidi@eecs.umich.edu    {
2175190Ssaidi@eecs.umich.edu        return _random(range.start, range.end);
2185190Ssaidi@eecs.umich.edu    }
2195190Ssaidi@eecs.umich.edu
2205190Ssaidi@eecs.umich.edu    // [0,1]
2215190Ssaidi@eecs.umich.edu    double
2225190Ssaidi@eecs.umich.edu    gen_real1()
2235190Ssaidi@eecs.umich.edu    {
2245190Ssaidi@eecs.umich.edu        return genrand() / 4294967296.0;
2255190Ssaidi@eecs.umich.edu    }
2265190Ssaidi@eecs.umich.edu
2275190Ssaidi@eecs.umich.edu    // [0,1)
2285190Ssaidi@eecs.umich.edu    double
2295190Ssaidi@eecs.umich.edu    gen_real2()
2305190Ssaidi@eecs.umich.edu    {
2315190Ssaidi@eecs.umich.edu        return genrand() / 4294967295.0;
2325190Ssaidi@eecs.umich.edu    }
2335190Ssaidi@eecs.umich.edu
2345190Ssaidi@eecs.umich.edu    // (0,1)
2355190Ssaidi@eecs.umich.edu    double
2365190Ssaidi@eecs.umich.edu    gen_real3()
2375190Ssaidi@eecs.umich.edu    {
2385190Ssaidi@eecs.umich.edu        return ((double)genrand() + 0.5) / 4294967296.0;
2395190Ssaidi@eecs.umich.edu    }
2405190Ssaidi@eecs.umich.edu
2415190Ssaidi@eecs.umich.edu  public:
2425190Ssaidi@eecs.umich.edu    void serialize(const std::string &base, std::ostream &os);
2435190Ssaidi@eecs.umich.edu    void unserialize(const std::string &base, Checkpoint *cp,
2445190Ssaidi@eecs.umich.edu                     const std::string &section);
2452SN/A};
2462SN/A
2475190Ssaidi@eecs.umich.eduextern Random random_mt;
2482SN/A
2491296SN/A#endif // __BASE_RANDOM_HH__
250