diff --git a/include/boost/random/additive_combine.hpp b/include/boost/random/additive_combine.hpp index d45b9d1..050e74d 100644 --- a/include/boost/random/additive_combine.hpp +++ b/include/boost/random/additive_combine.hpp @@ -65,8 +65,8 @@ public: void seed(typename MLCG1::result_type seed1, typename MLCG2::result_type seed2) { - _mlcg1.seed(seed1); - _mlcg2.seed(seed2); + _mlcg1(seed1); + _mlcg2(seed2); } template void seed(It& first, It last) diff --git a/include/boost/random/detail/const_mod.hpp b/include/boost/random/detail/const_mod.hpp index fbedd8e..ccfc7ab 100644 --- a/include/boost/random/detail/const_mod.hpp +++ b/include/boost/random/detail/const_mod.hpp @@ -43,10 +43,10 @@ namespace detail { template static IntType add(IntType m, IntType x, IntType c) { - if (x < m - c) - return x + c; - else - return x - (m-c); + x += (c-m); + if(x < 0) + x += m; + return x; } }; diff --git a/include/boost/random/detail/signed_unsigned_compare.hpp b/include/boost/random/detail/signed_unsigned_compare.hpp new file mode 100644 index 0000000..b421862 --- /dev/null +++ b/include/boost/random/detail/signed_unsigned_compare.hpp @@ -0,0 +1,91 @@ +/* boost random/detail/signed_unsigned_compare.hpp header file + * + * Copyright Jens Maurer 2000-2001 + * 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. + * + * Revision history + */ + + +#ifndef BOOST_RANDOM_DETAIL_SIGNED_UNSIGNED_COMPARE +#define BOOST_RANDOM_DETAIL_SIGNED_UNSIGNED_COMPARE + +#include + +namespace boost { +namespace random { + +/* + * Correctly compare two numbers whose types possibly differ in signedness. + * See boost::numeric_cast<> for the general idea. + * Most "if" statements involve only compile-time constants, so the + * optimizing compiler can do its job easily. + * + * With most compilers, the straightforward implementation produces a + * bunch of (legitimate) warnings. Some template magic helps, though. + */ + +namespace detail { +template +struct do_compare +{ }; + +template<> +struct do_compare +{ + // cast to the larger type is automatic with built-in types + template + static bool equal(T1 x, T2 y) { return x == y; } + template + static bool lessthan(T1 x, T2 y) { return x < y; } +}; + +template<> +struct do_compare : do_compare +{ }; + +template<> +struct do_compare +{ + template + static bool equal(T1 x, T2 y) { return x >= 0 && static_cast(x) == y; } + template + static bool lessthan(T1 x, T2 y) { return x < 0 || static_cast(x) < y; } +}; + +template<> +struct do_compare +{ + template + static bool equal(T1 x, T2 y) { return y >= 0 && x == static_cast(y); } + template + static bool lessthan(T1 x, T2 y) { return y >= 0 && x < static_cast(y); } +}; + +} // namespace detail + + +template +int equal_signed_unsigned(T1 x, T2 y) +{ + typedef std::numeric_limits x_traits; + typedef std::numeric_limits y_traits; + return detail::do_compare::equal(x, y); +} + +template +int lessthan_signed_unsigned(T1 x, T2 y) +{ + typedef std::numeric_limits x_traits; + typedef std::numeric_limits y_traits; + return detail::do_compare::lessthan(x, y); +} + +} // namespace random +} // namespace boost + +#endif // BOOST_RANDOM_DETAIL_SIGNED_UNSIGNED_COMPARE diff --git a/include/boost/random/detail/signed_unsigned_tools.hpp b/include/boost/random/detail/signed_unsigned_tools.hpp deleted file mode 100644 index aed3b36..0000000 --- a/include/boost/random/detail/signed_unsigned_tools.hpp +++ /dev/null @@ -1,164 +0,0 @@ -/* boost random/detail/signed_unsigned_tools.hpp header file - * - * Copyright Jens Maurer 2006 - * 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. - */ - -#ifndef BOOST_RANDOM_DETAIL_SIGNED_UNSIGNED_TOOLS -#define BOOST_RANDOM_DETAIL_SIGNED_UNSIGNED_TOOLS - -#include -#include - -namespace boost { -namespace random { -namespace detail { - -/* - * Given an (integral) type T, returns the type "unsigned T". - * (type_traits appears to be lacking the feature) - */ - -template -struct make_unsigned { }; - -template<> -struct make_unsigned -{ - typedef unsigned char type; -}; - -template<> -struct make_unsigned -{ - typedef unsigned char type; -}; - -template<> -struct make_unsigned -{ - typedef unsigned char type; -}; - -template<> -struct make_unsigned -{ - typedef unsigned short type; -}; - -template<> -struct make_unsigned -{ - typedef unsigned short type; -}; - -template<> -struct make_unsigned -{ - typedef unsigned int type; -}; - -template<> -struct make_unsigned -{ - typedef unsigned int type; -}; - -template<> -struct make_unsigned -{ - typedef unsigned long type; -}; - -template<> -struct make_unsigned -{ - typedef unsigned long type; -}; - -#ifdef BOOST_HAS_LONG_LONG -template<> -struct make_unsigned -{ - typedef unsigned long long type; -}; - -template<> -struct make_unsigned -{ - typedef unsigned long long type; -}; -#endif - - -/* - * Compute x - y, we know that x >= y, return an unsigned value. - */ - -template::is_signed> -struct subtract { }; - -template -struct subtract -{ - typedef T result_type; - result_type operator()(T x, T y) { return x - y; } -}; - -template -struct subtract -{ - typedef typename make_unsigned::type result_type; - result_type operator()(T x, T y) - { - if (y >= 0) // because x >= y, it follows that x >= 0, too - return result_type(x) - result_type(y); - if (x >= 0) // y < 0 - // avoid the nasty two's complement case for y == min() - return result_type(x) + result_type(-(y+1)) + 1; - // both x and y are negative: no signed overflow - return result_type(x - y); - } -}; - -/* - * Compute x + y, x is unsigned, result fits in type of "y". - */ - -template::is_signed> -struct add { }; - -template -struct add -{ - typedef T2 result_type; - result_type operator()(T1 x, T2 y) { return x + y; } -}; - -template -struct add -{ - typedef T2 result_type; - result_type operator()(T1 x, T2 y) - { - if (y >= 0) - return x + y; - // y < 0 - if (x >= T1(-(y+1))) // result >= 0 after subtraction - // avoid the nasty two's complement edge case for y == min() - return T2(x - T1(-(y+1)) - 1); - // abs(x) < abs(y), thus T2 able to represent x - return T2(x) + y; - } -}; - -} // namespace detail -} // namespace random -} // namespace boost - -#endif // BOOST_RANDOM_DETAIL_SIGNED_UNSIGNED_TOOLS - diff --git a/include/boost/random/inversive_congruential.hpp b/include/boost/random/inversive_congruential.hpp index 2378884..82798b2 100644 --- a/include/boost/random/inversive_congruential.hpp +++ b/include/boost/random/inversive_congruential.hpp @@ -18,7 +18,6 @@ #include #include -#include #include #include #include diff --git a/include/boost/random/lognormal_distribution.hpp b/include/boost/random/lognormal_distribution.hpp index 10c39e3..9da9322 100644 --- a/include/boost/random/lognormal_distribution.hpp +++ b/include/boost/random/lognormal_distribution.hpp @@ -60,8 +60,8 @@ public: // compiler-generated copy ctor and assignment operator are fine - RealType mean() const { return _mean; } - RealType sigma() const { return _sigma; } + RealType& mean() const { return _mean; } + RealType& sigma() const { return _sigma; } void reset() { _normal.reset(); } template diff --git a/include/boost/random/uniform_01.hpp b/include/boost/random/uniform_01.hpp index 5e1e8e7..8d8c200 100644 --- a/include/boost/random/uniform_01.hpp +++ b/include/boost/random/uniform_01.hpp @@ -55,11 +55,7 @@ public: void reset() { } result_type operator()() { - for (;;) { - result_type result = result_type(_rng() - (_rng.min)()) * _factor; - if (result < result_type(1)) - return result; - } + return result_type(_rng() - (_rng.min)()) * _factor; } #if !defined(BOOST_NO_OPERATORS_IN_NAMESPACE) && !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS) diff --git a/include/boost/random/uniform_int.hpp b/include/boost/random/uniform_int.hpp index 6ce6727..3e3f6d2 100644 --- a/include/boost/random/uniform_int.hpp +++ b/include/boost/random/uniform_int.hpp @@ -24,7 +24,7 @@ #include #include #include -#include +#include #ifdef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS #include #endif @@ -38,7 +38,6 @@ class uniform_int public: typedef IntType input_type; typedef IntType result_type; - typedef typename random::detail::make_unsigned::type range_type; explicit uniform_int(IntType min = 0, IntType max = 9) : _min(min), _max(max) @@ -60,47 +59,43 @@ public: result_type operator()(Engine& eng) { typedef typename Engine::result_type base_result; - // ranges are always unsigned - typedef typename random::detail::make_unsigned::type base_unsigned; - const base_result bmin = (eng.min)(); - const base_unsigned brange = - random::detail::subtract()((eng.max)(), (eng.min)()); + base_result bmin = (eng.min)(); + base_result brange = (eng.max)() - (eng.min)(); if(_range == 0) { return _min; - } else if(brange == _range) { + } else if(random::equal_signed_unsigned(brange, _range)) { // this will probably never happen in real life // basically nothing to do; just take care we don't overflow / underflow - base_unsigned v = random::detail::subtract()(eng(), bmin); - return random::detail::add()(v, _min); - } else if(brange < _range) { + return static_cast(eng() - bmin) + _min; + } else if(random::lessthan_signed_unsigned(brange, _range)) { // use rejection method to handle things like 0..3 --> 0..4 for(;;) { // concatenate several invocations of the base RNG // take extra care to avoid overflows - range_type limit; - if(_range == (std::numeric_limits::max)()) { - limit = _range/(range_type(brange)+1); - if(_range % range_type(brange)+1 == range_type(brange)) + result_type limit; + if(_range == (std::numeric_limits::max)()) { + limit = _range/(result_type(brange)+1); + if(_range % result_type(brange)+1 == result_type(brange)) ++limit; } else { - limit = (_range+1)/(range_type(brange)+1); + limit = (_range+1)/(result_type(brange)+1); } // We consider "result" as expressed to base (brange+1): // For every power of (brange+1), we determine a random factor - range_type result = range_type(0); - range_type mult = range_type(1); + result_type result = result_type(0); + result_type mult = result_type(1); while(mult <= limit) { - result += random::detail::subtract()(eng(), bmin) * mult; - mult *= range_type(brange)+range_type(1); + result += (eng() - bmin) * mult; + mult *= result_type(brange)+result_type(1); } if(mult == limit) // _range+1 is an integer power of brange+1: no rejections required return result; // _range/mult < brange+1 -> no endless loop - result += uniform_int(0, _range/mult)(eng) * mult; + result += uniform_int(0, _range/mult)(eng) * mult; if(result <= _range) - return random::detail::add()(result, _min); + return result + _min; } } else { // brange > range if(brange / _range > 4 /* quantization_cutoff */ ) { @@ -110,12 +105,11 @@ public: } else { // use rejection method to handle cases like 0..5 -> 0..4 for(;;) { - base_unsigned result = - random::detail::subtract()(eng(), bmin); + base_result result = eng() - bmin; // result and range are non-negative, and result is possibly larger // than range, so the cast is safe - if(result <= static_cast(_range)) - return random::detail::add()(result, _min); + if(result <= static_cast(_range)) + return result + _min; } } } @@ -147,13 +141,10 @@ public: private: void init() { - _range = random::detail::subtract()(_max, _min); + _range = _max - _min; } - - // The result_type may be signed or unsigned, but the _range is always - // unsigned. - result_type _min, _max; - range_type _range; + + result_type _min, _max, _range; }; } // namespace boost