diff options
author | Chanho Park <chanho61.park@samsung.com> | 2014-12-11 18:55:56 +0900 |
---|---|---|
committer | Chanho Park <chanho61.park@samsung.com> | 2014-12-11 18:55:56 +0900 |
commit | 08c1e93fa36a49f49325a07fe91ff92c964c2b6c (patch) | |
tree | 7a7053ceb8874b28ec4b868d4c49b500008a102e /boost/random | |
parent | bb4dd8289b351fae6b55e303f189127a394a1edd (diff) | |
download | boost-08c1e93fa36a49f49325a07fe91ff92c964c2b6c.tar.gz boost-08c1e93fa36a49f49325a07fe91ff92c964c2b6c.tar.bz2 boost-08c1e93fa36a49f49325a07fe91ff92c964c2b6c.zip |
Imported Upstream version 1.57.0upstream/1.57.0
Diffstat (limited to 'boost/random')
62 files changed, 1076 insertions, 279 deletions
diff --git a/boost/random/additive_combine.hpp b/boost/random/additive_combine.hpp index b4cb63cd57..d786e18473 100644 --- a/boost/random/additive_combine.hpp +++ b/boost/random/additive_combine.hpp @@ -7,7 +7,7 @@ * * See http://www.boost.org for most recent version including documentation. * - * $Id: additive_combine.hpp 71018 2011-04-05 21:27:52Z steven_watanabe $ + * $Id$ * * Revision history * 2001-02-18 moved to individual header files diff --git a/boost/random/bernoulli_distribution.hpp b/boost/random/bernoulli_distribution.hpp index 79d905d698..d66bae4389 100644 --- a/boost/random/bernoulli_distribution.hpp +++ b/boost/random/bernoulli_distribution.hpp @@ -8,7 +8,7 @@ * * See http://www.boost.org for most recent version including documentation. * - * $Id: bernoulli_distribution.hpp 71018 2011-04-05 21:27:52Z steven_watanabe $ + * $Id$ * * Revision history * 2001-02-18 moved to individual header files diff --git a/boost/random/beta_distribution.hpp b/boost/random/beta_distribution.hpp new file mode 100644 index 0000000000..dabb72bfe2 --- /dev/null +++ b/boost/random/beta_distribution.hpp @@ -0,0 +1,184 @@ +/* boost random/beta_distribution.hpp header file + * + * Copyright Steven Watanabe 2014 + * Distributed under the Boost Software License, Version 1.0. (See + * accompanying file LICENSE_1_0.txt or copy at + * http://www.boost.org/LICENSE_1_0.txt) + * + * See http://www.boost.org for most recent version including documentation. + * + * $Id$ + */ + +#ifndef BOOST_RANDOM_BETA_DISTRIBUTION_HPP +#define BOOST_RANDOM_BETA_DISTRIBUTION_HPP + +#include <cassert> +#include <istream> +#include <iosfwd> +#include <boost/random/detail/operators.hpp> +#include <boost/random/gamma_distribution.hpp> + +namespace boost { +namespace random { + +/** + * The beta distribution is a real-valued distribution which produces + * values in the range [0, 1]. It has two parameters, alpha and beta. + * + * It has \f$\displaystyle p(x) = \frac{x^{\alpha-1}(1-x)^{\beta-1}}{B(\alpha, \beta)}\f$. + */ +template<class RealType = double> +class beta_distribution { +public: + typedef RealType result_type; + typedef RealType input_type; + + class param_type { + public: + typedef beta_distribution distribution_type; + + /** + * Constructs a @c param_type from the "alpha" and "beta" parameters + * of the distribution. + * + * Requires: alpha > 0, beta > 0 + */ + explicit param_type(RealType alpha_arg = RealType(1.0), + RealType beta_arg = RealType(1.0)) + : _alpha(alpha_arg), _beta(beta_arg) + { + assert(alpha_arg > 0); + assert(beta_arg > 0); + } + + /** Returns the "alpha" parameter of the distribtuion. */ + RealType alpha() const { return _alpha; } + /** Returns the "beta" parameter of the distribution. */ + RealType beta() const { return _beta; } + + /** Writes a @c param_type to a @c std::ostream. */ + BOOST_RANDOM_DETAIL_OSTREAM_OPERATOR(os, param_type, parm) + { os << parm._alpha << ' ' << parm._beta; return os; } + + /** Reads a @c param_type from a @c std::istream. */ + BOOST_RANDOM_DETAIL_ISTREAM_OPERATOR(is, param_type, parm) + { is >> parm._alpha >> std::ws >> parm._beta; return is; } + + /** Returns true if the two sets of parameters are the same. */ + BOOST_RANDOM_DETAIL_EQUALITY_OPERATOR(param_type, lhs, rhs) + { return lhs._alpha == rhs._alpha && lhs._beta == rhs._beta; } + + /** Returns true if the two sets of parameters are the different. */ + BOOST_RANDOM_DETAIL_INEQUALITY_OPERATOR(param_type) + + private: + RealType _alpha; + RealType _beta; + }; + + /** + * Constructs an @c beta_distribution from its "alpha" and "beta" parameters. + * + * Requires: alpha > 0, beta > 0 + */ + explicit beta_distribution(RealType alpha_arg = RealType(1.0), + RealType beta_arg = RealType(1.0)) + : _alpha(alpha_arg), _beta(beta_arg) + { + assert(alpha_arg > 0); + assert(beta_arg > 0); + } + /** Constructs an @c beta_distribution from its parameters. */ + explicit beta_distribution(const param_type& parm) + : _alpha(parm.alpha()), _beta(parm.beta()) + {} + + /** + * Returns a random variate distributed according to the + * beta distribution. + */ + template<class URNG> + RealType operator()(URNG& urng) const + { + RealType a = gamma_distribution<RealType>(_alpha, RealType(1.0))(urng); + RealType b = gamma_distribution<RealType>(_beta, RealType(1.0))(urng); + return a / (a + b); + } + + /** + * Returns a random variate distributed accordint to the beta + * distribution with parameters specified by @c param. + */ + template<class URNG> + RealType operator()(URNG& urng, const param_type& parm) const + { + return beta_distribution(parm)(urng); + } + + /** Returns the "alpha" parameter of the distribution. */ + RealType alpha() const { return _alpha; } + /** Returns the "beta" parameter of the distribution. */ + RealType beta() const { return _beta; } + + /** Returns the smallest value that the distribution can produce. */ + RealType min BOOST_PREVENT_MACRO_SUBSTITUTION () const + { return RealType(0.0); } + /** Returns the largest value that the distribution can produce. */ + RealType max BOOST_PREVENT_MACRO_SUBSTITUTION () const + { return RealType(1.0); } + + /** Returns the parameters of the distribution. */ + param_type param() const { return param_type(_alpha, _beta); } + /** Sets the parameters of the distribution. */ + void param(const param_type& parm) + { + _alpha = parm.alpha(); + _beta = parm.beta(); + } + + /** + * Effects: Subsequent uses of the distribution do not depend + * on values produced by any engine prior to invoking reset. + */ + void reset() { } + + /** Writes an @c beta_distribution to a @c std::ostream. */ + BOOST_RANDOM_DETAIL_OSTREAM_OPERATOR(os, beta_distribution, wd) + { + os << wd.param(); + return os; + } + + /** Reads an @c beta_distribution from a @c std::istream. */ + BOOST_RANDOM_DETAIL_ISTREAM_OPERATOR(is, beta_distribution, wd) + { + param_type parm; + if(is >> parm) { + wd.param(parm); + } + return is; + } + + /** + * Returns true if the two instances of @c beta_distribution will + * return identical sequences of values given equal generators. + */ + BOOST_RANDOM_DETAIL_EQUALITY_OPERATOR(beta_distribution, lhs, rhs) + { return lhs._alpha == rhs._alpha && lhs._beta == rhs._beta; } + + /** + * Returns true if the two instances of @c beta_distribution will + * return different sequences of values given equal generators. + */ + BOOST_RANDOM_DETAIL_INEQUALITY_OPERATOR(beta_distribution) + +private: + RealType _alpha; + RealType _beta; +}; + +} // namespace random +} // namespace boost + +#endif // BOOST_RANDOM_BETA_DISTRIBUTION_HPP diff --git a/boost/random/binomial_distribution.hpp b/boost/random/binomial_distribution.hpp index dbe2784d2a..8c880e855c 100644 --- a/boost/random/binomial_distribution.hpp +++ b/boost/random/binomial_distribution.hpp @@ -7,7 +7,7 @@ * * See http://www.boost.org for most recent version including documentation. * - * $Id: binomial_distribution.hpp 71018 2011-04-05 21:27:52Z steven_watanabe $ + * $Id$ */ #ifndef BOOST_RANDOM_BINOMIAL_DISTRIBUTION_HPP_INCLUDED @@ -378,7 +378,19 @@ private: while(u > r) { u = u - r; ++x; - r = ((a/x) - s) * r; + RealType r1 = ((a/x) - s) * r; + // If r gets too small then the round-off error + // becomes a problem. At this point, p(i) is + // decreasing exponentially, so if we just call + // it 0, it's close enough. Note that the + // minimum value of q_n is about 1e-7, so we + // may need to be a little careful to make sure that + // we don't terminate the first time through the loop + // for float. (Hence the test that r is decreasing) + if(r1 < std::numeric_limits<RealType>::epsilon() && r1 < r) { + break; + } + r = r1; } return x; } diff --git a/boost/random/cauchy_distribution.hpp b/boost/random/cauchy_distribution.hpp index ed673bc933..998e523447 100644 --- a/boost/random/cauchy_distribution.hpp +++ b/boost/random/cauchy_distribution.hpp @@ -7,7 +7,7 @@ * * See http://www.boost.org for most recent version including documentation. * - * $Id: cauchy_distribution.hpp 71018 2011-04-05 21:27:52Z steven_watanabe $ + * $Id$ * * Revision history * 2001-02-18 moved to individual header files diff --git a/boost/random/chi_squared_distribution.hpp b/boost/random/chi_squared_distribution.hpp index 9e7d478076..ce63584f2d 100644 --- a/boost/random/chi_squared_distribution.hpp +++ b/boost/random/chi_squared_distribution.hpp @@ -7,7 +7,7 @@ * * See http://www.boost.org for most recent version including documentation. * - * $Id: chi_squared_distribution.hpp 71018 2011-04-05 21:27:52Z steven_watanabe $ + * $Id$ */ #ifndef BOOST_RANDOM_CHI_SQUARED_DISTRIBUTION_HPP_INCLUDED diff --git a/boost/random/detail/auto_link.hpp b/boost/random/detail/auto_link.hpp index 1f30fd56d9..6b180cc71e 100644 --- a/boost/random/detail/auto_link.hpp +++ b/boost/random/detail/auto_link.hpp @@ -5,7 +5,7 @@ * accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) * - * $Id: auto_link.hpp 60755 2010-03-22 00:45:06Z steven_watanabe $ + * $Id$ */ #ifndef BOOST_RANDOM_DETAIL_AUTO_LINK_HPP diff --git a/boost/random/detail/config.hpp b/boost/random/detail/config.hpp index d6bc0ccd07..724ab19452 100644 --- a/boost/random/detail/config.hpp +++ b/boost/random/detail/config.hpp @@ -7,7 +7,7 @@ * * See http://www.boost.org for most recent version including documentation. * - * $Id: config.hpp 52492 2009-04-19 14:55:57Z steven_watanabe $ + * $Id$ */ #include <boost/config.hpp> diff --git a/boost/random/detail/const_mod.hpp b/boost/random/detail/const_mod.hpp index 9778f55179..07f4ea7d84 100644 --- a/boost/random/detail/const_mod.hpp +++ b/boost/random/detail/const_mod.hpp @@ -7,7 +7,7 @@ * * See http://www.boost.org for most recent version including documentation. * - * $Id: const_mod.hpp 71018 2011-04-05 21:27:52Z steven_watanabe $ + * $Id$ * * Revision history * 2001-02-18 moved to individual header files diff --git a/boost/random/detail/disable_warnings.hpp b/boost/random/detail/disable_warnings.hpp index f3ade5ec8d..d875004c44 100644 --- a/boost/random/detail/disable_warnings.hpp +++ b/boost/random/detail/disable_warnings.hpp @@ -7,7 +7,7 @@ * * See http://www.boost.org for most recent version including documentation. * - * $Id: disable_warnings.hpp 60755 2010-03-22 00:45:06Z steven_watanabe $ + * $Id$ * */ @@ -21,3 +21,8 @@ #pragma warning(disable:4127) #pragma warning(disable:4724) #endif + +#if defined(BOOST_GCC) && BOOST_GCC >= 40600 +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wlogical-op" +#endif diff --git a/boost/random/detail/enable_warnings.hpp b/boost/random/detail/enable_warnings.hpp index 26184ea55b..24f3bb3f58 100644 --- a/boost/random/detail/enable_warnings.hpp +++ b/boost/random/detail/enable_warnings.hpp @@ -7,7 +7,7 @@ * * See http://www.boost.org for most recent version including documentation. * - * $Id: enable_warnings.hpp 58649 2010-01-02 21:23:17Z steven_watanabe $ + * $Id$ * */ @@ -16,3 +16,7 @@ #ifdef BOOST_MSVC #pragma warning(pop) #endif + +#if defined(BOOST_GCC) && BOOST_GCC >= 40600 +#pragma GCC diagnostic pop +#endif diff --git a/boost/random/detail/generator_bits.hpp b/boost/random/detail/generator_bits.hpp index 44b4248b2f..05276142cb 100644 --- a/boost/random/detail/generator_bits.hpp +++ b/boost/random/detail/generator_bits.hpp @@ -7,7 +7,7 @@ * * See http://www.boost.org for most recent version including documentation. * - * $Id: generator_bits.hpp 72951 2011-07-07 04:57:37Z steven_watanabe $ + * $Id$ * */ diff --git a/boost/random/detail/generator_seed_seq.hpp b/boost/random/detail/generator_seed_seq.hpp index 6aaf98f577..7e13483464 100644 --- a/boost/random/detail/generator_seed_seq.hpp +++ b/boost/random/detail/generator_seed_seq.hpp @@ -8,7 +8,7 @@ * * See http://www.boost.org for most recent version including documentation. * - * $Id: generator_seed_seq.hpp 71018 2011-04-05 21:27:52Z steven_watanabe $ + * $Id$ * */ diff --git a/boost/random/detail/integer_log2.hpp b/boost/random/detail/integer_log2.hpp index baee426f7a..248243a4b2 100644 --- a/boost/random/detail/integer_log2.hpp +++ b/boost/random/detail/integer_log2.hpp @@ -7,7 +7,7 @@ * * See http://www.boost.org for most recent version including documentation. * - * $Id: integer_log2.hpp 76145 2011-12-24 19:05:17Z danieljames $ + * $Id$ * */ @@ -22,12 +22,12 @@ namespace boost { namespace random { namespace detail { -#if !defined(BOOST_NO_CONSTEXPR) +#if !defined(BOOST_NO_CXX11_CONSTEXPR) #define BOOST_RANDOM_DETAIL_CONSTEXPR constexpr #elif defined(BOOST_MSVC) #define BOOST_RANDOM_DETAIL_CONSTEXPR __forceinline #elif defined(__GNUC__) && __GNUC__ >= 4 -#define BOOST_RANDOM_DETAIL_CONSTEXPR __attribute__((const)) __attribute__((always_inline)) +#define BOOST_RANDOM_DETAIL_CONSTEXPR inline __attribute__((__const__)) __attribute__((__always_inline__)) #else #define BOOST_RANDOM_DETAIL_CONSTEXPR inline #endif @@ -35,7 +35,7 @@ namespace detail { template<int Shift> struct integer_log2_impl { -#if defined(BOOST_NO_CONSTEXPR) +#if defined(BOOST_NO_CXX11_CONSTEXPR) template<class T> BOOST_RANDOM_DETAIL_CONSTEXPR static int apply(T t, int accum) { diff --git a/boost/random/detail/large_arithmetic.hpp b/boost/random/detail/large_arithmetic.hpp index 24177dcdda..66f6b4e615 100644 --- a/boost/random/detail/large_arithmetic.hpp +++ b/boost/random/detail/large_arithmetic.hpp @@ -7,7 +7,7 @@ * * See http://www.boost.org for most recent version including documentation. * - * $Id: large_arithmetic.hpp 71018 2011-04-05 21:27:52Z steven_watanabe $ + * $Id$ */ #ifndef BOOST_RANDOM_DETAIL_LARGE_ARITHMETIC_HPP @@ -31,9 +31,9 @@ struct div_t { inline div_t muldivmod(boost::uintmax_t a, boost::uintmax_t b, boost::uintmax_t m) { - static const int bits = + const int bits = ::std::numeric_limits< ::boost::uintmax_t>::digits / 2; - static const ::boost::uintmax_t mask = (::boost::uintmax_t(1) << bits) - 1; + const ::boost::uintmax_t mask = (::boost::uintmax_t(1) << bits) - 1; typedef ::boost::uint_t<bits>::fast digit_t; int shift = std::numeric_limits< ::boost::uintmax_t>::digits - 1 @@ -96,8 +96,8 @@ inline div_t muldivmod(boost::uintmax_t a, boost::uintmax_t b, boost::uintmax_t quotient[i - 2] = q; product[i] = 0; - product[i-1] = (rem >> bits) & mask; - product[i-2] = rem & mask; + product[i-1] = static_cast<digit_t>((rem >> bits) & mask); + product[i-2] = static_cast<digit_t>(rem & mask); } div_t result = { diff --git a/boost/random/detail/operators.hpp b/boost/random/detail/operators.hpp index f27839a961..597343c907 100644 --- a/boost/random/detail/operators.hpp +++ b/boost/random/detail/operators.hpp @@ -7,7 +7,7 @@ * * See http://www.boost.org for most recent version including documentation. * - * $Id: operators.hpp 71018 2011-04-05 21:27:52Z steven_watanabe $ + * $Id$ */ #ifndef BOOST_RANDOM_DETAIL_OPERATORS_HPP diff --git a/boost/random/detail/ptr_helper.hpp b/boost/random/detail/ptr_helper.hpp index 3f3fbdd564..f1b983d936 100644 --- a/boost/random/detail/ptr_helper.hpp +++ b/boost/random/detail/ptr_helper.hpp @@ -7,7 +7,7 @@ * * See http://www.boost.org for most recent version including documentation. * - * $Id: ptr_helper.hpp 24096 2004-07-27 03:43:34Z dgregor $ + * $Id$ * */ @@ -32,7 +32,6 @@ struct ptr_helper static const T& ref(const T& r) { return r; } }; -#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION template<class T> struct ptr_helper<T&> { @@ -52,7 +51,6 @@ struct ptr_helper<T*> static reference_type ref(T * p) { return *p; } static const T& ref(const T * p) { return *p; } }; -#endif } // namespace detail } // namespace random @@ -64,31 +62,6 @@ struct ptr_helper<T*> // Helper macro for broken compilers defines specializations of // ptr_helper. // -#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION -# define BOOST_RANDOM_PTR_HELPER_SPEC(T) \ -namespace boost { namespace random { namespace detail { \ -template<> \ -struct ptr_helper<T&> \ -{ \ - typedef T value_type; \ - typedef T& reference_type; \ - typedef T& rvalue_type; \ - static reference_type ref(T& r) { return r; } \ - static const T& ref(const T& r) { return r; } \ -}; \ - \ -template<> \ -struct ptr_helper<T*> \ -{ \ - typedef T value_type; \ - typedef T& reference_type; \ - typedef T* rvalue_type; \ - static reference_type ref(T * p) { return *p; } \ - static const T& ref(const T * p) { return *p; } \ -}; \ -}}} -#else # define BOOST_RANDOM_PTR_HELPER_SPEC(T) -#endif #endif // BOOST_RANDOM_DETAIL_PTR_HELPER_HPP diff --git a/boost/random/detail/seed.hpp b/boost/random/detail/seed.hpp index 979db297af..55b2fa667d 100644 --- a/boost/random/detail/seed.hpp +++ b/boost/random/detail/seed.hpp @@ -7,7 +7,7 @@ * * See http://www.boost.org for most recent version including documentation. * - * $Id: seed.hpp 71018 2011-04-05 21:27:52Z steven_watanabe $ + * $Id$ */ #ifndef BOOST_RANDOM_DETAIL_SEED_HPP diff --git a/boost/random/detail/seed_impl.hpp b/boost/random/detail/seed_impl.hpp index e044d45d38..f88cab299c 100644 --- a/boost/random/detail/seed_impl.hpp +++ b/boost/random/detail/seed_impl.hpp @@ -7,7 +7,7 @@ * * See http://www.boost.org for most recent version including documentation. * - * $Id: seed_impl.hpp 72951 2011-07-07 04:57:37Z steven_watanabe $ + * $Id$ */ #ifndef BOOST_RANDOM_DETAIL_SEED_IMPL_HPP @@ -15,6 +15,7 @@ #include <stdexcept> #include <boost/cstdint.hpp> +#include <boost/throw_exception.hpp> #include <boost/config/no_tr1/cmath.hpp> #include <boost/integer/integer_mask.hpp> #include <boost/integer/static_log2.hpp> @@ -253,7 +254,7 @@ IntType get_one_int(Iter& first, Iter last) IntType s = 0; for(int j = 0; j < k; ++j) { if(first == last) { - throw ::std::invalid_argument("Not enough elements in call to seed."); + boost::throw_exception(::std::invalid_argument("Not enough elements in call to seed.")); } IntType digit = const_mod<IntType, m>::apply(IntType(*first++)); IntType mult = IntType(1) << 32*j; @@ -303,7 +304,7 @@ void fill_array_int_impl(Iter& first, Iter last, UIntType (&x)[n]) UIntType val = 0; for(std::size_t k = 0; k < (w+31)/32; ++k) { if(first == last) { - throw std::invalid_argument("Not enough elements in call to seed."); + boost::throw_exception(std::invalid_argument("Not enough elements in call to seed.")); } val += static_cast<UIntType>(*first++) << 32*k; } @@ -373,12 +374,12 @@ void fill_array_real(Iter& first, Iter last, RealType (&x)[n]) RealType val = RealType(0); RealType mult = divisor; for(int k = 0; k < w/32; ++k, ++first) { - if(first == last) throw std::invalid_argument("Not enough elements in call to seed."); + if(first == last) boost::throw_exception(std::invalid_argument("Not enough elements in call to seed.")); val += *first * mult; mult *= two32; } if(mask != 0) { - if(first == last) throw std::invalid_argument("Not enough elements in call to seed."); + if(first == last) boost::throw_exception(std::invalid_argument("Not enough elements in call to seed.")); val += (*first & mask) * mult; ++first; } diff --git a/boost/random/detail/uniform_int_float.hpp b/boost/random/detail/uniform_int_float.hpp index ef209157b6..393c455bcd 100644 --- a/boost/random/detail/uniform_int_float.hpp +++ b/boost/random/detail/uniform_int_float.hpp @@ -8,7 +8,7 @@ * * See http://www.boost.org for most recent version including documentation. * - * $Id: uniform_int_float.hpp 72951 2011-07-07 04:57:37Z steven_watanabe $ + * $Id$ * */ diff --git a/boost/random/detail/vector_io.hpp b/boost/random/detail/vector_io.hpp index 0bb261c3ae..24508c210e 100644 --- a/boost/random/detail/vector_io.hpp +++ b/boost/random/detail/vector_io.hpp @@ -7,7 +7,7 @@ * * See http://www.boost.org for most recent version including documentation. * - * $Id: vector_io.hpp 71018 2011-04-05 21:27:52Z steven_watanabe $ + * $Id$ */ #ifndef BOOST_RANDOM_DETAIL_VECTOR_IO_HPP diff --git a/boost/random/discard_block.hpp b/boost/random/discard_block.hpp index aba6212671..f3c6b82b87 100644 --- a/boost/random/discard_block.hpp +++ b/boost/random/discard_block.hpp @@ -8,7 +8,7 @@ * * See http://www.boost.org for most recent version including documentation. * - * $Id: discard_block.hpp 72951 2011-07-07 04:57:37Z steven_watanabe $ + * $Id$ * * Revision history * 2001-03-02 created @@ -24,6 +24,7 @@ #include <boost/static_assert.hpp> #include <boost/random/detail/config.hpp> #include <boost/random/detail/seed.hpp> +#include <boost/random/detail/seed_impl.hpp> namespace boost { @@ -61,7 +62,7 @@ public: /** Constructs a new \discard_block_engine with a copy of rng. */ explicit discard_block_engine(const base_type & rng) : _rng(rng), _n(0) { } -#ifndef BOOST_NO_RVALUE_REFERENCES +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES /** Constructs a new \discard_block_engine with rng. */ explicit discard_block_engine(base_type && rng) : _rng(rng), _n(0) { } #endif diff --git a/boost/random/discrete_distribution.hpp b/boost/random/discrete_distribution.hpp index bbdc055383..6407272093 100644 --- a/boost/random/discrete_distribution.hpp +++ b/boost/random/discrete_distribution.hpp @@ -7,7 +7,7 @@ * * See http://www.boost.org for most recent version including documentation. * - * $Id: discrete_distribution.hpp 79771 2012-07-27 18:15:55Z jewillco $ + * $Id$ */ #ifndef BOOST_RANDOM_DISCRETE_DISTRIBUTION_HPP_INCLUDED @@ -20,7 +20,7 @@ #include <iterator> #include <boost/assert.hpp> #include <boost/random/uniform_01.hpp> -#include <boost/random/uniform_int.hpp> +#include <boost/random/uniform_int_distribution.hpp> #include <boost/random/detail/config.hpp> #include <boost/random/detail/operators.hpp> #include <boost/random/detail/vector_io.hpp> @@ -36,6 +36,186 @@ namespace boost { namespace random { +namespace detail { + +template<class IntType, class WeightType> +struct integer_alias_table { + WeightType get_weight(IntType bin) const { + WeightType result = _average; + if(bin < _excess) ++result; + return result; + } + template<class Iter> + WeightType init_average(Iter begin, Iter end) { + WeightType weight_average = 0; + IntType excess = 0; + IntType n = 0; + // weight_average * n + excess == current partial sum + // This is a bit messy, but it's guaranteed not to overflow + for(Iter iter = begin; iter != end; ++iter) { + ++n; + if(*iter < weight_average) { + WeightType diff = weight_average - *iter; + weight_average -= diff / n; + if(diff % n > excess) { + --weight_average; + excess += n - diff % n; + } else { + excess -= diff % n; + } + } else { + WeightType diff = *iter - weight_average; + weight_average += diff / n; + if(diff % n < n - excess) { + excess += diff % n; + } else { + ++weight_average; + excess -= n - diff % n; + } + } + } + _alias_table.resize(static_cast<std::size_t>(n)); + _average = weight_average; + _excess = excess; + return weight_average; + } + void init_empty() + { + _alias_table.clear(); + _alias_table.push_back(std::make_pair(static_cast<WeightType>(1), + static_cast<IntType>(0))); + _average = static_cast<WeightType>(1); + _excess = static_cast<IntType>(0); + } + bool operator==(const integer_alias_table& other) const + { + return _alias_table == other._alias_table && + _average == other._average && _excess == other._excess; + } + static WeightType normalize(WeightType val, WeightType average) + { + return val; + } + static void normalize(std::vector<WeightType>&) {} + template<class URNG> + WeightType test(URNG &urng) const + { + return uniform_int_distribution<WeightType>(0, _average)(urng); + } + bool accept(IntType result, WeightType val) const + { + return result < _excess || val < _average; + } + static WeightType try_get_sum(const std::vector<WeightType>& weights) + { + WeightType result = static_cast<WeightType>(0); + for(typename std::vector<WeightType>::const_iterator + iter = weights.begin(), end = weights.end(); + iter != end; ++iter) + { + if((std::numeric_limits<WeightType>::max)() - result > *iter) { + return static_cast<WeightType>(0); + } + result += *iter; + } + return result; + } + template<class URNG> + static WeightType generate_in_range(URNG &urng, WeightType max) + { + return uniform_int_distribution<WeightType>( + static_cast<WeightType>(0), max-1)(urng); + } + typedef std::vector<std::pair<WeightType, IntType> > alias_table_t; + alias_table_t _alias_table; + WeightType _average; + IntType _excess; +}; + +template<class IntType, class WeightType> +struct real_alias_table { + WeightType get_weight(IntType) const + { + return WeightType(1.0); + } + template<class Iter> + WeightType init_average(Iter first, Iter last) + { + std::size_t size = std::distance(first, last); + WeightType weight_sum = + std::accumulate(first, last, static_cast<WeightType>(0)); + _alias_table.resize(size); + return weight_sum / size; + } + void init_empty() + { + _alias_table.clear(); + _alias_table.push_back(std::make_pair(static_cast<WeightType>(1), + static_cast<IntType>(0))); + } + bool operator==(const real_alias_table& other) const + { + return _alias_table == other._alias_table; + } + static WeightType normalize(WeightType val, WeightType average) + { + return val / average; + } + static void normalize(std::vector<WeightType>& weights) + { + WeightType sum = + std::accumulate(weights.begin(), weights.end(), + static_cast<WeightType>(0)); + for(typename std::vector<WeightType>::iterator + iter = weights.begin(), + end = weights.end(); + iter != end; ++iter) + { + *iter /= sum; + } + } + template<class URNG> + WeightType test(URNG &urng) const + { + return uniform_01<WeightType>()(urng); + } + bool accept(IntType, WeightType) const + { + return true; + } + static WeightType try_get_sum(const std::vector<WeightType>& weights) + { + return static_cast<WeightType>(1); + } + template<class URNG> + static WeightType generate_in_range(URNG &urng, WeightType) + { + return uniform_01<WeightType>()(urng); + } + typedef std::vector<std::pair<WeightType, IntType> > alias_table_t; + alias_table_t _alias_table; +}; + +template<bool IsIntegral> +struct select_alias_table; + +template<> +struct select_alias_table<true> { + template<class IntType, class WeightType> + struct apply { + typedef integer_alias_table<IntType, WeightType> type; + }; +}; + +template<> +struct select_alias_table<false> { + template<class IntType, class WeightType> + struct apply { + typedef real_alias_table<IntType, WeightType> type; + }; +}; + +} /** * The class @c discrete_distribution models a \random_distribution. @@ -155,16 +335,7 @@ public: {} void normalize() { - WeightType sum = - std::accumulate(_probabilities.begin(), _probabilities.end(), - static_cast<WeightType>(0)); - for(typename std::vector<WeightType>::iterator - iter = _probabilities.begin(), - end = _probabilities.end(); - iter != end; ++iter) - { - *iter /= sum; - } + impl_type::normalize(_probabilities); } std::vector<WeightType> _probabilities; /// @endcond @@ -176,8 +347,7 @@ public: */ discrete_distribution() { - _alias_table.push_back(std::make_pair(static_cast<WeightType>(1), - static_cast<IntType>(0))); + _impl.init_empty(); } /** * Constructs a discrete_distribution from an iterator range. @@ -257,13 +427,17 @@ public: template<class URNG> IntType operator()(URNG& urng) const { - BOOST_ASSERT(!_alias_table.empty()); - WeightType test = uniform_01<WeightType>()(urng); - IntType result = uniform_int<IntType>((min)(), (max)())(urng); - if(test < _alias_table[result].first) { + BOOST_ASSERT(!_impl._alias_table.empty()); + IntType result; + WeightType test; + do { + result = uniform_int_distribution<IntType>((min)(), (max)())(urng); + test = _impl.test(urng); + } while(!_impl.accept(result, test)); + if(test < _impl._alias_table[result].first) { return result; } else { - return(_alias_table[result].second); + return(_impl._alias_table[result].second); } } @@ -274,13 +448,13 @@ public: template<class URNG> IntType operator()(URNG& urng, const param_type& parm) const { - while(true) { - WeightType val = uniform_01<WeightType>()(urng); + if(WeightType limit = impl_type::try_get_sum(parm._probabilities)) { + WeightType val = impl_type::generate_in_range(urng, limit); WeightType sum = 0; std::size_t result = 0; for(typename std::vector<WeightType>::const_iterator - iter = parm._probabilities.begin(), - end = parm._probabilities.end(); + iter = parm._probabilities.begin(), + end = parm._probabilities.end(); iter != end; ++iter, ++result) { sum += *iter; @@ -288,6 +462,14 @@ public: return result; } } + // This shouldn't be reachable, but round-off error + // can prevent any match from being found when val is + // very close to 1. + return static_cast<IntType>(parm._probabilities.size() - 1); + } else { + // WeightType is integral and sum(parm._probabilities) + // would overflow. Just use the easy solution. + return discrete_distribution(parm)(urng); } } @@ -295,7 +477,7 @@ public: result_type min BOOST_PREVENT_MACRO_SUBSTITUTION () const { return 0; } /** Returns the largest value that the distribution can produce. */ result_type max BOOST_PREVENT_MACRO_SUBSTITUTION () const - { return static_cast<result_type>(_alias_table.size() - 1); } + { return static_cast<result_type>(_impl._alias_table.size() - 1); } /** * Returns a vector containing the probabilities of each @@ -307,22 +489,24 @@ public: * @endcode * * the vector, p will contain {0.1, 0.4, 0.5}. + * + * If @c WeightType is integral, then the weights + * will be returned unchanged. */ std::vector<WeightType> probabilities() const { - std::vector<WeightType> result(_alias_table.size()); - const WeightType mean = - static_cast<WeightType>(1) / _alias_table.size(); + std::vector<WeightType> result(_impl._alias_table.size()); std::size_t i = 0; - for(typename alias_table_t::const_iterator - iter = _alias_table.begin(), - end = _alias_table.end(); + for(typename impl_type::alias_table_t::const_iterator + iter = _impl._alias_table.begin(), + end = _impl._alias_table.end(); iter != end; ++iter, ++i) { - WeightType val = iter->first * mean; + WeightType val = iter->first; result[i] += val; - result[iter->second] += mean - val; + result[iter->second] += _impl.get_weight(i) - val; } + impl_type::normalize(result); return(result); } @@ -366,7 +550,7 @@ public: */ BOOST_RANDOM_DETAIL_EQUALITY_OPERATOR(discrete_distribution, lhs, rhs) { - return lhs._alias_table == rhs._alias_table; + return lhs._impl == rhs._impl; } /** * Returns true if the two distributions may return different @@ -389,59 +573,58 @@ private: { std::vector<std::pair<WeightType, IntType> > below_average; std::vector<std::pair<WeightType, IntType> > above_average; - std::size_t size = std::distance(first, last); - WeightType weight_sum = - std::accumulate(first, last, static_cast<WeightType>(0)); - WeightType weight_average = weight_sum / size; + WeightType weight_average = _impl.init_average(first, last); + WeightType normalized_average = _impl.get_weight(0); std::size_t i = 0; for(; first != last; ++first, ++i) { - WeightType val = *first / weight_average; + WeightType val = impl_type::normalize(*first, weight_average); std::pair<WeightType, IntType> elem(val, static_cast<IntType>(i)); - if(val < static_cast<WeightType>(1)) { + if(val < normalized_average) { below_average.push_back(elem); } else { above_average.push_back(elem); } } - _alias_table.resize(size); - typename alias_table_t::iterator + typename impl_type::alias_table_t::iterator b_iter = below_average.begin(), b_end = below_average.end(), a_iter = above_average.begin(), a_end = above_average.end() ; while(b_iter != b_end && a_iter != a_end) { - _alias_table[b_iter->second] = + _impl._alias_table[b_iter->second] = std::make_pair(b_iter->first, a_iter->second); - a_iter->first -= (static_cast<WeightType>(1) - b_iter->first); - if(a_iter->first < static_cast<WeightType>(1)) { + a_iter->first -= (_impl.get_weight(b_iter->second) - b_iter->first); + if(a_iter->first < normalized_average) { *b_iter = *a_iter++; } else { ++b_iter; } } for(; b_iter != b_end; ++b_iter) { - _alias_table[b_iter->second].first = static_cast<WeightType>(1); + _impl._alias_table[b_iter->second].first = + _impl.get_weight(b_iter->second); } for(; a_iter != a_end; ++a_iter) { - _alias_table[a_iter->second].first = static_cast<WeightType>(1); + _impl._alias_table[a_iter->second].first = + _impl.get_weight(a_iter->second); } } template<class Iter> void init(Iter first, Iter last) { if(first == last) { - _alias_table.clear(); - _alias_table.push_back(std::make_pair(static_cast<WeightType>(1), - static_cast<IntType>(0))); + _impl.init_empty(); } else { typename std::iterator_traits<Iter>::iterator_category category; init(first, last, category); } } - typedef std::vector<std::pair<WeightType, IntType> > alias_table_t; - alias_table_t _alias_table; + typedef typename detail::select_alias_table< + (::boost::is_integral<WeightType>::value) + >::template apply<IntType, WeightType>::type impl_type; + impl_type _impl; /// @endcond }; diff --git a/boost/random/exponential_distribution.hpp b/boost/random/exponential_distribution.hpp index dd45e35d9b..53eaa93865 100644 --- a/boost/random/exponential_distribution.hpp +++ b/boost/random/exponential_distribution.hpp @@ -8,7 +8,7 @@ * * See http://www.boost.org for most recent version including documentation. * - * $Id: exponential_distribution.hpp 71018 2011-04-05 21:27:52Z steven_watanabe $ + * $Id$ * * Revision history * 2001-02-18 moved to individual header files diff --git a/boost/random/extreme_value_distribution.hpp b/boost/random/extreme_value_distribution.hpp index 61a6554546..419c3da651 100644 --- a/boost/random/extreme_value_distribution.hpp +++ b/boost/random/extreme_value_distribution.hpp @@ -7,7 +7,7 @@ * * See http://www.boost.org for most recent version including documentation. * - * $Id: extreme_value_distribution.hpp 71018 2011-04-05 21:27:52Z steven_watanabe $ + * $Id$ */ #ifndef BOOST_RANDOM_EXTREME_VALUE_DISTRIBUTION_HPP diff --git a/boost/random/fisher_f_distribution.hpp b/boost/random/fisher_f_distribution.hpp index 58a05ac342..cdf14da8f6 100644 --- a/boost/random/fisher_f_distribution.hpp +++ b/boost/random/fisher_f_distribution.hpp @@ -7,7 +7,7 @@ * * See http://www.boost.org for most recent version including documentation. * - * $Id: fisher_f_distribution.hpp 71018 2011-04-05 21:27:52Z steven_watanabe $ + * $Id$ */ #ifndef BOOST_RANDOM_FISHER_F_DISTRIBUTION_HPP diff --git a/boost/random/gamma_distribution.hpp b/boost/random/gamma_distribution.hpp index 20f5c3b4ff..c9bda4ca9d 100644 --- a/boost/random/gamma_distribution.hpp +++ b/boost/random/gamma_distribution.hpp @@ -8,7 +8,7 @@ * * See http://www.boost.org for most recent version including documentation. * - * $Id: gamma_distribution.hpp 71018 2011-04-05 21:27:52Z steven_watanabe $ + * $Id$ * */ diff --git a/boost/random/generate_canonical.hpp b/boost/random/generate_canonical.hpp index 1bba44f0d2..23ff43dfac 100644 --- a/boost/random/generate_canonical.hpp +++ b/boost/random/generate_canonical.hpp @@ -7,7 +7,7 @@ * * See http://www.boost.org for most recent version including documentation. * - * $Id: generate_canonical.hpp 72951 2011-07-07 04:57:37Z steven_watanabe $ + * $Id$ * */ @@ -19,7 +19,6 @@ #include <boost/config/no_tr1/cmath.hpp> #include <boost/limits.hpp> #include <boost/type_traits/is_integral.hpp> -#include <boost/math/special_functions.hpp> #include <boost/random/detail/signed_unsigned_tools.hpp> #include <boost/random/detail/generator_bits.hpp> @@ -55,7 +54,6 @@ RealType generate_canonical_impl(URNG& g, boost::mpl::false_ /*is_integral*/) using std::floor; BOOST_ASSERT((g.min)() == 0); BOOST_ASSERT((g.max)() == 1); - typedef typename URNG::result_type base_result; std::size_t digits = std::numeric_limits<RealType>::digits; std::size_t engine_bits = detail::generator_bits<URNG>::value(); std::size_t b = (std::min)(bits, digits); diff --git a/boost/random/geometric_distribution.hpp b/boost/random/geometric_distribution.hpp index daca0ceb11..90374cff71 100644 --- a/boost/random/geometric_distribution.hpp +++ b/boost/random/geometric_distribution.hpp @@ -8,7 +8,7 @@ * * See http://www.boost.org for most recent version including documentation. * - * $Id: geometric_distribution.hpp 74867 2011-10-09 23:13:31Z steven_watanabe $ + * $Id$ * * Revision history * 2001-02-18 moved to individual header files @@ -104,8 +104,8 @@ public: * * Requires: 0 < p < 1 */ - explicit geometric_distribution(const RealType& p = RealType(0.5)) - : _p(p) + explicit geometric_distribution(const RealType& p_arg = RealType(0.5)) + : _p(p_arg) { BOOST_ASSERT(RealType(0) < _p && _p < RealType(1)); init(); diff --git a/boost/random/independent_bits.hpp b/boost/random/independent_bits.hpp index f387fe2d8f..5ff52b80ff 100644 --- a/boost/random/independent_bits.hpp +++ b/boost/random/independent_bits.hpp @@ -7,7 +7,7 @@ * * See http://www.boost.org for most recent version including documentation. * - * $Id: independent_bits.hpp 71018 2011-04-05 21:27:52Z steven_watanabe $ + * $Id$ * */ diff --git a/boost/random/inversive_congruential.hpp b/boost/random/inversive_congruential.hpp index 616909d445..2329c0db3a 100644 --- a/boost/random/inversive_congruential.hpp +++ b/boost/random/inversive_congruential.hpp @@ -7,7 +7,7 @@ * * See http://www.boost.org for most recent version including documentation. * - * $Id: inversive_congruential.hpp 71018 2011-04-05 21:27:52Z steven_watanabe $ + * $Id$ * * Revision history * 2001-02-18 moved to individual header files diff --git a/boost/random/lagged_fibonacci.hpp b/boost/random/lagged_fibonacci.hpp index eb4e405c50..5a809f3e49 100644 --- a/boost/random/lagged_fibonacci.hpp +++ b/boost/random/lagged_fibonacci.hpp @@ -7,9 +7,10 @@ * * See http://www.boost.org for most recent version including documentation. * - * $Id: lagged_fibonacci.hpp 72951 2011-07-07 04:57:37Z steven_watanabe $ + * $Id$ * * Revision history + * 2013-10-14 fixed some warnings with Wshadow (mgaunard) * 2001-02-18 moved to individual header files */ @@ -35,7 +36,7 @@ namespace boost { namespace random { -/** +/** * Instantiations of class template \lagged_fibonacci_engine model a * \pseudo_random_number_generator. It uses a lagged Fibonacci * algorithm with two lags @c p and @c q: @@ -79,7 +80,7 @@ public: { seed(first, last); } // compiler-generated copy ctor and assignment operator are fine - + /** Calls @c seed(default_seed). */ void seed() { seed(default_seed); } @@ -123,7 +124,7 @@ public: fill(); return x[i++]; } - + /** Fills a range with random values */ template<class Iter> void generate(Iter first, Iter last) @@ -136,36 +137,36 @@ public: (*this)(); } } - + /** * Writes the textual representation of the generator to a @c std::ostream. */ BOOST_RANDOM_DETAIL_OSTREAM_OPERATOR(os, lagged_fibonacci_engine, f) { os << f.i; - for(unsigned int i = 0; i < f.long_lag; ++i) - os << ' ' << f.x[i]; + for(unsigned int j = 0; j < f.long_lag; ++j) + os << ' ' << f.x[j]; return os; } - + /** * Reads the textual representation of the generator from a @c std::istream. */ BOOST_RANDOM_DETAIL_ISTREAM_OPERATOR(is, lagged_fibonacci_engine, f) { is >> f.i >> std::ws; - for(unsigned int i = 0; i < f.long_lag; ++i) - is >> f.x[i] >> std::ws; + for(unsigned int j = 0; j < f.long_lag; ++j) + is >> f.x[j] >> std::ws; return is; } - + /** * Returns true if the two generators will produce identical * sequences of outputs. */ - BOOST_RANDOM_DETAIL_EQUALITY_OPERATOR(lagged_fibonacci_engine, x, y) - { return x.i == y.i && std::equal(x.x, x.x+long_lag, y.x); } - + BOOST_RANDOM_DETAIL_EQUALITY_OPERATOR(lagged_fibonacci_engine, x_, y_) + { return x_.i == y_.i && std::equal(x_.x, x_.x+long_lag, y_.x); } + /** * Returns true if the two generators will produce different * sequences of outputs. @@ -306,7 +307,7 @@ public: detail::seed_array_real<w>(seq, x); i = long_lag; } - + /** * Seeds this @c lagged_fibonacci_01_engine using values from the * iterator range [first, last). If there are not enough elements @@ -318,7 +319,7 @@ public: detail::fill_array_real<w>(first, last, x); i = long_lag; } - + /** Returns the smallest value that the generator can produce. */ static result_type min BOOST_PREVENT_MACRO_SUBSTITUTION () { return result_type(0); } /** Returns the upper bound of the generators outputs. */ @@ -331,7 +332,7 @@ public: fill(); return x[i++]; } - + /** Fills a range with random values */ template<class Iter> void generate(Iter first, Iter last) @@ -344,7 +345,7 @@ public: (*this)(); } } - + /** * Writes the textual representation of the generator to a @c std::ostream. */ @@ -353,34 +354,34 @@ public: // allow for Koenig lookup using std::pow; os << f.i; - std::ios_base::fmtflags oldflags = os.flags(os.dec | os.fixed | os.left); - for(unsigned int i = 0; i < f.long_lag; ++i) - os << ' ' << f.x[i] * f.modulus(); + std::ios_base::fmtflags oldflags = os.flags(os.dec | os.fixed | os.left); + for(unsigned int j = 0; j < f.long_lag; ++j) + os << ' ' << f.x[j] * f.modulus(); os.flags(oldflags); return os; } - + /** * Reads the textual representation of the generator from a @c std::istream. */ BOOST_RANDOM_DETAIL_ISTREAM_OPERATOR(is, lagged_fibonacci_01_engine, f) { is >> f.i; - for(unsigned int i = 0; i < f.long_lag; ++i) { + for(unsigned int j = 0; j < f.long_lag; ++j) { typename lagged_fibonacci_01_engine::result_type value; is >> std::ws >> value; - f.x[i] = value / f.modulus(); + f.x[j] = value / f.modulus(); } return is; } - + /** * Returns true if the two generators will produce identical * sequences of outputs. */ - BOOST_RANDOM_DETAIL_EQUALITY_OPERATOR(lagged_fibonacci_01_engine, x, y) - { return x.i == y.i && std::equal(x.x, x.x+long_lag, y.x); } - + BOOST_RANDOM_DETAIL_EQUALITY_OPERATOR(lagged_fibonacci_01_engine, x_, y_) + { return x_.i == y_.i && std::equal(x_.x, x_.x+long_lag, y_.x); } + /** * Returns true if the two generators will produce different * sequences of outputs. diff --git a/boost/random/laplace_distribution.hpp b/boost/random/laplace_distribution.hpp new file mode 100644 index 0000000000..ec176a59c1 --- /dev/null +++ b/boost/random/laplace_distribution.hpp @@ -0,0 +1,175 @@ +/* boost random/laplace_distribution.hpp header file + * + * Copyright Steven Watanabe 2014 + * Distributed under the Boost Software License, Version 1.0. (See + * accompanying file LICENSE_1_0.txt or copy at + * http://www.boost.org/LICENSE_1_0.txt) + * + * See http://www.boost.org for most recent version including documentation. + * + * $Id$ + */ + +#ifndef BOOST_RANDOM_LAPLACE_DISTRIBUTION_HPP +#define BOOST_RANDOM_LAPLACE_DISTRIBUTION_HPP + +#include <cassert> +#include <istream> +#include <iosfwd> +#include <boost/random/detail/operators.hpp> +#include <boost/random/exponential_distribution.hpp> + +namespace boost { +namespace random { + +/** + * The laplace distribution is a real-valued distribution with + * two parameters, mean and beta. + * + * It has \f$\displaystyle p(x) = \frac{e^-{\frac{|x-\mu|}{\beta}}}{2\beta}\f$. + */ +template<class RealType = double> +class laplace_distribution { +public: + typedef RealType result_type; + typedef RealType input_type; + + class param_type { + public: + typedef laplace_distribution distribution_type; + + /** + * Constructs a @c param_type from the "mean" and "beta" parameters + * of the distribution. + */ + explicit param_type(RealType mean_arg = RealType(0.0), + RealType beta_arg = RealType(1.0)) + : _mean(mean_arg), _beta(beta_arg) + {} + + /** Returns the "mean" parameter of the distribtuion. */ + RealType mean() const { return _mean; } + /** Returns the "beta" parameter of the distribution. */ + RealType beta() const { return _beta; } + + /** Writes a @c param_type to a @c std::ostream. */ + BOOST_RANDOM_DETAIL_OSTREAM_OPERATOR(os, param_type, parm) + { os << parm._mean << ' ' << parm._beta; return os; } + + /** Reads a @c param_type from a @c std::istream. */ + BOOST_RANDOM_DETAIL_ISTREAM_OPERATOR(is, param_type, parm) + { is >> parm._mean >> std::ws >> parm._beta; return is; } + + /** Returns true if the two sets of parameters are the same. */ + BOOST_RANDOM_DETAIL_EQUALITY_OPERATOR(param_type, lhs, rhs) + { return lhs._mean == rhs._mean && lhs._beta == rhs._beta; } + + /** Returns true if the two sets of parameters are the different. */ + BOOST_RANDOM_DETAIL_INEQUALITY_OPERATOR(param_type) + + private: + RealType _mean; + RealType _beta; + }; + + /** + * Constructs an @c laplace_distribution from its "mean" and "beta" parameters. + */ + explicit laplace_distribution(RealType mean_arg = RealType(0.0), + RealType beta_arg = RealType(1.0)) + : _mean(mean_arg), _beta(beta_arg) + {} + /** Constructs an @c laplace_distribution from its parameters. */ + explicit laplace_distribution(const param_type& parm) + : _mean(parm.mean()), _beta(parm.beta()) + {} + + /** + * Returns a random variate distributed according to the + * laplace distribution. + */ + template<class URNG> + RealType operator()(URNG& urng) const + { + RealType exponential = exponential_distribution<RealType>()(urng); + if(uniform_01<RealType>()(urng) < 0.5) + exponential = -exponential; + return _mean + _beta * exponential; + } + + /** + * Returns a random variate distributed accordint to the laplace + * distribution with parameters specified by @c param. + */ + template<class URNG> + RealType operator()(URNG& urng, const param_type& parm) const + { + return laplace_distribution(parm)(urng); + } + + /** Returns the "mean" parameter of the distribution. */ + RealType mean() const { return _mean; } + /** Returns the "beta" parameter of the distribution. */ + RealType beta() const { return _beta; } + + /** Returns the smallest value that the distribution can produce. */ + RealType min BOOST_PREVENT_MACRO_SUBSTITUTION () const + { return RealType(-std::numeric_limits<RealType>::infinity()); } + /** Returns the largest value that the distribution can produce. */ + RealType max BOOST_PREVENT_MACRO_SUBSTITUTION () const + { return RealType(std::numeric_limits<RealType>::infinity()); } + + /** Returns the parameters of the distribution. */ + param_type param() const { return param_type(_mean, _beta); } + /** Sets the parameters of the distribution. */ + void param(const param_type& parm) + { + _mean = parm.mean(); + _beta = parm.beta(); + } + + /** + * Effects: Subsequent uses of the distribution do not depend + * on values produced by any engine prior to invoking reset. + */ + void reset() { } + + /** Writes an @c laplace_distribution to a @c std::ostream. */ + BOOST_RANDOM_DETAIL_OSTREAM_OPERATOR(os, laplace_distribution, wd) + { + os << wd.param(); + return os; + } + + /** Reads an @c laplace_distribution from a @c std::istream. */ + BOOST_RANDOM_DETAIL_ISTREAM_OPERATOR(is, laplace_distribution, wd) + { + param_type parm; + if(is >> parm) { + wd.param(parm); + } + return is; + } + + /** + * Returns true if the two instances of @c laplace_distribution will + * return identical sequences of values given equal generators. + */ + BOOST_RANDOM_DETAIL_EQUALITY_OPERATOR(laplace_distribution, lhs, rhs) + { return lhs._mean == rhs._mean && lhs._beta == rhs._beta; } + + /** + * Returns true if the two instances of @c laplace_distribution will + * return different sequences of values given equal generators. + */ + BOOST_RANDOM_DETAIL_INEQUALITY_OPERATOR(laplace_distribution) + +private: + RealType _mean; + RealType _beta; +}; + +} // namespace random +} // namespace boost + +#endif // BOOST_RANDOM_LAPLACE_DISTRIBUTION_HPP diff --git a/boost/random/linear_congruential.hpp b/boost/random/linear_congruential.hpp index 5f8fe7a078..de3a1d0749 100644 --- a/boost/random/linear_congruential.hpp +++ b/boost/random/linear_congruential.hpp @@ -7,7 +7,7 @@ * * See http://www.boost.org for most recent version including documentation. * - * $Id: linear_congruential.hpp 71018 2011-04-05 21:27:52Z steven_watanabe $ + * $Id$ * * Revision history * 2001-02-18 moved to individual header files diff --git a/boost/random/linear_feedback_shift.hpp b/boost/random/linear_feedback_shift.hpp index 1cce9f9cf3..a695dfde97 100644 --- a/boost/random/linear_feedback_shift.hpp +++ b/boost/random/linear_feedback_shift.hpp @@ -8,7 +8,7 @@ * * See http://www.boost.org for most recent version including documentation. * - * $Id: linear_feedback_shift.hpp 71018 2011-04-05 21:27:52Z steven_watanabe $ + * $Id$ * */ diff --git a/boost/random/lognormal_distribution.hpp b/boost/random/lognormal_distribution.hpp index bc7ddfeff2..7ed1e13abf 100644 --- a/boost/random/lognormal_distribution.hpp +++ b/boost/random/lognormal_distribution.hpp @@ -8,7 +8,7 @@ * * See http://www.boost.org for most recent version including documentation. * - * $Id: lognormal_distribution.hpp 71018 2011-04-05 21:27:52Z steven_watanabe $ + * $Id$ * * Revision history * 2001-02-18 moved to individual header files diff --git a/boost/random/mersenne_twister.hpp b/boost/random/mersenne_twister.hpp index be603898be..3878fee156 100644 --- a/boost/random/mersenne_twister.hpp +++ b/boost/random/mersenne_twister.hpp @@ -8,9 +8,10 @@ * * See http://www.boost.org for most recent version including documentation. * - * $Id: mersenne_twister.hpp 74867 2011-10-09 23:13:31Z steven_watanabe $ + * $Id$ * * Revision history + * 2013-10-14 fixed some warnings with Wshadow (mgaunard) * 2001-02-18 moved to individual header files */ @@ -40,7 +41,7 @@ namespace random { * "Mersenne Twister: A 623-dimensionally equidistributed uniform * pseudo-random number generator", Makoto Matsumoto and Takuji Nishimura, * ACM Transactions on Modeling and Computer Simulation: Special Issue on - * Uniform Random Number Generation, Vol. 8, No. 1, January 1998, pp. 3-30. + * Uniform Random Number Generation, Vol. 8, No. 1, January 1998, pp. 3-30. * @endblockquote * * @xmlnote @@ -51,7 +52,7 @@ namespace random { * * The seeding from an integer was changed in April 2005 to address a * <a href="http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/MT2002/emt19937ar.html">weakness</a>. - * + * * The quality of the generator crucially depends on the choice of the * parameters. User code should employ one of the sensibly parameterized * generators such as \mt19937 instead. @@ -83,7 +84,7 @@ public: BOOST_STATIC_CONSTANT(std::size_t, tempering_l = l); BOOST_STATIC_CONSTANT(UIntType, initialization_multiplier = f); BOOST_STATIC_CONSTANT(UIntType, default_seed = 5489u); - + // backwards compatibility BOOST_STATIC_CONSTANT(UIntType, parameter_a = a); BOOST_STATIC_CONSTANT(std::size_t, output_u = u); @@ -92,7 +93,7 @@ public: BOOST_STATIC_CONSTANT(std::size_t, output_t = t); BOOST_STATIC_CONSTANT(UIntType, output_c = c); BOOST_STATIC_CONSTANT(std::size_t, output_l = l); - + // old Boost.Random concept requirements BOOST_STATIC_CONSTANT(bool, has_fixed_range = false); @@ -136,7 +137,7 @@ public: */ BOOST_RANDOM_DETAIL_ARITHMETIC_SEED(mersenne_twister_engine, UIntType, value) { - // New seeding algorithm from + // New seeding algorithm from // http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/MT2002/emt19937ar.html // In the previous versions, MSBs of the seed affected only MSBs of the // state x[]. @@ -147,8 +148,10 @@ public: // Vol. 2, 3rd ed., page 106 x[i] = (f * (x[i-1] ^ (x[i-1] >> (w-2))) + i) & mask; } + + normalize_state(); } - + /** * Seeds a mersenne_twister_engine using values produced by seq.generate(). */ @@ -157,13 +160,7 @@ public: detail::seed_array_int<w>(seq, x); i = n; - // fix up the state if it's all zeroes. - if((x[0] & (~static_cast<UIntType>(0) << r)) == 0) { - for(std::size_t j = 1; j < n; ++j) { - if(x[j] != 0) return; - } - x[0] = static_cast<UIntType>(1) << (w-1); - } + normalize_state(); } /** Sets the state of the generator using values from an iterator range. */ @@ -173,22 +170,16 @@ public: detail::fill_array_int<w>(first, last, x); i = n; - // fix up the state if it's all zeroes. - if((x[0] & (~static_cast<UIntType>(0) << r)) == 0) { - for(std::size_t j = 1; j < n; ++j) { - if(x[j] != 0) return; - } - x[0] = static_cast<UIntType>(1) << (w-1); - } + normalize_state(); } - + /** Returns the smallest value that the generator can produce. */ static result_type min BOOST_PREVENT_MACRO_SUBSTITUTION () { return 0; } /** Returns the largest value that the generator can produce. */ static result_type max BOOST_PREVENT_MACRO_SUBSTITUTION () { return boost::low_bits_mask_t<w>::sig_bits; } - + /** Produces the next value of the generator. */ result_type operator()(); @@ -223,7 +214,7 @@ public: mt.print(os); return os; } - + /** Reads a mersenne_twister_engine from a @c std::istream */ template<class CharT, class Traits> friend std::basic_istream<CharT,Traits>& @@ -244,19 +235,19 @@ public: * Returns true if the two generators are in the same state, * and will thus produce identical sequences. */ - friend bool operator==(const mersenne_twister_engine& x, - const mersenne_twister_engine& y) + friend bool operator==(const mersenne_twister_engine& x_, + const mersenne_twister_engine& y_) { - if(x.i < y.i) return x.equal_imp(y); - else return y.equal_imp(x); + if(x_.i < y_.i) return x_.equal_imp(y_); + else return y_.equal_imp(x_); } - + /** * Returns true if the two generators are in different states. */ - friend bool operator!=(const mersenne_twister_engine& x, - const mersenne_twister_engine& y) - { return !(x == y); } + friend bool operator!=(const mersenne_twister_engine& x_, + const mersenne_twister_engine& y_) + { return !(x_ == y_); } private: /// \cond show_private @@ -333,6 +324,35 @@ private: } /** + * Converts an arbitrary array into a valid generator state. + * First we normalize x[0], so that it contains the same + * value we would get by running the generator forwards + * and then in reverse. (The low order r bits are redundant). + * Then, if the state consists of all zeros, we set the + * high order bit of x[0] to 1. This function only needs to + * be called by seed, since the state transform preserves + * this relationship. + */ + void normalize_state() + { + const UIntType upper_mask = (~static_cast<UIntType>(0)) << r; + const UIntType lower_mask = ~upper_mask; + UIntType y0 = x[m-1] ^ x[n-1]; + if(y0 & (static_cast<UIntType>(1) << (w-1))) { + y0 = ((y0 ^ a) << 1) | 1; + } else { + y0 = y0 << 1; + } + x[0] = (x[0] & upper_mask) | (y0 & lower_mask); + + // fix up the state if it's all zeroes. + for(std::size_t j = 0; j < n; ++j) { + if(x[j] != 0) return; + } + x[0] = static_cast<UIntType>(1) << (w-1); + } + + /** * Given a pointer to the last element of the rewind array, * and the current size of the rewind array, finds an element * relative to the next available slot in the rewind array. @@ -354,7 +374,7 @@ private: // x[0] ... x[k] x[k+1] ... x[n-1] represents // x(i-k) ... x(i) x(i+1) ... x(i-k+n-1) - UIntType x[n]; + UIntType x[n]; std::size_t i; }; @@ -468,7 +488,7 @@ mersenne_twister_engine<UIntType,w,n,m,r,a,u,d,s,b,t,c,l,f>::operator()() * uniform pseudo-random number generator", Makoto Matsumoto * and Takuji Nishimura, ACM Transactions on Modeling and * Computer Simulation: Special Issue on Uniform Random Number - * Generation, Vol. 8, No. 1, January 1998, pp. 3-30. + * Generation, Vol. 8, No. 1, January 1998, pp. 3-30. * @endblockquote */ typedef mersenne_twister_engine<uint32_t,32,351,175,19,0xccab8ee7, @@ -482,7 +502,7 @@ typedef mersenne_twister_engine<uint32_t,32,351,175,19,0xccab8ee7, * uniform pseudo-random number generator", Makoto Matsumoto * and Takuji Nishimura, ACM Transactions on Modeling and * Computer Simulation: Special Issue on Uniform Random Number - * Generation, Vol. 8, No. 1, January 1998, pp. 3-30. + * Generation, Vol. 8, No. 1, January 1998, pp. 3-30. * @endblockquote */ typedef mersenne_twister_engine<uint32_t,32,624,397,31,0x9908b0df, diff --git a/boost/random/negative_binomial_distribution.hpp b/boost/random/negative_binomial_distribution.hpp index 23b657ffcf..cbe26fad25 100644 --- a/boost/random/negative_binomial_distribution.hpp +++ b/boost/random/negative_binomial_distribution.hpp @@ -7,7 +7,7 @@ * * See http://www.boost.org for most recent version including documentation. * - * $Id: negative_binomial_distribution.hpp 71018 2011-04-05 21:27:52Z steven_watanabe $ + * $Id$ */ #ifndef BOOST_RANDOM_NEGATIVE_BINOMIAL_DISTRIBUTION_HPP_INCLUDED diff --git a/boost/random/normal_distribution.hpp b/boost/random/normal_distribution.hpp index 9515fb305a..0be1298fcc 100644 --- a/boost/random/normal_distribution.hpp +++ b/boost/random/normal_distribution.hpp @@ -8,7 +8,7 @@ * * See http://www.boost.org for most recent version including documentation. * - * $Id: normal_distribution.hpp 71018 2011-04-05 21:27:52Z steven_watanabe $ + * $Id$ * * Revision history * 2001-02-18 moved to individual header files @@ -23,13 +23,224 @@ #include <boost/assert.hpp> #include <boost/limits.hpp> #include <boost/static_assert.hpp> +#include <boost/integer.hpp> +#include <boost/integer/integer_mask.hpp> +#include <boost/type_traits/is_integral.hpp> +#include <boost/type_traits/make_unsigned.hpp> #include <boost/random/detail/config.hpp> #include <boost/random/detail/operators.hpp> +#include <boost/random/detail/integer_log2.hpp> #include <boost/random/uniform_01.hpp> +#include <boost/random/uniform_int_distribution.hpp> +#include <boost/random/exponential_distribution.hpp> namespace boost { namespace random { +namespace detail { + +// tables for the ziggurat algorithm +template<class RealType> +struct normal_table { + static const RealType table_x[129]; + static const RealType table_y[129]; +}; + +template<class RealType> +const RealType normal_table<RealType>::table_x[129] = { + 3.7130862467403632609, 3.4426198558966521214, 3.2230849845786185446, 3.0832288582142137009, + 2.9786962526450169606, 2.8943440070186706210, 2.8231253505459664379, 2.7611693723841538514, + 2.7061135731187223371, 2.6564064112581924999, 2.6109722484286132035, 2.5690336259216391328, + 2.5300096723854666170, 2.4934545220919507609, 2.4590181774083500943, 2.4264206455302115930, + 2.3954342780074673425, 2.3658713701139875435, 2.3375752413355307354, 2.3104136836950021558, + 2.2842740596736568056, 2.2590595738653295251, 2.2346863955870569803, 2.2110814088747278106, + 2.1881804320720206093, 2.1659267937448407377, 2.1442701823562613518, 2.1231657086697899595, + 2.1025731351849988838, 2.0824562379877246441, 2.0627822745039633575, 2.0435215366506694976, + 2.0246469733729338782, 2.0061338699589668403, 1.9879595741230607243, 1.9701032608497132242, + 1.9525457295488889058, 1.9352692282919002011, 1.9182573008597320303, 1.9014946531003176140, + 1.8849670357028692380, 1.8686611409895420085, 1.8525645117230870617, 1.8366654602533840447, + 1.8209529965910050740, 1.8054167642140487420, 1.7900469825946189862, 1.7748343955807692457, + 1.7597702248942318749, 1.7448461281083765085, 1.7300541605582435350, 1.7153867407081165482, + 1.7008366185643009437, 1.6863968467734863258, 1.6720607540918522072, 1.6578219209482075462, + 1.6436741568569826489, 1.6296114794646783962, 1.6156280950371329644, 1.6017183802152770587, + 1.5878768648844007019, 1.5740982160167497219, 1.5603772223598406870, 1.5467087798535034608, + 1.5330878776675560787, 1.5195095847593707806, 1.5059690368565502602, 1.4924614237746154081, + 1.4789819769830978546, 1.4655259573357946276, 1.4520886428822164926, 1.4386653166774613138, + 1.4252512545068615734, 1.4118417124397602509, 1.3984319141236063517, 1.3850170377251486449, + 1.3715922024197322698, 1.3581524543224228739, 1.3446927517457130432, 1.3312079496576765017, + 1.3176927832013429910, 1.3041418501204215390, 1.2905495919178731508, 1.2769102735516997175, + 1.2632179614460282310, 1.2494664995643337480, 1.2356494832544811749, 1.2217602305309625678, + 1.2077917504067576028, 1.1937367078237721994, 1.1795873846544607035, 1.1653356361550469083, + 1.1509728421389760651, 1.1364898520030755352, 1.1218769225722540661, 1.1071236475235353980, + 1.0922188768965537614, 1.0771506248819376573, 1.0619059636836193998, 1.0464709007525802629, + 1.0308302360564555907, 1.0149673952392994716, 0.99886423348064351303, 0.98250080350276038481, + 0.96585507938813059489, 0.94890262549791195381, 0.93161619660135381056, 0.91396525100880177644, + 0.89591535256623852894, 0.87742742909771569142, 0.85845684317805086354, 0.83895221428120745572, + 0.81885390668331772331, 0.79809206062627480454, 0.77658398787614838598, 0.75423066443451007146, + 0.73091191062188128150, 0.70647961131360803456, 0.68074791864590421664, 0.65347863871504238702, + 0.62435859730908822111, 0.59296294244197797913, 0.55869217837551797140, 0.52065603872514491759, + 0.47743783725378787681, 0.42654798630330512490, 0.36287143102841830424, 0.27232086470466385065, + 0 +}; + +template<class RealType> +const RealType normal_table<RealType>::table_y[129] = { + 0, 0.0026696290839025035092, 0.0055489952208164705392, 0.0086244844129304709682, + 0.011839478657982313715, 0.015167298010672042468, 0.018592102737165812650, 0.022103304616111592615, + 0.025693291936149616572, 0.029356317440253829618, 0.033087886146505155566, 0.036884388786968774128, + 0.040742868074790604632, 0.044660862200872429800, 0.048636295860284051878, 0.052667401903503169793, + 0.056752663481538584188, 0.060890770348566375972, 0.065080585213631873753, 0.069321117394180252601, + 0.073611501884754893389, 0.077950982514654714188, 0.082338898242957408243, 0.086774671895542968998, + 0.091257800827634710201, 0.09578784912257815216, 0.10036444102954554013, 0.10498725541035453978, + 0.10965602101581776100, 0.11437051244988827452, 0.11913054670871858767, 0.12393598020398174246, + 0.12878670619710396109, 0.13368265258464764118, 0.13862377998585103702, 0.14361008009193299469, + 0.14864157424369696566, 0.15371831220958657066, 0.15884037114093507813, 0.16400785468492774791, + 0.16922089223892475176, 0.17447963833240232295, 0.17978427212496211424, 0.18513499701071343216, + 0.19053204032091372112, 0.19597565311811041399, 0.20146611007620324118, 0.20700370944187380064, + 0.21258877307373610060, 0.21822164655637059599, 0.22390269938713388747, 0.22963232523430270355, + 0.23541094226572765600, 0.24123899354775131610, 0.24711694751469673582, 0.25304529850976585934, + 0.25902456739871074263, 0.26505530225816194029, 0.27113807914102527343, 0.27727350292189771153, + 0.28346220822601251779, 0.28970486044581049771, 0.29600215684985583659, 0.30235482778947976274, + 0.30876363800925192282, 0.31522938806815752222, 0.32175291587920862031, 0.32833509837615239609, + 0.33497685331697116147, 0.34167914123501368412, 0.34844296754987246935, 0.35526938485154714435, + 0.36215949537303321162, 0.36911445366827513952, 0.37613546951445442947, 0.38322381105988364587, + 0.39038080824138948916, 0.39760785649804255208, 0.40490642081148835099, 0.41227804010702462062, + 0.41972433205403823467, 0.42724699830956239880, 0.43484783025466189638, 0.44252871528024661483, + 0.45029164368692696086, 0.45813871627287196483, 0.46607215269457097924, 0.47409430069824960453, + 0.48220764633483869062, 0.49041482528932163741, 0.49871863547658432422, 0.50712205108130458951, + 0.51562823824987205196, 0.52424057267899279809, 0.53296265938998758838, 0.54179835503172412311, + 0.55075179312105527738, 0.55982741271069481791, 0.56902999107472161225, 0.57836468112670231279, + 0.58783705444182052571, 0.59745315095181228217, 0.60721953663260488551, 0.61714337082656248870, + 0.62723248525781456578, 0.63749547734314487428, 0.64794182111855080873, 0.65858200005865368016, + 0.66942766735770616891, 0.68049184100641433355, 0.69178914344603585279, 0.70333609902581741633, + 0.71515150742047704368, 0.72725691835450587793, 0.73967724368333814856, 0.75244155918570380145, + 0.76558417390923599480, 0.77914608594170316563, 0.79317701178385921053, 0.80773829469612111340, + 0.82290721139526200050, 0.83878360531064722379, 0.85550060788506428418, 0.87324304892685358879, + 0.89228165080230272301, 0.91304364799203805999, 0.93628268170837107547, 0.96359969315576759960, + 1 +}; + +template<class Engine> +inline typename boost::make_unsigned<typename Engine::result_type>::type +generate_one_digit(Engine& eng, std::size_t bits) +{ + typedef typename Engine::result_type base_result; + typedef typename boost::make_unsigned<base_result>::type base_unsigned; + + base_unsigned range = + detail::subtract<base_result>()((eng.max)(), (eng.min)()); + base_unsigned y0_mask = (base_unsigned(2) << (bits - 1)) - 1; + base_unsigned y0 = (range + 1) & ~y0_mask; + base_unsigned u; + do { + u = detail::subtract<base_result>()(eng(), (eng.min)()); + } while(y0 != 0 && u > base_unsigned(y0 - 1)); + return u & y0_mask; +} + +template<class RealType, std::size_t w, class Engine> +std::pair<RealType, int> generate_int_float_pair(Engine& eng, boost::mpl::true_) +{ + typedef typename Engine::result_type base_result; + typedef typename boost::make_unsigned<base_result>::type base_unsigned; + + base_unsigned range = + detail::subtract<base_result>()((eng.max)(), (eng.min)()); + + std::size_t m = + (range == (std::numeric_limits<base_unsigned>::max)()) ? + std::numeric_limits<base_unsigned>::digits : + detail::integer_log2(range + 1); + + int bucket = 0; + // process as many full digits as possible into the int part + for(std::size_t i = 0; i < w/m; ++i) { + base_unsigned u = generate_one_digit(eng, m); + bucket = (bucket << m) | u; + } + RealType r; + + const std::size_t digits = std::numeric_limits<RealType>::digits; + { + base_unsigned u = generate_one_digit(eng, m); + base_unsigned mask = (base_unsigned(1) << (w%m)) - 1; + bucket = (bucket << (w%m)) | (mask & u); + const RealType mult = RealType(1)/RealType(base_unsigned(1) << (m - w%m)); + // zero out unused bits + if (m - w%m > digits) { + u &= ~(base_unsigned(1) << (m - digits)); + } + r = RealType(u >> (w%m)) * mult; + } + for(std::size_t i = m - w%m; i + m < digits; ++i) { + base_unsigned u = generate_one_digit(eng, m); + r += u; + r *= RealType(0.5)/RealType(base_unsigned(1) << (m - 1)); + } + if (m - w%m < digits) + { + const std::size_t remaining = (digits - m + w%m) % m; + base_unsigned u = generate_one_digit(eng, m); + r += u & ((base_unsigned(2) << (remaining - 1)) - 1); + const RealType mult = RealType(0.5)/RealType(base_unsigned(1) << (remaining - 1)); + r *= mult; + } + return std::make_pair(r, bucket); +} + +template<class RealType, std::size_t w, class Engine> +inline std::pair<RealType, int> generate_int_float_pair(Engine& eng, boost::mpl::false_) +{ + int bucket = uniform_int_distribution<>(0, (1 << w) - 1)(eng); + RealType r = uniform_01<RealType>()(eng); + return std::make_pair(r, bucket); +} + +template<class RealType, std::size_t w, class Engine> +inline std::pair<RealType, int> generate_int_float_pair(Engine& eng) +{ + typedef typename Engine::result_type base_result; + return generate_int_float_pair<RealType, w>(eng, + boost::is_integral<base_result>()); +} + +template<class RealType = double> +struct unit_normal_distribution +{ + template<class Engine> + RealType operator()(Engine& eng) { + const double * const table_x = normal_table<double>::table_x; + const double * const table_y = normal_table<double>::table_y; + for(;;) { + std::pair<RealType, int> vals = generate_int_float_pair<RealType, 8>(eng); + int i = vals.second; + int sign = (i & 1) * 2 - 1; + i = i >> 1; + RealType x = vals.first * RealType(table_x[i]); + if(x < table_x[i + 1]) return x * sign; + if(i == 0) return generate_tail(eng) * sign; + RealType y = RealType(table_y[i]) + uniform_01<RealType>()(eng) * RealType(table_y[i + 1] - table_y[i]); + if (y < f(x)) return x * sign; + } + } + static RealType f(RealType x) { + using std::exp; + return exp(-x*x/2); + } + template<class Engine> + RealType generate_tail(Engine& eng) { + boost::random::exponential_distribution<RealType> exponential; + const RealType tail_start = RealType(normal_table<double>::table_x[1]); + for(;;) { + RealType x = exponential(eng)/tail_start; + RealType y = exponential(eng); + if(2*y > x*x) return x + tail_start; + } + } +}; + +} + // deterministic Box-Muller method, uses trigonometric functions /** @@ -37,7 +248,7 @@ namespace random { * \random_distribution. Such a distribution produces random numbers * @c x distributed with probability density function * \f$\displaystyle p(x) = - * \frac{1}{\sqrt{2\pi\sigma}} e^{-\frac{(x-\mu)^2}{2\sigma^2}} + * \frac{1}{\sqrt{2\pi}\sigma} e^{-\frac{(x-\mu)^2}{2\sigma^2}} * \f$, * where mean and sigma are the parameters of the distribution. */ @@ -98,8 +309,7 @@ public: */ explicit normal_distribution(const RealType& mean_arg = RealType(0.0), const RealType& sigma_arg = RealType(1.0)) - : _mean(mean_arg), _sigma(sigma_arg), - _r1(0), _r2(0), _cached_rho(0), _valid(false) + : _mean(mean_arg), _sigma(sigma_arg) { BOOST_ASSERT(_sigma >= RealType(0)); } @@ -108,8 +318,7 @@ public: * Constructs a @c normal_distribution object from its parameters. */ explicit normal_distribution(const param_type& parm) - : _mean(parm.mean()), _sigma(parm.sigma()), - _r1(0), _r2(0), _cached_rho(0), _valid(false) + : _mean(parm.mean()), _sigma(parm.sigma()) {} /** Returns the mean of the distribution. */ @@ -131,39 +340,20 @@ public: { _mean = parm.mean(); _sigma = parm.sigma(); - _valid = false; } /** * Effects: Subsequent uses of the distribution do not depend * on values produced by any engine prior to invoking reset. */ - void reset() { _valid = false; } + void reset() { } /** Returns a normal variate. */ template<class Engine> result_type operator()(Engine& eng) { - using std::sqrt; - using std::log; - using std::sin; - using std::cos; - - if(!_valid) { - _r1 = boost::uniform_01<RealType>()(eng); - _r2 = boost::uniform_01<RealType>()(eng); - _cached_rho = sqrt(-result_type(2) * log(result_type(1)-_r2)); - _valid = true; - } else { - _valid = false; - } - // Can we have a boost::mathconst please? - const result_type pi = result_type(3.14159265358979323846); - - return _cached_rho * (_valid ? - cos(result_type(2)*pi*_r1) : - sin(result_type(2)*pi*_r1)) - * _sigma + _mean; + detail::unit_normal_distribution<RealType> impl; + return impl(eng) * _sigma + _mean; } /** Returns a normal variate with parameters specified by @c param. */ @@ -176,17 +366,14 @@ public: /** Writes a @c normal_distribution to a @c std::ostream. */ BOOST_RANDOM_DETAIL_OSTREAM_OPERATOR(os, normal_distribution, nd) { - os << nd._mean << " " << nd._sigma << " " - << nd._valid << " " << nd._cached_rho << " " << nd._r1; + os << nd._mean << " " << nd._sigma; return os; } /** Reads a @c normal_distribution from a @c std::istream. */ BOOST_RANDOM_DETAIL_ISTREAM_OPERATOR(is, normal_distribution, nd) { - is >> std::ws >> nd._mean >> std::ws >> nd._sigma - >> std::ws >> nd._valid >> std::ws >> nd._cached_rho - >> std::ws >> nd._r1; + is >> std::ws >> nd._mean >> std::ws >> nd._sigma; return is; } @@ -196,9 +383,7 @@ public: */ BOOST_RANDOM_DETAIL_EQUALITY_OPERATOR(normal_distribution, lhs, rhs) { - return lhs._mean == rhs._mean && lhs._sigma == rhs._sigma - && lhs._valid == rhs._valid - && (!lhs._valid || (lhs._r1 == rhs._r1 && lhs._r2 == rhs._r2)); + return lhs._mean == rhs._mean && lhs._sigma == rhs._sigma; } /** @@ -209,8 +394,6 @@ public: private: RealType _mean, _sigma; - RealType _r1, _r2, _cached_rho; - bool _valid; }; diff --git a/boost/random/piecewise_constant_distribution.hpp b/boost/random/piecewise_constant_distribution.hpp index dbeadae3a9..697a374087 100644 --- a/boost/random/piecewise_constant_distribution.hpp +++ b/boost/random/piecewise_constant_distribution.hpp @@ -7,7 +7,7 @@ * * See http://www.boost.org for most recent version including documentation. * - * $Id: piecewise_constant_distribution.hpp 79771 2012-07-27 18:15:55Z jewillco $ + * $Id$ */ #ifndef BOOST_RANDOM_PIECEWISE_CONSTANT_DISTRIBUTION_HPP_INCLUDED diff --git a/boost/random/piecewise_linear_distribution.hpp b/boost/random/piecewise_linear_distribution.hpp index b7b6860cbc..861cf429c5 100644 --- a/boost/random/piecewise_linear_distribution.hpp +++ b/boost/random/piecewise_linear_distribution.hpp @@ -7,7 +7,7 @@ * * See http://www.boost.org for most recent version including documentation. * - * $Id: piecewise_linear_distribution.hpp 79771 2012-07-27 18:15:55Z jewillco $ + * $Id$ */ #ifndef BOOST_RANDOM_PIECEWISE_LINEAR_DISTRIBUTION_HPP_INCLUDED diff --git a/boost/random/poisson_distribution.hpp b/boost/random/poisson_distribution.hpp index c1eac37164..759f206e42 100644 --- a/boost/random/poisson_distribution.hpp +++ b/boost/random/poisson_distribution.hpp @@ -8,7 +8,7 @@ * * See http://www.boost.org for most recent version including documentation. * - * $Id: poisson_distribution.hpp 71018 2011-04-05 21:27:52Z steven_watanabe $ + * $Id$ * */ diff --git a/boost/random/random_device.hpp b/boost/random/random_device.hpp index 6c9d872b39..8f3903c953 100644 --- a/boost/random/random_device.hpp +++ b/boost/random/random_device.hpp @@ -6,7 +6,7 @@ * accompanying file LICENSE_1_0.txt or copy at * http://www.boost.org/LICENSE_1_0.txt) * - * $Id: random_device.hpp 71018 2011-04-05 21:27:52Z steven_watanabe $ + * $Id$ * * Revision history * 2000-02-18 Portability fixes (thanks to Beman Dawes) @@ -22,6 +22,7 @@ #include <boost/config.hpp> #include <boost/noncopyable.hpp> #include <boost/random/detail/auto_link.hpp> +#include <boost/system/config.hpp> // force autolink to find Boost.System namespace boost { namespace random { diff --git a/boost/random/random_number_generator.hpp b/boost/random/random_number_generator.hpp index f8eaf01bd5..ac975e3298 100644 --- a/boost/random/random_number_generator.hpp +++ b/boost/random/random_number_generator.hpp @@ -7,7 +7,7 @@ * * See http://www.boost.org for most recent version including documentation. * - * $Id: random_number_generator.hpp 71018 2011-04-05 21:27:52Z steven_watanabe $ + * $Id$ * * Revision history * 2001-02-18 moved to individual header files diff --git a/boost/random/ranlux.hpp b/boost/random/ranlux.hpp index 88476665cf..82a7ca66f1 100644 --- a/boost/random/ranlux.hpp +++ b/boost/random/ranlux.hpp @@ -7,7 +7,7 @@ * * See http://www.boost.org for most recent version including documentation. * - * $Id: ranlux.hpp 71018 2011-04-05 21:27:52Z steven_watanabe $ + * $Id$ * * Revision history * 2001-02-18 created @@ -37,7 +37,7 @@ namespace detail { * The levels are given in * * @blockquote - * "RANLUX: A Fortran implementation ofthe high-quality + * "RANLUX: A Fortran implementation of the high-quality * pseudorandom number generator of Luescher", F. James, * Computer Physics Communications 79 (1994) 111-114 * @endblockquote diff --git a/boost/random/seed_seq.hpp b/boost/random/seed_seq.hpp index 44798f21bc..9579d5bb9b 100644 --- a/boost/random/seed_seq.hpp +++ b/boost/random/seed_seq.hpp @@ -7,7 +7,7 @@ * * See http://www.boost.org for most recent version including documentation. * - * $Id: seed_seq.hpp 79771 2012-07-27 18:15:55Z jewillco $ + * $Id$ * */ diff --git a/boost/random/shuffle_order.hpp b/boost/random/shuffle_order.hpp index 1c8d875d5b..646c09bafa 100644 --- a/boost/random/shuffle_order.hpp +++ b/boost/random/shuffle_order.hpp @@ -8,7 +8,7 @@ * * See http://www.boost.org for most recent version including documentation. * - * $Id: shuffle_order.hpp 71018 2011-04-05 21:27:52Z steven_watanabe $ + * $Id$ * */ @@ -98,7 +98,7 @@ public: */ explicit shuffle_order_engine(const base_type & rng) : _rng(rng) { init(); } -#ifndef BOOST_NO_RVALUE_REFERENCES +#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES explicit shuffle_order_engine(base_type&& rng) : _rng(rng) { init(); } #endif diff --git a/boost/random/shuffle_output.hpp b/boost/random/shuffle_output.hpp index 44b823f573..478e1029bd 100644 --- a/boost/random/shuffle_output.hpp +++ b/boost/random/shuffle_output.hpp @@ -7,7 +7,7 @@ * * See http://www.boost.org for most recent version including documentation. * - * $Id: shuffle_output.hpp 71018 2011-04-05 21:27:52Z steven_watanabe $ + * $Id$ * * Revision history * 2001-02-18 moved to individual header files @@ -28,13 +28,13 @@ template<typename URNG, int k, class shuffle_output : public shuffle_order_engine<URNG, k> { typedef shuffle_order_engine<URNG, k> base_t; - typedef typename base_t::result_type result_type; public: + typedef typename base_t::result_type result_type; shuffle_output() {} template<class T> - shuffle_output(T& arg) : base_t(arg) {} + explicit shuffle_output(T& arg) : base_t(arg) {} template<class T> - shuffle_output(const T& arg) : base_t(arg) {} + explicit shuffle_output(const T& arg) : base_t(arg) {} template<class It> shuffle_output(It& first, It last) : base_t(first, last) {} result_type min BOOST_PREVENT_MACRO_SUBSTITUTION () diff --git a/boost/random/student_t_distribution.hpp b/boost/random/student_t_distribution.hpp index 665afdb556..e28b0e3bfb 100644 --- a/boost/random/student_t_distribution.hpp +++ b/boost/random/student_t_distribution.hpp @@ -7,7 +7,7 @@ * * See http://www.boost.org for most recent version including documentation. * - * $Id: student_t_distribution.hpp 71018 2011-04-05 21:27:52Z steven_watanabe $ + * $Id$ */ #ifndef BOOST_RANDOM_STUDENT_T_DISTRIBUTION_HPP diff --git a/boost/random/subtract_with_carry.hpp b/boost/random/subtract_with_carry.hpp index 298eb33475..dc430e6d55 100644 --- a/boost/random/subtract_with_carry.hpp +++ b/boost/random/subtract_with_carry.hpp @@ -7,7 +7,7 @@ * * See http://www.boost.org for most recent version including documentation. * - * $Id: subtract_with_carry.hpp 72951 2011-07-07 04:57:37Z steven_watanabe $ + * $Id$ * * Revision history * 2002-03-02 created @@ -161,7 +161,7 @@ public: IntType, value) { typedef linear_congruential_engine<uint32_t,40014,0,2147483563> gen_t; - gen_t intgen(static_cast<boost::uint32_t>(value)); + gen_t intgen(static_cast<boost::uint32_t>(value == 0 ? default_seed : value)); detail::generator_seed_seq<gen_t> gen(intgen); seed(gen); } @@ -354,7 +354,7 @@ public: boost::uint32_t, value) { init_modulus(); seed(value); } /** - * Creates a new \subtract_with_carry_01_engine and seeds with with values + * Creates a new \subtract_with_carry_01_engine and seeds with values * produced by seq.generate(). */ BOOST_RANDOM_DETAIL_SEED_SEQ_CONSTRUCTOR(subtract_with_carry_01_engine, @@ -392,7 +392,7 @@ public: boost::uint32_t, value) { typedef linear_congruential_engine<uint32_t, 40014, 0, 2147483563> gen_t; - gen_t intgen(value); + gen_t intgen(value == 0 ? default_seed : value); detail::generator_seed_seq<gen_t> gen(intgen); seed(gen); } diff --git a/boost/random/taus88.hpp b/boost/random/taus88.hpp index c9d381044c..68214f3aed 100644 --- a/boost/random/taus88.hpp +++ b/boost/random/taus88.hpp @@ -8,7 +8,7 @@ * * See http://www.boost.org/libs/random for documentation. * - * $Id: taus88.hpp 71018 2011-04-05 21:27:52Z steven_watanabe $ + * $Id$ * */ diff --git a/boost/random/triangle_distribution.hpp b/boost/random/triangle_distribution.hpp index 8776000982..5ac6604713 100644 --- a/boost/random/triangle_distribution.hpp +++ b/boost/random/triangle_distribution.hpp @@ -8,7 +8,7 @@ * * See http://www.boost.org for most recent version including documentation. * - * $Id: triangle_distribution.hpp 71018 2011-04-05 21:27:52Z steven_watanabe $ + * $Id$ * * Revision history * 2001-02-18 moved to individual header files diff --git a/boost/random/uniform_01.hpp b/boost/random/uniform_01.hpp index d32a08546f..9710b766ea 100644 --- a/boost/random/uniform_01.hpp +++ b/boost/random/uniform_01.hpp @@ -7,7 +7,7 @@ * * See http://www.boost.org for most recent version including documentation. * - * $Id: uniform_01.hpp 71018 2011-04-05 21:27:52Z steven_watanabe $ + * $Id$ * * Revision history * 2001-02-18 moved to individual header files @@ -128,7 +128,7 @@ public: BOOST_STATIC_CONSTANT(bool, has_fixed_range = false); -#if !defined(BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS) && !(defined(BOOST_MSVC) && BOOST_MSVC <= 1300) +#if !defined(BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS) BOOST_STATIC_ASSERT(!std::numeric_limits<RealType>::is_integer); #endif diff --git a/boost/random/uniform_int.hpp b/boost/random/uniform_int.hpp index 7ae3b92a0f..4362652593 100644 --- a/boost/random/uniform_int.hpp +++ b/boost/random/uniform_int.hpp @@ -7,7 +7,7 @@ * * See http://www.boost.org for most recent version including documentation. * - * $Id: uniform_int.hpp 71018 2011-04-05 21:27:52Z steven_watanabe $ + * $Id$ * * Revision history * 2001-04-08 added min<max assertion (N. Becker) diff --git a/boost/random/uniform_int_distribution.hpp b/boost/random/uniform_int_distribution.hpp index 0612028ea9..a175025edc 100644 --- a/boost/random/uniform_int_distribution.hpp +++ b/boost/random/uniform_int_distribution.hpp @@ -8,7 +8,7 @@ * * See http://www.boost.org for most recent version including documentation. * - * $Id: uniform_int_distribution.hpp 71018 2011-04-05 21:27:52Z steven_watanabe $ + * $Id$ * * Revision history * 2001-04-08 added min<max assertion (N. Becker) diff --git a/boost/random/uniform_on_sphere.hpp b/boost/random/uniform_on_sphere.hpp index 04071dc2b6..fdd4e950bb 100644 --- a/boost/random/uniform_on_sphere.hpp +++ b/boost/random/uniform_on_sphere.hpp @@ -8,7 +8,7 @@ * * See http://www.boost.org for most recent version including documentation. * - * $Id: uniform_on_sphere.hpp 71018 2011-04-05 21:27:52Z steven_watanabe $ + * $Id$ * * Revision history * 2001-02-18 moved to individual header files @@ -152,7 +152,7 @@ public: * Effects: Subsequent uses of the distribution do not depend * on values produced by any engine prior to invoking reset. */ - void reset() { _normal.reset(); } + void reset() {} /** * Returns a point uniformly distributed over the surface of @@ -161,18 +161,73 @@ public: template<class Engine> const result_type & operator()(Engine& eng) { - RealType sqsum = 0; - for(typename Cont::iterator it = _container.begin(); - it != _container.end(); - ++it) { - RealType val = _normal(eng); - *it = val; - sqsum += val * val; - } using std::sqrt; - // for all i: result[i] /= sqrt(sqsum) - std::transform(_container.begin(), _container.end(), _container.begin(), - std::bind2nd(std::divides<RealType>(), sqrt(sqsum))); + switch(_dim) + { + case 0: break; + case 1: + { + if(uniform_01<RealType>()(eng) < 0.5) { + *_container.begin() = -1; + } else { + *_container.begin() = 1; + } + } + case 2: + { + uniform_01<RealType> uniform; + RealType sqsum; + RealType x, y; + do { + x = uniform(eng) * 2 - 1; + y = uniform(eng) * 2 - 1; + sqsum = x*x + y*y; + } while(sqsum == 0 || sqsum > 1); + RealType mult = 1/sqrt(sqsum); + typename Cont::iterator iter = _container.begin(); + *iter = x * mult; + iter++; + *iter = y * mult; + break; + } + case 3: + { + uniform_01<RealType> uniform; + RealType sqsum; + RealType x, y, z; + do { + x = uniform(eng) * 2 - 1; + y = uniform(eng) * 2 - 1; + sqsum = x*x + y*y; + } while(sqsum > 1); + RealType mult = 2 * sqrt(1 - sqsum); + typename Cont::iterator iter = _container.begin(); + *iter = x * mult; + ++iter; + *iter = y * mult; + ++iter; + *iter = 2 * sqsum - 1; + break; + } + default: + { + detail::unit_normal_distribution<RealType> normal; + RealType sqsum; + do { + sqsum = 0; + for(typename Cont::iterator it = _container.begin(); + it != _container.end(); + ++it) { + RealType val = normal(eng); + *it = val; + sqsum += val * val; + } + } while(sqsum == 0); + // for all i: result[i] /= sqrt(sqsum) + std::transform(_container.begin(), _container.end(), _container.begin(), + std::bind2nd(std::multiplies<RealType>(), 1/sqrt(sqsum))); + } + } return _container; } @@ -206,7 +261,7 @@ public: * sequences of values, given equal generators. */ BOOST_RANDOM_DETAIL_EQUALITY_OPERATOR(uniform_on_sphere, lhs, rhs) - { return lhs._dim == rhs._dim && lhs._normal == rhs._normal; } + { return lhs._dim == rhs._dim; } /** * Returns true if the two distributions may produce different @@ -215,7 +270,6 @@ public: BOOST_RANDOM_DETAIL_INEQUALITY_OPERATOR(uniform_on_sphere) private: - normal_distribution<RealType> _normal; result_type _container; int _dim; }; diff --git a/boost/random/uniform_real.hpp b/boost/random/uniform_real.hpp index 396072e2d8..c98626e779 100644 --- a/boost/random/uniform_real.hpp +++ b/boost/random/uniform_real.hpp @@ -7,7 +7,7 @@ * * See http://www.boost.org for most recent version including documentation. * - * $Id: uniform_real.hpp 71018 2011-04-05 21:27:52Z steven_watanabe $ + * $Id$ * * Revision history * 2001-04-08 added min<max assertion (N. Becker) @@ -63,7 +63,7 @@ public: RealType max_arg = RealType(1.0)) : base_type(min_arg, max_arg) { - BOOST_ASSERT(min_arg <= max_arg); + BOOST_ASSERT(min_arg < max_arg); } /** Constructs a uniform_real distribution from its parameters. */ diff --git a/boost/random/uniform_real_distribution.hpp b/boost/random/uniform_real_distribution.hpp index 61b235a31c..437ee69330 100644 --- a/boost/random/uniform_real_distribution.hpp +++ b/boost/random/uniform_real_distribution.hpp @@ -8,7 +8,7 @@ * * See http://www.boost.org for most recent version including documentation. * - * $Id: uniform_real_distribution.hpp 71018 2011-04-05 21:27:52Z steven_watanabe $ + * $Id$ * */ @@ -36,7 +36,6 @@ T generate_uniform_real( { for(;;) { typedef T result_type; - typedef typename Engine::result_type base_result; result_type numerator = static_cast<T>(eng() - (eng.min)()); result_type divisor = static_cast<T>((eng.max)() - (eng.min)()); BOOST_ASSERT(divisor > 0); @@ -66,6 +65,8 @@ T generate_uniform_real( template<class Engine, class T> inline T generate_uniform_real(Engine& eng, T min_value, T max_value) { + if(max_value / 2 - min_value / 2 > (std::numeric_limits<T>::max)() / 2) + return 2 * generate_uniform_real(eng, min_value / 2, max_value / 2); typedef typename Engine::result_type base_result; return generate_uniform_real(eng, min_value, max_value, boost::is_integral<base_result>()); @@ -100,7 +101,7 @@ public: RealType max_arg = RealType(1.0)) : _min(min_arg), _max(max_arg) { - BOOST_ASSERT(_min <= _max); + BOOST_ASSERT(_min < _max); } /** Returns the minimum value of the distribution. */ @@ -154,7 +155,7 @@ public: RealType max_arg = RealType(1.0)) : _min(min_arg), _max(max_arg) { - BOOST_ASSERT(min_arg <= max_arg); + BOOST_ASSERT(min_arg < max_arg); } /** Constructs a uniform_real_distribution from its parameters. */ explicit uniform_real_distribution(const param_type& parm) diff --git a/boost/random/uniform_smallint.hpp b/boost/random/uniform_smallint.hpp index 745fa8e93b..4f5f437517 100644 --- a/boost/random/uniform_smallint.hpp +++ b/boost/random/uniform_smallint.hpp @@ -7,7 +7,7 @@ * * See http://www.boost.org for most recent version including documentation. * - * $Id: uniform_smallint.hpp 71018 2011-04-05 21:27:52Z steven_watanabe $ + * $Id$ * * Revision history * 2001-04-08 added min<max assertion (N. Becker) diff --git a/boost/random/variate_generator.hpp b/boost/random/variate_generator.hpp index ac698006c2..6d5aac4e47 100644 --- a/boost/random/variate_generator.hpp +++ b/boost/random/variate_generator.hpp @@ -8,7 +8,7 @@ * * See http://www.boost.org for most recent version including documentation. * - * $Id: variate_generator.hpp 71018 2011-04-05 21:27:52Z steven_watanabe $ + * $Id$ * */ diff --git a/boost/random/weibull_distribution.hpp b/boost/random/weibull_distribution.hpp index 2c8a26f770..55e3c04903 100644 --- a/boost/random/weibull_distribution.hpp +++ b/boost/random/weibull_distribution.hpp @@ -7,7 +7,7 @@ * * See http://www.boost.org for most recent version including documentation. * - * $Id: weibull_distribution.hpp 71018 2011-04-05 21:27:52Z steven_watanabe $ + * $Id$ */ #ifndef BOOST_RANDOM_WEIBULL_DISTRIBUTION_HPP diff --git a/boost/random/xor_combine.hpp b/boost/random/xor_combine.hpp index d997a1c1a0..fe8a58b40f 100644 --- a/boost/random/xor_combine.hpp +++ b/boost/random/xor_combine.hpp @@ -7,7 +7,7 @@ * * See http://www.boost.org for most recent version including documentation. * - * $Id: xor_combine.hpp 71018 2011-04-05 21:27:52Z steven_watanabe $ + * $Id$ * */ @@ -24,6 +24,7 @@ #include <boost/random/detail/config.hpp> #include <boost/random/detail/seed.hpp> #include <boost/random/detail/seed_impl.hpp> +#include <boost/random/detail/operators.hpp> namespace boost { namespace random { |