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 §ion); 2452SN/A}; 2462SN/A 2475190Ssaidi@eecs.umich.eduextern Random random_mt; 2482SN/A 2491296SN/A#endif // __BASE_RANDOM_HH__ 250