diff -r 000000000000 -r e4d67989cc36 ossrv_pub/boost_apis/boost/random/subtract_with_carry.hpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ossrv_pub/boost_apis/boost/random/subtract_with_carry.hpp Tue Feb 02 02:01:42 2010 +0200 @@ -0,0 +1,445 @@ +/* boost random/subtract_with_carry.hpp header file + * + * Copyright Jens Maurer 2002 + * 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: subtract_with_carry.hpp,v 1.24 2005/05/21 15:57:00 dgregor Exp $ + * + * Revision history + * 2002-03-02 created + */ + +#ifndef BOOST_RANDOM_SUBTRACT_WITH_CARRY_HPP +#define BOOST_RANDOM_SUBTRACT_WITH_CARRY_HPP + +#include +#include +#include // std::equal +#include +#include // std::pow +#include +#include +#include +#include +#include +#include + + +namespace boost { +namespace random { + +#if BOOST_WORKAROUND(_MSC_FULL_VER, BOOST_TESTED_AT(13102292)) && BOOST_MSVC > 1300 +# define BOOST_RANDOM_EXTRACT_SWC_01 +#endif + +#if defined(__APPLE_CC__) && defined(__GNUC__) && (__GNUC__ == 3) && (__GNUC_MINOR__ <= 3) +# define BOOST_RANDOM_EXTRACT_SWC_01 +#endif + +# ifdef BOOST_RANDOM_EXTRACT_SWC_01 +namespace detail +{ + template + void extract_subtract_with_carry_01( + IStream& is + , SubtractWithCarry& f + , RealType& carry + , RealType* x + , RealType modulus) + { + RealType value; + for(unsigned int j = 0; j < f.long_lag; ++j) { + is >> value >> std::ws; + x[j] = value / modulus; + } + is >> value >> std::ws; + carry = value / modulus; + } +} +# endif +// subtract-with-carry generator +// Marsaglia and Zaman + +template +class subtract_with_carry +{ +public: + typedef IntType result_type; + BOOST_STATIC_CONSTANT(bool, has_fixed_range = true); + BOOST_STATIC_CONSTANT(result_type, min_value = 0); + BOOST_STATIC_CONSTANT(result_type, max_value = m-1); + BOOST_STATIC_CONSTANT(result_type, modulus = m); + BOOST_STATIC_CONSTANT(unsigned int, long_lag = r); + BOOST_STATIC_CONSTANT(unsigned int, short_lag = s); + + subtract_with_carry() { + // MSVC fails BOOST_STATIC_ASSERT with std::numeric_limits at class scope +#ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS + BOOST_STATIC_ASSERT(std::numeric_limits::is_signed); + BOOST_STATIC_ASSERT(std::numeric_limits::is_integer); +#endif + seed(); + } + explicit subtract_with_carry(uint32_t value) { seed(value); } + template + explicit subtract_with_carry(Generator & gen) { seed(gen); } + template subtract_with_carry(It& first, It last) { seed(first,last); } + + // compiler-generated copy ctor and assignment operator are fine + + void seed(uint32_t value = 19780503u) + { + random::linear_congruential intgen(value); + seed(intgen); + } + + // For GCC, moving this function out-of-line prevents inlining, which may + // reduce overall object code size. However, MSVC does not grok + // out-of-line template member functions. + template + void seed(Generator & gen) + { + // I could have used std::generate_n, but it takes "gen" by value + for(unsigned int j = 0; j < long_lag; ++j) + x[j] = gen() % modulus; + carry = (x[long_lag-1] == 0); + k = 0; + } + + template + void seed(It& first, It last) + { + unsigned int j; + for(j = 0; j < long_lag && first != last; ++j, ++first) + x[j] = *first % modulus; + if(first == last && j < long_lag) + throw std::invalid_argument("subtract_with_carry::seed"); + carry = (x[long_lag-1] == 0); + k = 0; + } + + result_type min BOOST_PREVENT_MACRO_SUBSTITUTION () const { return min_value; } + result_type max BOOST_PREVENT_MACRO_SUBSTITUTION () const { return max_value; } + + result_type operator()() + { + int short_index = k - short_lag; + if(short_index < 0) + short_index += long_lag; + IntType delta; + if (x[short_index] >= x[k] + carry) { + // x(n) >= 0 + delta = x[short_index] - (x[k] + carry); + carry = 0; + } else { + // x(n) < 0 + delta = modulus - x[k] - carry + x[short_index]; + carry = 1; + } + x[k] = delta; + ++k; + if(k >= long_lag) + k = 0; + return delta; + } + +public: + static bool validation(result_type x) { return x == val; } + +#ifndef BOOST_NO_OPERATORS_IN_NAMESPACE + +#ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS + template + friend std::basic_ostream& + operator<<(std::basic_ostream& os, + const subtract_with_carry& f) + { + for(unsigned int j = 0; j < f.long_lag; ++j) + os << f.compute(j) << " "; + os << f.carry << " "; + return os; + } + + template + friend std::basic_istream& + operator>>(std::basic_istream& is, subtract_with_carry& f) + { + for(unsigned int j = 0; j < f.long_lag; ++j) + is >> f.x[j] >> std::ws; + is >> f.carry >> std::ws; + f.k = 0; + return is; + } +#endif + + friend bool operator==(const subtract_with_carry& x, const subtract_with_carry& y) + { + for(unsigned int j = 0; j < r; ++j) + if(x.compute(j) != y.compute(j)) + return false; + return true; + } + + friend bool operator!=(const subtract_with_carry& x, const subtract_with_carry& y) + { return !(x == y); } +#else + // Use a member function; Streamable concept not supported. + bool operator==(const subtract_with_carry& rhs) const + { + for(unsigned int j = 0; j < r; ++j) + if(compute(j) != rhs.compute(j)) + return false; + return true; + } + + bool operator!=(const subtract_with_carry& rhs) const + { return !(*this == rhs); } +#endif + +private: + // returns x(i-r+index), where index is in 0..r-1 + IntType compute(unsigned int index) const + { + return x[(k+index) % long_lag]; + } + + // state representation; next output (state) is x(i) + // x[0] ... x[k] x[k+1] ... x[long_lag-1] represents + // x(i-k) ... x(i) x(i+1) ... x(i-k+long_lag-1) + // speed: base: 20-25 nsec + // ranlux_4: 230 nsec, ranlux_7: 430 nsec, ranlux_14: 810 nsec + // This state representation makes operator== and save/restore more + // difficult, because we've already computed "too much" and thus + // have to undo some steps to get at x(i-r) etc. + + // state representation: next output (state) is x(i) + // x[0] ... x[k] x[k+1] ... x[long_lag-1] represents + // x(i-k) ... x(i) x(i-long_lag+1) ... x(i-k-1) + // speed: base 28 nsec + // ranlux_4: 370 nsec, ranlux_7: 688 nsec, ranlux_14: 1343 nsec + IntType x[long_lag]; + unsigned int k; + int carry; +}; + +#ifndef BOOST_NO_INCLASS_MEMBER_INITIALIZATION +// A definition is required even for integral static constants +template +const bool subtract_with_carry::has_fixed_range; +template +const IntType subtract_with_carry::min_value; +template +const IntType subtract_with_carry::max_value; +template +const IntType subtract_with_carry::modulus; +template +const unsigned int subtract_with_carry::long_lag; +template +const unsigned int subtract_with_carry::short_lag; +#endif + + +// use a floating-point representation to produce values in [0..1) +template +class subtract_with_carry_01 +{ +public: + typedef RealType result_type; + BOOST_STATIC_CONSTANT(bool, has_fixed_range = false); + BOOST_STATIC_CONSTANT(int, word_size = w); + BOOST_STATIC_CONSTANT(unsigned int, long_lag = r); + BOOST_STATIC_CONSTANT(unsigned int, short_lag = s); + +#ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS + BOOST_STATIC_ASSERT(!std::numeric_limits::is_integer); +#endif + + subtract_with_carry_01() { init_modulus(); seed(); } + explicit subtract_with_carry_01(uint32_t value) + { init_modulus(); seed(value); } + template subtract_with_carry_01(It& first, It last) + { init_modulus(); seed(first,last); } + +private: + void init_modulus() + { +#ifndef BOOST_NO_STDC_NAMESPACE + // allow for Koenig lookup + using std::pow; +#endif + _modulus = pow(RealType(2), word_size); + } + +public: + // compiler-generated copy ctor and assignment operator are fine + + void seed(uint32_t value = 19780503u) + { +#ifndef BOOST_NO_STDC_NAMESPACE + // allow for Koenig lookup + using std::fmod; +#endif + random::linear_congruential gen(value); + unsigned long array[(w+31)/32 * long_lag]; + for(unsigned int j = 0; j < sizeof(array)/sizeof(unsigned long); ++j) + array[j] = gen(); + unsigned long * start = array; + seed(start, array + sizeof(array)/sizeof(unsigned long)); + } + + template + void seed(It& first, It last) + { +#ifndef BOOST_NO_STDC_NAMESPACE + // allow for Koenig lookup + using std::fmod; + using std::pow; +#endif + unsigned long mask = ~((~0u) << (w%32)); // now lowest (w%32) bits set + RealType two32 = pow(RealType(2), 32); + unsigned int j; + for(j = 0; j < long_lag && first != last; ++j) { + x[j] = RealType(0); + for(int i = 0; i < w/32 && first != last; ++i, ++first) + x[j] += *first / pow(two32,i+1); + if(first != last && mask != 0) { + x[j] += fmod((*first & mask) / _modulus, RealType(1)); + ++first; + } + } + if(first == last && j < long_lag) + throw std::invalid_argument("subtract_with_carry_01::seed"); + carry = (x[long_lag-1] ? 0 : 1 / _modulus); + k = 0; + } + + result_type min BOOST_PREVENT_MACRO_SUBSTITUTION () const { return result_type(0); } + result_type max BOOST_PREVENT_MACRO_SUBSTITUTION () const { return result_type(1); } + + result_type operator()() + { + int short_index = k - short_lag; + if(short_index < 0) + short_index += long_lag; + RealType delta = x[short_index] - x[k] - carry; + if(delta < 0) { + delta += RealType(1); + carry = RealType(1)/_modulus; + } else { + carry = 0; + } + x[k] = delta; + ++k; + if(k >= long_lag) + k = 0; + return delta; + } + + static bool validation(result_type x) + { return x == val/pow(RealType(2), word_size); } + +#ifndef BOOST_NO_OPERATORS_IN_NAMESPACE + +#ifndef BOOST_NO_MEMBER_TEMPLATE_FRIENDS + template + friend std::basic_ostream& + operator<<(std::basic_ostream& os, + const subtract_with_carry_01& f) + { +#ifndef BOOST_NO_STDC_NAMESPACE + // allow for Koenig lookup + using std::pow; +#endif + 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.compute(j) * f._modulus) << " "; + os << (f.carry * f._modulus); + os.flags(oldflags); + return os; + } + + template + friend std::basic_istream& + operator>>(std::basic_istream& is, subtract_with_carry_01& f) + { +# ifdef BOOST_RANDOM_EXTRACT_SWC_01 + detail::extract_subtract_with_carry_01(is, f, f.carry, f.x, f._modulus); +# else + // MSVC (up to 7.1) and Borland (up to 5.64) don't handle the template type + // parameter "RealType" available from the class template scope, so use + // the member typedef + typename subtract_with_carry_01::result_type value; + for(unsigned int j = 0; j < long_lag; ++j) { + is >> value >> std::ws; + f.x[j] = value / f._modulus; + } + is >> value >> std::ws; + f.carry = value / f._modulus; +# endif + f.k = 0; + return is; + } +#endif + + friend bool operator==(const subtract_with_carry_01& x, + const subtract_with_carry_01& y) + { + for(unsigned int j = 0; j < r; ++j) + if(x.compute(j) != y.compute(j)) + return false; + return true; + } + + friend bool operator!=(const subtract_with_carry_01& x, + const subtract_with_carry_01& y) + { return !(x == y); } +#else + // Use a member function; Streamable concept not supported. + bool operator==(const subtract_with_carry_01& rhs) const + { + for(unsigned int j = 0; j < r; ++j) + if(compute(j) != rhs.compute(j)) + return false; + return true; + } + + bool operator!=(const subtract_with_carry_01& rhs) const + { return !(*this == rhs); } +#endif + +private: + RealType compute(unsigned int index) const; + unsigned int k; + RealType carry; + RealType x[long_lag]; + RealType _modulus; +}; + +#ifndef BOOST_NO_INCLASS_MEMBER_INITIALIZATION +// A definition is required even for integral static constants +template +const bool subtract_with_carry_01::has_fixed_range; +template +const int subtract_with_carry_01::word_size; +template +const unsigned int subtract_with_carry_01::long_lag; +template +const unsigned int subtract_with_carry_01::short_lag; +#endif + +template +RealType subtract_with_carry_01::compute(unsigned int index) const +{ + return x[(k+index) % long_lag]; +} + + +} // namespace random +} // namespace boost + +#endif // BOOST_RANDOM_SUBTRACT_WITH_CARRY_HPP