X-Git-Url: https://git.donarmstrong.com/?p=rsem.git;a=blobdiff_plain;f=boost%2Frandom%2Flagged_fibonacci.hpp;h=eb4e405c50c6106c42b4443ba0bbaeb312049eb8;hp=20860dae69156067a6292d173ff5591a51a7e4ae;hb=2d71eb92104693ca9baa5a2e1c23eeca776d8fd3;hpb=da57529b92adbb7ae74a89861cb39fb35ac7c62d diff --git a/boost/random/lagged_fibonacci.hpp b/boost/random/lagged_fibonacci.hpp index 20860da..eb4e405 100644 --- a/boost/random/lagged_fibonacci.hpp +++ b/boost/random/lagged_fibonacci.hpp @@ -7,7 +7,7 @@ * * See http://www.boost.org for most recent version including documentation. * - * $Id: lagged_fibonacci.hpp 60755 2010-03-22 00:45:06Z steven_watanabe $ + * $Id: lagged_fibonacci.hpp 72951 2011-07-07 04:57:37Z steven_watanabe $ * * Revision history * 2001-02-18 moved to individual header files @@ -16,289 +16,223 @@ #ifndef BOOST_RANDOM_LAGGED_FIBONACCI_HPP #define BOOST_RANDOM_LAGGED_FIBONACCI_HPP -#include -#include +#include +#include #include // std::max #include #include // std::pow #include #include #include -#include +#include #include #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_LF -#endif - -#if defined(__APPLE_CC__) && defined(__GNUC__) && (__GNUC__ == 3) && (__GNUC_MINOR__ <= 3) -# define BOOST_RANDOM_EXTRACT_LF -#endif - -# ifdef BOOST_RANDOM_EXTRACT_LF -namespace detail -{ - template - IStream& - extract_lagged_fibonacci_01( - IStream& is - , F const& f - , unsigned int& i - , RealType* x - , RealType modulus) - { - is >> i >> std::ws; - for(unsigned int i = 0; i < f.long_lag; ++i) - { - RealType value; - is >> value >> std::ws; - x[i] = value / modulus; - } - return is; - } - - template - IStream& - extract_lagged_fibonacci( - IStream& is - , F const& f - , unsigned int& i - , UIntType* x) - { - is >> i >> std::ws; - for(unsigned int i = 0; i < f.long_lag; ++i) - is >> x[i] >> std::ws; - return is; - } -} -# endif - /** - * Instantiations of class template \lagged_fibonacci model a + * 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: * x(i) = x(i-p) + x(i-q) (mod 2w) with p > q. */ -template -class lagged_fibonacci +template +class lagged_fibonacci_engine { public: - typedef UIntType result_type; - BOOST_STATIC_CONSTANT(bool, has_fixed_range = false); - BOOST_STATIC_CONSTANT(int, word_size = w); - BOOST_STATIC_CONSTANT(unsigned int, long_lag = p); - BOOST_STATIC_CONSTANT(unsigned int, short_lag = q); - - /** - * Returns: the smallest value that the generator can produce - */ - result_type min BOOST_PREVENT_MACRO_SUBSTITUTION () const { return 0; } - /** - * Returns: the largest value that the generator can produce - */ - result_type max BOOST_PREVENT_MACRO_SUBSTITUTION () const { return wordmask; } - - /** - * Creates a new @c lagged_fibonacci generator and calls @c seed() - */ - lagged_fibonacci() { init_wordmask(); seed(); } - /** - * Creates a new @c lagged_fibonacci generator and calls @c seed(value) - */ - explicit lagged_fibonacci(uint32_t value) { init_wordmask(); seed(value); } - /** - * Creates a new @c lagged_fibonacci generator and calls @c seed(first, last) - */ - template lagged_fibonacci(It& first, It last) - { init_wordmask(); seed(first, last); } - // compiler-generated copy ctor and assignment operator are fine + typedef UIntType result_type; + BOOST_STATIC_CONSTANT(bool, has_fixed_range = false); + BOOST_STATIC_CONSTANT(int, word_size = w); + BOOST_STATIC_CONSTANT(unsigned int, long_lag = p); + BOOST_STATIC_CONSTANT(unsigned int, short_lag = q); + + BOOST_STATIC_CONSTANT(UIntType, default_seed = 331u); + + /** 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 low_bits_mask_t::sig_bits; } + + /** Creates a new @c lagged_fibonacci_engine and calls @c seed(). */ + lagged_fibonacci_engine() { seed(); } + + /** Creates a new @c lagged_fibonacci_engine and calls @c seed(value). */ + BOOST_RANDOM_DETAIL_ARITHMETIC_CONSTRUCTOR(lagged_fibonacci_engine, + UIntType, value) + { seed(value); } + + /** Creates a new @c lagged_fibonacci_engine and calls @c seed(seq). */ + BOOST_RANDOM_DETAIL_SEED_SEQ_CONSTRUCTOR(lagged_fibonacci_engine, + SeedSeq, seq) + { seed(seq); } + + /** + * Creates a new @c lagged_fibonacci_engine and calls @c seed(first, last). + */ + template lagged_fibonacci_engine(It& first, It last) + { seed(first, last); } + + // compiler-generated copy ctor and assignment operator are fine + + /** Calls @c seed(default_seed). */ + void seed() { seed(default_seed); } + + /** + * Sets the state of the generator to values produced by + * a \minstd_rand0 generator. + */ + BOOST_RANDOM_DETAIL_ARITHMETIC_SEED(lagged_fibonacci_engine, + UIntType, value) + { + minstd_rand0 intgen(static_cast(value)); + detail::generator_seed_seq gen(intgen); + seed(gen); + } -private: - /// \cond hide_private_members - void init_wordmask() - { - wordmask = 0; - for(int j = 0; j < w; ++j) - wordmask |= (1u << j); - } - /// \endcond + /** + * Sets the state of the generator using values produced by seq. + */ + BOOST_RANDOM_DETAIL_SEED_SEQ_SEED(lagged_fibonacci_engine, SeedSeq, seq) + { + detail::seed_array_int(seq, x); + i = long_lag; + } -public: - /** - * Sets the state of the generator to values produced by - * a \minstd_rand generator. - */ - void seed(uint32_t value = 331u) - { - minstd_rand0 gen(value); - for(unsigned int j = 0; j < long_lag; ++j) - x[j] = gen() & wordmask; - i = long_lag; - } - - /** - * Sets the state of the generator to values from the iterator - * range [first, last). If there are not enough elements in the - * range [first, last) throws @c std::invalid_argument. - */ - template - void seed(It& first, It last) - { - // word size could be smaller than the seed values - unsigned int j; - for(j = 0; j < long_lag && first != last; ++j, ++first) - x[j] = *first & wordmask; - i = long_lag; - if(first == last && j < long_lag) - throw std::invalid_argument("lagged_fibonacci::seed"); - } - - /** - * Returns: the next value of the generator - */ - result_type operator()() - { - if(i >= long_lag) - fill(); - return x[i++]; - } - - static bool validation(result_type x) - { - return x == val; - } + /** + * Sets the state of the generator to values from the iterator + * range [first, last). If there are not enough elements in the + * range [first, last) throws @c std::invalid_argument. + */ + template + void seed(It& first, It last) + { + detail::fill_array_int(first, last, x); + i = long_lag; + } + + /** Returns the next value of the generator. */ + result_type operator()() + { + if(i >= long_lag) + fill(); + return x[i++]; + } -#ifndef BOOST_NO_OPERATORS_IN_NAMESPACE - -#ifndef BOOST_RANDOM_NO_STREAM_OPERATORS - template - friend std::basic_ostream& - operator<<(std::basic_ostream& os, const lagged_fibonacci& f) - { - os << f.i << " "; - for(unsigned int i = 0; i < f.long_lag; ++i) - os << f.x[i] << " "; - return os; - } - - template - friend std::basic_istream& - operator>>(std::basic_istream& is, lagged_fibonacci& f) - { -# ifdef BOOST_RANDOM_EXTRACT_LF - return detail::extract_lagged_fibonacci(is, f, f.i, f.x); -# else - is >> f.i >> std::ws; - for(unsigned int i = 0; i < f.long_lag; ++i) - is >> f.x[i] >> std::ws; - return is; -# endif - } -#endif + /** Fills a range with random values */ + template + void generate(Iter first, Iter last) + { detail::generate_from_int(*this, first, last); } - friend bool operator==(const lagged_fibonacci& x, const lagged_fibonacci& y) - { return x.i == y.i && std::equal(x.x, x.x+long_lag, y.x); } - friend bool operator!=(const lagged_fibonacci& x, - const lagged_fibonacci& y) - { return !(x == y); } -#else - // Use a member function; Streamable concept not supported. - bool operator==(const lagged_fibonacci& rhs) const - { return i == rhs.i && std::equal(x, x+long_lag, rhs.x); } - bool operator!=(const lagged_fibonacci& rhs) const - { return !(*this == rhs); } -#endif + /** Advances the state of the generator by @c z. */ + void discard(boost::uintmax_t z) + { + for(boost::uintmax_t j = 0; j < z; ++j) { + (*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]; + 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; + 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); } + + /** + * Returns true if the two generators will produce different + * sequences of outputs. + */ + BOOST_RANDOM_DETAIL_INEQUALITY_OPERATOR(lagged_fibonacci_engine) private: - /// \cond hide_private_members - void fill(); - /// \endcond + /// \cond show_private + void fill(); + /// \endcond - UIntType wordmask; - unsigned int i; - UIntType x[long_lag]; + unsigned int i; + UIntType x[long_lag]; }; #ifndef BOOST_NO_INCLASS_MEMBER_INITIALIZATION // A definition is required even for integral static constants -template -const bool lagged_fibonacci::has_fixed_range; -template -const unsigned int lagged_fibonacci::long_lag; -template -const unsigned int lagged_fibonacci::short_lag; +template +const bool lagged_fibonacci_engine::has_fixed_range; +template +const unsigned int lagged_fibonacci_engine::long_lag; +template +const unsigned int lagged_fibonacci_engine::short_lag; +template +const UIntType lagged_fibonacci_engine::default_seed; #endif -/// \cond hide_private_members +/// \cond show_private -template -void lagged_fibonacci::fill() +template +void lagged_fibonacci_engine::fill() { - // two loops to avoid costly modulo operations - { // extra scope for MSVC brokenness w.r.t. for scope - for(unsigned int j = 0; j < short_lag; ++j) - x[j] = (x[j] + x[j+(long_lag-short_lag)]) & wordmask; - } - for(unsigned int j = short_lag; j < long_lag; ++j) - x[j] = (x[j] + x[j-short_lag]) & wordmask; - i = 0; + // two loops to avoid costly modulo operations + { // extra scope for MSVC brokenness w.r.t. for scope + for(unsigned int j = 0; j < short_lag; ++j) + x[j] = (x[j] + x[j+(long_lag-short_lag)]) & low_bits_mask_t::sig_bits; + } + for(unsigned int j = short_lag; j < long_lag; ++j) + x[j] = (x[j] + x[j-short_lag]) & low_bits_mask_t::sig_bits; + i = 0; } +/// \endcond +/// \cond show_deprecated -// lagged Fibonacci generator for the range [0..1) -// contributed by Matthias Troyer -// for p=55, q=24 originally by G. J. Mitchell and D. P. Moore 1958 - -template -struct fibonacci_validation +// provided for backwards compatibility +template +class lagged_fibonacci : public lagged_fibonacci_engine { - BOOST_STATIC_CONSTANT(bool, is_specialized = false); - static T value() { return 0; } - static T tolerance() { return 0; } -}; - -#ifndef BOOST_NO_INCLASS_MEMBER_INITIALIZATION -// A definition is required even for integral static constants -template -const bool fibonacci_validation::is_specialized; -#endif - -#define BOOST_RANDOM_FIBONACCI_VAL(T,P,Q,V,E) \ -template<> \ -struct fibonacci_validation \ -{ \ - BOOST_STATIC_CONSTANT(bool, is_specialized = true); \ - static T value() { return V; } \ - static T tolerance() \ -{ return (std::max)(E, static_cast(5*std::numeric_limits::epsilon())); } \ + typedef lagged_fibonacci_engine base_type; +public: + lagged_fibonacci() {} + BOOST_RANDOM_DETAIL_ARITHMETIC_CONSTRUCTOR(lagged_fibonacci, UIntType, val) + { this->seed(val); } + BOOST_RANDOM_DETAIL_SEED_SEQ_CONSTRUCTOR(lagged_fibonacci, SeedSeq, seq) + { this->seed(seq); } + template + lagged_fibonacci(It& first, It last) : base_type(first, last) {} }; -// (The extra static_cast in the std::max call above is actually -// unnecessary except for HP aCC 1.30, which claims that -// numeric_limits::epsilon() doesn't actually return a double.) - -BOOST_RANDOM_FIBONACCI_VAL(double, 607, 273, 0.4293817707235914, 1e-14) -BOOST_RANDOM_FIBONACCI_VAL(double, 1279, 418, 0.9421630240437659, 1e-14) -BOOST_RANDOM_FIBONACCI_VAL(double, 2281, 1252, 0.1768114046909004, 1e-14) -BOOST_RANDOM_FIBONACCI_VAL(double, 3217, 576, 0.1956232694868209, 1e-14) -BOOST_RANDOM_FIBONACCI_VAL(double, 4423, 2098, 0.9499762202147172, 1e-14) -BOOST_RANDOM_FIBONACCI_VAL(double, 9689, 5502, 0.05737836943695162, 1e-14) -BOOST_RANDOM_FIBONACCI_VAL(double, 19937, 9842, 0.5076528587449834, 1e-14) -BOOST_RANDOM_FIBONACCI_VAL(double, 23209, 13470, 0.5414473810619185, 1e-14) -BOOST_RANDOM_FIBONACCI_VAL(double, 44497,21034, 0.254135073399297, 1e-14) - -#undef BOOST_RANDOM_FIBONACCI_VAL /// \endcond +// lagged Fibonacci generator for the range [0..1) +// contributed by Matthias Troyer +// for p=55, q=24 originally by G. J. Mitchell and D. P. Moore 1958 + /** * Instantiations of class template @c lagged_fibonacci_01 model a * \pseudo_random_number_generator. It uses a lagged Fibonacci @@ -322,216 +256,224 @@ BOOST_RANDOM_FIBONACCI_VAL(double, 44497,21034, 0.254135073399297, 1e-14) * 4856 bytes and \lagged_fibonacci44497 requires about 350 KBytes. */ template -class lagged_fibonacci_01 +class lagged_fibonacci_01_engine { 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 = p); - BOOST_STATIC_CONSTANT(unsigned int, short_lag = q); - - /** Constructs a @c lagged_fibonacci_01 generator and calls @c seed(). */ - lagged_fibonacci_01() { init_modulus(); seed(); } - /** Constructs a @c lagged_fibonacci_01 generator and calls @c seed(value). */ - BOOST_RANDOM_DETAIL_ARITHMETIC_CONSTRUCTOR(lagged_fibonacci_01, uint32_t, value) - { init_modulus(); seed(value); } - /** Constructs a @c lagged_fibonacci_01 generator and calls @c seed(gen). */ - BOOST_RANDOM_DETAIL_GENERATOR_CONSTRUCTOR(lagged_fibonacci_01, Generator, gen) - { init_modulus(); seed(gen); } - template lagged_fibonacci_01(It& first, It last) - { init_modulus(); seed(first, last); } - // compiler-generated copy ctor and assignment operator are fine - -private: - /// \cond hide_private_members - void init_modulus() - { -#ifndef BOOST_NO_STDC_NAMESPACE - // allow for Koenig lookup - using std::pow; -#endif - _modulus = pow(RealType(2), word_size); - } - /// \endcond + 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 = p); + BOOST_STATIC_CONSTANT(unsigned int, short_lag = q); + + BOOST_STATIC_CONSTANT(boost::uint32_t, default_seed = 331u); + + /** Constructs a @c lagged_fibonacci_01 generator and calls @c seed(). */ + lagged_fibonacci_01_engine() { seed(); } + /** Constructs a @c lagged_fibonacci_01 generator and calls @c seed(value). */ + BOOST_RANDOM_DETAIL_ARITHMETIC_CONSTRUCTOR(lagged_fibonacci_01_engine, uint32_t, value) + { seed(value); } + /** Constructs a @c lagged_fibonacci_01 generator and calls @c seed(gen). */ + BOOST_RANDOM_DETAIL_SEED_SEQ_CONSTRUCTOR(lagged_fibonacci_01_engine, SeedSeq, seq) + { seed(seq); } + template lagged_fibonacci_01_engine(It& first, It last) + { seed(first, last); } + + // compiler-generated copy ctor and assignment operator are fine + + /** Calls seed(default_seed). */ + void seed() { seed(default_seed); } + + /** + * Constructs a \minstd_rand0 generator with the constructor parameter + * value and calls seed with it. Distinct seeds in the range + * [1, 2147483647) will produce generators with different states. Other + * seeds will be equivalent to some seed within this range. See + * \linear_congruential_engine for details. + */ + BOOST_RANDOM_DETAIL_ARITHMETIC_SEED(lagged_fibonacci_01_engine, boost::uint32_t, value) + { + minstd_rand0 intgen(value); + detail::generator_seed_seq gen(intgen); + seed(gen); + } -public: - /** Calls seed(331u). */ - void seed() { seed(331u); } - /** - * Constructs a \minstd_rand0 generator with the constructor parameter - * value and calls seed with it. Distinct seeds in the range - * [1, 2147483647) will produce generators with different states. Other - * seeds will be equivalent to some seed within this range. See - * \linear_congruential for details. - */ - BOOST_RANDOM_DETAIL_ARITHMETIC_SEED(lagged_fibonacci_01, uint32_t, value) - { - minstd_rand0 intgen(value); - seed(intgen); - } - - /** - * Sets the state of this @c lagged_fibonacci_01 to the values returned - * by p invocations of \uniform_01\()(gen). - * - * Complexity: Exactly p invocations of gen. - */ - BOOST_RANDOM_DETAIL_GENERATOR_SEED(lagged_fibonacci, Generator, gen) - { - // use pass-by-reference, but wrap argument in pass_through_engine - typedef detail::pass_through_engine ref_gen; - uniform_01 gen01 = - uniform_01(ref_gen(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] = gen01(); - i = long_lag; - } - - 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 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 k = 0; k < w/32 && first != last; ++k, ++first) - x[j] += *first / pow(two32,k+1); - if(first != last && mask != 0) { - x[j] += fmod((*first & mask) / _modulus, RealType(1)); - ++first; - } + /** + * Seeds this @c lagged_fibonacci_01_engine using values produced by + * @c seq.generate. + */ + BOOST_RANDOM_DETAIL_SEED_SEQ_SEED(lagged_fibonacci_01_engine, SeedSeq, seq) + { + detail::seed_array_real(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 + * in the range, throws @c std::invalid_argument. + */ + template + void seed(It& first, It last) + { + detail::fill_array_real(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. */ + static result_type max BOOST_PREVENT_MACRO_SUBSTITUTION () { return result_type(1); } + + /** Returns the next value of the generator. */ + result_type operator()() + { + if(i >= long_lag) + fill(); + return x[i++]; } - i = long_lag; - if(first == last && j < long_lag) - throw std::invalid_argument("lagged_fibonacci_01::seed"); - } - - 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()() - { - if(i >= long_lag) - fill(); - return x[i++]; - } - - static bool validation(result_type x) - { - result_type v = fibonacci_validation::value(); - result_type epsilon = fibonacci_validation::tolerance(); - // std::abs is a source of trouble: sometimes, it's not overloaded - // for double, plus the usual namespace std noncompliance -> avoid it - // using std::abs; - // return abs(x - v) < 5 * epsilon - return x > v - epsilon && x < v + epsilon; - } -#ifndef BOOST_NO_OPERATORS_IN_NAMESPACE - -#ifndef BOOST_RANDOM_NO_STREAM_OPERATORS - template - friend std::basic_ostream& - operator<<(std::basic_ostream& os, const lagged_fibonacci_01&f) - { -#ifndef BOOST_NO_STDC_NAMESPACE - // allow for Koenig lookup - using std::pow; -#endif - 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 << " "; - os.flags(oldflags); - return os; - } - - template - friend std::basic_istream& - operator>>(std::basic_istream& is, lagged_fibonacci_01& f) + /** Fills a range with random values */ + template + void generate(Iter first, Iter last) + { return detail::generate_from_real(*this, first, last); } + + /** Advances the state of the generator by @c z. */ + void discard(boost::uintmax_t z) { -# ifdef BOOST_RANDOM_EXTRACT_LF - return detail::extract_lagged_fibonacci_01(is, f, f.i, f.x, f._modulus); -# else - is >> f.i >> std::ws; + for(boost::uintmax_t j = 0; j < z; ++j) { + (*this)(); + } + } + + /** + * Writes the textual representation of the generator to a @c std::ostream. + */ + BOOST_RANDOM_DETAIL_OSTREAM_OPERATOR(os, lagged_fibonacci_01_engine, f) + { + // 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(); + 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) { - typename lagged_fibonacci_01::result_type value; - is >> value >> std::ws; - f.x[i] = value / f._modulus; + typename lagged_fibonacci_01_engine::result_type value; + is >> std::ws >> value; + f.x[i] = value / f.modulus(); } return is; -# endif } -#endif - - friend bool operator==(const lagged_fibonacci_01& x, - const lagged_fibonacci_01& y) - { return x.i == y.i && std::equal(x.x, x.x+long_lag, y.x); } - friend bool operator!=(const lagged_fibonacci_01& x, - const lagged_fibonacci_01& y) - { return !(x == y); } -#else - // Use a member function; Streamable concept not supported. - bool operator==(const lagged_fibonacci_01& rhs) const - { return i == rhs.i && std::equal(x, x+long_lag, rhs.x); } - bool operator!=(const lagged_fibonacci_01& rhs) const - { return !(*this == rhs); } -#endif + + /** + * 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); } + + /** + * Returns true if the two generators will produce different + * sequences of outputs. + */ + BOOST_RANDOM_DETAIL_INEQUALITY_OPERATOR(lagged_fibonacci_01_engine) private: - /// \cond hide_private_members - void fill(); - /// \endcond - unsigned int i; - RealType x[long_lag]; - RealType _modulus; + /// \cond show_private + void fill(); + static RealType modulus() + { + using std::pow; + return pow(RealType(2), word_size); + } + /// \endcond + unsigned int i; + RealType x[long_lag]; }; #ifndef BOOST_NO_INCLASS_MEMBER_INITIALIZATION // A definition is required even for integral static constants template -const bool lagged_fibonacci_01::has_fixed_range; +const bool lagged_fibonacci_01_engine::has_fixed_range; template -const unsigned int lagged_fibonacci_01::long_lag; +const unsigned int lagged_fibonacci_01_engine::long_lag; template -const unsigned int lagged_fibonacci_01::short_lag; +const unsigned int lagged_fibonacci_01_engine::short_lag; template -const int lagged_fibonacci_01::word_size; - +const int lagged_fibonacci_01_engine::word_size; +template +const boost::uint32_t lagged_fibonacci_01_engine::default_seed; #endif -/// \cond hide_private_members +/// \cond show_private template -void lagged_fibonacci_01::fill() +void lagged_fibonacci_01_engine::fill() { - // two loops to avoid costly modulo operations - { // extra scope for MSVC brokenness w.r.t. for scope - for(unsigned int j = 0; j < short_lag; ++j) { - RealType t = x[j] + x[j+(long_lag-short_lag)]; - if(t >= RealType(1)) - t -= RealType(1); - x[j] = t; - } - } - for(unsigned int j = short_lag; j < long_lag; ++j) { - RealType t = x[j] + x[j-short_lag]; - if(t >= RealType(1)) - t -= RealType(1); - x[j] = t; - } - i = 0; + // two loops to avoid costly modulo operations + { // extra scope for MSVC brokenness w.r.t. for scope + for(unsigned int j = 0; j < short_lag; ++j) { + RealType t = x[j] + x[j+(long_lag-short_lag)]; + if(t >= RealType(1)) + t -= RealType(1); + x[j] = t; + } + } + for(unsigned int j = short_lag; j < long_lag; ++j) { + RealType t = x[j] + x[j-short_lag]; + if(t >= RealType(1)) + t -= RealType(1); + x[j] = t; + } + i = 0; } /// \endcond -} // namespace random +/// \cond show_deprecated + +// provided for backwards compatibility +template +class lagged_fibonacci_01 : public lagged_fibonacci_01_engine +{ + typedef lagged_fibonacci_01_engine base_type; +public: + lagged_fibonacci_01() {} + BOOST_RANDOM_DETAIL_ARITHMETIC_CONSTRUCTOR(lagged_fibonacci_01, boost::uint32_t, val) + { this->seed(val); } + BOOST_RANDOM_DETAIL_SEED_SEQ_CONSTRUCTOR(lagged_fibonacci_01, SeedSeq, seq) + { this->seed(seq); } + template + lagged_fibonacci_01(It& first, It last) : base_type(first, last) {} +}; + +/// \endcond + +namespace detail { + +template +struct generator_bits; + +template +struct generator_bits > +{ + static std::size_t value() { return w; } +}; + +template +struct generator_bits > +{ + static std::size_t value() { return w; } +}; + +} #ifdef BOOST_RANDOM_DOXYGEN namespace detail { @@ -558,47 +500,36 @@ struct lagged_fibonacci_doc {}; } #endif -/** - * @copydoc boost::detail::lagged_fibonacci_doc - */ -typedef random::lagged_fibonacci_01 lagged_fibonacci607; -/** - * @copydoc boost::detail::lagged_fibonacci_doc - */ -typedef random::lagged_fibonacci_01 lagged_fibonacci1279; -/** - * @copydoc boost::detail::lagged_fibonacci_doc - */ -typedef random::lagged_fibonacci_01 lagged_fibonacci2281; -/** - * @copydoc boost::detail::lagged_fibonacci_doc - */ -typedef random::lagged_fibonacci_01 lagged_fibonacci3217; -/** - * @copydoc boost::detail::lagged_fibonacci_doc - */ -typedef random::lagged_fibonacci_01 lagged_fibonacci4423; -/** - * @copydoc boost::detail::lagged_fibonacci_doc - */ -typedef random::lagged_fibonacci_01 lagged_fibonacci9689; -/** - * @copydoc boost::detail::lagged_fibonacci_doc - */ -typedef random::lagged_fibonacci_01 lagged_fibonacci19937; -/** - * @copydoc boost::detail::lagged_fibonacci_doc - */ -typedef random::lagged_fibonacci_01 lagged_fibonacci23209; -/** - * @copydoc boost::detail::lagged_fibonacci_doc - */ -typedef random::lagged_fibonacci_01 lagged_fibonacci44497; +/** @copydoc boost::random::detail::lagged_fibonacci_doc */ +typedef lagged_fibonacci_01_engine lagged_fibonacci607; +/** @copydoc boost::random::detail::lagged_fibonacci_doc */ +typedef lagged_fibonacci_01_engine lagged_fibonacci1279; +/** @copydoc boost::random::detail::lagged_fibonacci_doc */ +typedef lagged_fibonacci_01_engine lagged_fibonacci2281; +/** @copydoc boost::random::detail::lagged_fibonacci_doc */ +typedef lagged_fibonacci_01_engine lagged_fibonacci3217; +/** @copydoc boost::random::detail::lagged_fibonacci_doc */ +typedef lagged_fibonacci_01_engine lagged_fibonacci4423; +/** @copydoc boost::random::detail::lagged_fibonacci_doc */ +typedef lagged_fibonacci_01_engine lagged_fibonacci9689; +/** @copydoc boost::random::detail::lagged_fibonacci_doc */ +typedef lagged_fibonacci_01_engine lagged_fibonacci19937; +/** @copydoc boost::random::detail::lagged_fibonacci_doc */ +typedef lagged_fibonacci_01_engine lagged_fibonacci23209; +/** @copydoc boost::random::detail::lagged_fibonacci_doc */ +typedef lagged_fibonacci_01_engine lagged_fibonacci44497; +} // namespace random -// It is possible to partially specialize uniform_01<> on lagged_fibonacci_01<> -// to help the compiler generate efficient code. For GCC, this seems useless, -// because GCC optimizes (x-0)/(1-0) to (x-0). This is good enough for now. +using random::lagged_fibonacci607; +using random::lagged_fibonacci1279; +using random::lagged_fibonacci2281; +using random::lagged_fibonacci3217; +using random::lagged_fibonacci4423; +using random::lagged_fibonacci9689; +using random::lagged_fibonacci19937; +using random::lagged_fibonacci23209; +using random::lagged_fibonacci44497; } // namespace boost