| 1 |
// -*- C++ -*- |
| 2 |
|
| 3 |
// Copyright (C) 2007-2021 Free Software Foundation, Inc. |
| 4 |
// |
| 5 |
// This file is part of the GNU ISO C++ Library. This library is free |
| 6 |
// software; you can redistribute it and/or modify it under the terms |
| 7 |
// of the GNU General Public License as published by the Free Software |
| 8 |
// Foundation; either version 3, or (at your option) any later |
| 9 |
// version. |
| 10 |
|
| 11 |
// This library is distributed in the hope that it will be useful, but |
| 12 |
// WITHOUT ANY WARRANTY; without even the implied warranty of |
| 13 |
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| 14 |
// General Public License for more details. |
| 15 |
|
| 16 |
// Under Section 7 of GPL version 3, you are granted additional |
| 17 |
// permissions described in the GCC Runtime Library Exception, version |
| 18 |
// 3.1, as published by the Free Software Foundation. |
| 19 |
|
| 20 |
// You should have received a copy of the GNU General Public License and |
| 21 |
// a copy of the GCC Runtime Library Exception along with this program; |
| 22 |
// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see |
| 23 |
// <http://www.gnu.org/licenses/>. |
| 24 |
|
| 25 |
/** @file parallel/random_number.h |
| 26 |
* @brief Random number generator based on the Mersenne twister. |
| 27 |
* This file is a GNU parallel extension to the Standard C++ Library. |
| 28 |
*/ |
| 29 |
|
| 30 |
// Written by Johannes Singler. |
| 31 |
|
| 32 |
#ifndef _GLIBCXX_PARALLEL_RANDOM_NUMBER_H |
| 33 |
#define _GLIBCXX_PARALLEL_RANDOM_NUMBER_H 1 |
| 34 |
|
| 35 |
#include <parallel/types.h> |
| 36 |
#include <tr1/random> |
| 37 |
#include <limits> |
| 38 |
|
| 39 |
namespace __gnu_parallel |
| 40 |
{ |
| 41 |
/** @brief Random number generator, based on the Mersenne twister. */ |
| 42 |
class _RandomNumber |
| 43 |
{ |
| 44 |
private: |
| 45 |
std::tr1::mt19937 _M_mt; |
| 46 |
uint64_t _M_supremum; |
| 47 |
uint64_t _M_rand_sup; |
| 48 |
double _M_supremum_reciprocal; |
| 49 |
double _M_rand_sup_reciprocal; |
| 50 |
|
| 51 |
// Assumed to be twice as long as the usual random number. |
| 52 |
uint64_t __cache; |
| 53 |
|
| 54 |
// Bit results. |
| 55 |
int __bits_left; |
| 56 |
|
| 57 |
static uint32_t |
| 58 |
__scale_down(uint64_t __x, |
| 59 |
#if _GLIBCXX_SCALE_DOWN_FPU |
| 60 |
uint64_t /*_M_supremum*/, double _M_supremum_reciprocal) |
| 61 |
#else |
| 62 |
uint64_t _M_supremum, double /*_M_supremum_reciprocal*/) |
| 63 |
#endif |
| 64 |
{ |
| 65 |
#if _GLIBCXX_SCALE_DOWN_FPU |
| 66 |
return uint32_t(__x * _M_supremum_reciprocal); |
| 67 |
#else |
| 68 |
return static_cast<uint32_t>(__x % _M_supremum); |
| 69 |
#endif |
| 70 |
} |
| 71 |
|
| 72 |
public: |
| 73 |
/** @brief Default constructor. Seed with 0. */ |
| 74 |
_RandomNumber() |
| 75 |
: _M_mt(0), _M_supremum(0x100000000ULL), |
| 76 |
_M_rand_sup(1ULL << std::numeric_limits<uint32_t>::digits), |
| 77 |
_M_supremum_reciprocal(double(_M_supremum) / double(_M_rand_sup)), |
| 78 |
_M_rand_sup_reciprocal(1.0 / double(_M_rand_sup)), |
| 79 |
__cache(0), __bits_left(0) { } |
| 80 |
|
| 81 |
/** @brief Constructor. |
| 82 |
* @param __seed Random __seed. |
| 83 |
* @param _M_supremum Generate integer random numbers in the |
| 84 |
* interval @c [0,_M_supremum). */ |
| 85 |
_RandomNumber(uint32_t __seed, uint64_t _M_supremum = 0x100000000ULL) |
| 86 |
: _M_mt(__seed), _M_supremum(_M_supremum), |
| 87 |
_M_rand_sup(1ULL << std::numeric_limits<uint32_t>::digits), |
| 88 |
_M_supremum_reciprocal(double(_M_supremum) / double(_M_rand_sup)), |
| 89 |
_M_rand_sup_reciprocal(1.0 / double(_M_rand_sup)), |
| 90 |
__cache(0), __bits_left(0) { } |
| 91 |
|
| 92 |
/** @brief Generate unsigned random 32-bit integer. */ |
| 93 |
uint32_t |
| 94 |
operator()() |
| 95 |
{ return __scale_down(_M_mt(), _M_supremum, _M_supremum_reciprocal); } |
| 96 |
|
| 97 |
/** @brief Generate unsigned random 32-bit integer in the |
| 98 |
interval @c [0,local_supremum). */ |
| 99 |
uint32_t |
| 100 |
operator()(uint64_t local_supremum) |
| 101 |
{ |
| 102 |
return __scale_down(_M_mt(), local_supremum, |
| 103 |
double(local_supremum * _M_rand_sup_reciprocal)); |
| 104 |
} |
| 105 |
|
| 106 |
/** @brief Generate a number of random bits, run-time parameter. |
| 107 |
* @param __bits Number of bits to generate. */ |
| 108 |
unsigned long |
| 109 |
__genrand_bits(int __bits) |
| 110 |
{ |
| 111 |
unsigned long __res = __cache & ((1 << __bits) - 1); |
| 112 |
__cache = __cache >> __bits; |
| 113 |
__bits_left -= __bits; |
| 114 |
if (__bits_left < 32) |
| 115 |
{ |
| 116 |
__cache |= ((uint64_t(_M_mt())) << __bits_left); |
| 117 |
__bits_left += 32; |
| 118 |
} |
| 119 |
return __res; |
| 120 |
} |
| 121 |
}; |
| 122 |
|
| 123 |
} // namespace __gnu_parallel |
| 124 |
|
| 125 |
#endif /* _GLIBCXX_PARALLEL_RANDOM_NUMBER_H */ |