0,0 → 1,125 |
// -*- C++ -*- |
|
// Copyright (C) 2007-2015 Free Software Foundation, Inc. |
// |
// This file is part of the GNU ISO C++ Library. This library is free |
// software; you can redistribute it and/or modify it under the terms |
// of the GNU General Public License as published by the Free Software |
// Foundation; either version 3, or (at your option) any later |
// version. |
|
// This library is distributed in the hope that it will be useful, but |
// WITHOUT ANY WARRANTY; without even the implied warranty of |
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
// General Public License for more details. |
|
// Under Section 7 of GPL version 3, you are granted additional |
// permissions described in the GCC Runtime Library Exception, version |
// 3.1, as published by the Free Software Foundation. |
|
// You should have received a copy of the GNU General Public License and |
// a copy of the GCC Runtime Library Exception along with this program; |
// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see |
// <http://www.gnu.org/licenses/>. |
|
/** @file parallel/random_number.h |
* @brief Random number generator based on the Mersenne twister. |
* This file is a GNU parallel extension to the Standard C++ Library. |
*/ |
|
// Written by Johannes Singler. |
|
#ifndef _GLIBCXX_PARALLEL_RANDOM_NUMBER_H |
#define _GLIBCXX_PARALLEL_RANDOM_NUMBER_H 1 |
|
#include <parallel/types.h> |
#include <tr1/random> |
#include <limits> |
|
namespace __gnu_parallel |
{ |
/** @brief Random number generator, based on the Mersenne twister. */ |
class _RandomNumber |
{ |
private: |
std::tr1::mt19937 _M_mt; |
uint64_t _M_supremum; |
uint64_t _M_rand_sup; |
double _M_supremum_reciprocal; |
double _M_rand_sup_reciprocal; |
|
// Assumed to be twice as long as the usual random number. |
uint64_t __cache; |
|
// Bit results. |
int __bits_left; |
|
static uint32_t |
__scale_down(uint64_t __x, |
#if _GLIBCXX_SCALE_DOWN_FPU |
uint64_t /*_M_supremum*/, double _M_supremum_reciprocal) |
#else |
uint64_t _M_supremum, double /*_M_supremum_reciprocal*/) |
#endif |
{ |
#if _GLIBCXX_SCALE_DOWN_FPU |
return uint32_t(__x * _M_supremum_reciprocal); |
#else |
return static_cast<uint32_t>(__x % _M_supremum); |
#endif |
} |
|
public: |
/** @brief Default constructor. Seed with 0. */ |
_RandomNumber() |
: _M_mt(0), _M_supremum(0x100000000ULL), |
_M_rand_sup(1ULL << std::numeric_limits<uint32_t>::digits), |
_M_supremum_reciprocal(double(_M_supremum) / double(_M_rand_sup)), |
_M_rand_sup_reciprocal(1.0 / double(_M_rand_sup)), |
__cache(0), __bits_left(0) { } |
|
/** @brief Constructor. |
* @param __seed Random __seed. |
* @param _M_supremum Generate integer random numbers in the |
* interval @c [0,_M_supremum). */ |
_RandomNumber(uint32_t __seed, uint64_t _M_supremum = 0x100000000ULL) |
: _M_mt(__seed), _M_supremum(_M_supremum), |
_M_rand_sup(1ULL << std::numeric_limits<uint32_t>::digits), |
_M_supremum_reciprocal(double(_M_supremum) / double(_M_rand_sup)), |
_M_rand_sup_reciprocal(1.0 / double(_M_rand_sup)), |
__cache(0), __bits_left(0) { } |
|
/** @brief Generate unsigned random 32-bit integer. */ |
uint32_t |
operator()() |
{ return __scale_down(_M_mt(), _M_supremum, _M_supremum_reciprocal); } |
|
/** @brief Generate unsigned random 32-bit integer in the |
interval @c [0,local_supremum). */ |
uint32_t |
operator()(uint64_t local_supremum) |
{ |
return __scale_down(_M_mt(), local_supremum, |
double(local_supremum * _M_rand_sup_reciprocal)); |
} |
|
/** @brief Generate a number of random bits, run-time parameter. |
* @param __bits Number of bits to generate. */ |
unsigned long |
__genrand_bits(int __bits) |
{ |
unsigned long __res = __cache & ((1 << __bits) - 1); |
__cache = __cache >> __bits; |
__bits_left -= __bits; |
if (__bits_left < 32) |
{ |
__cache |= ((uint64_t(_M_mt())) << __bits_left); |
__bits_left += 32; |
} |
return __res; |
} |
}; |
|
} // namespace __gnu_parallel |
|
#endif /* _GLIBCXX_PARALLEL_RANDOM_NUMBER_H */ |