X-Git-Url: https://git.donarmstrong.com/?p=rsem.git;a=blobdiff_plain;f=boost%2Frandom%2Finversive_congruential.hpp;fp=boost%2Frandom%2Finversive_congruential.hpp;h=616909d445414c1f0741b58a524fdb3ed377d481;hp=93604b324e58ee32b9de97462f2059bf6b512056;hb=2d71eb92104693ca9baa5a2e1c23eeca776d8fd3;hpb=da57529b92adbb7ae74a89861cb39fb35ac7c62d diff --git a/boost/random/inversive_congruential.hpp b/boost/random/inversive_congruential.hpp index 93604b3..616909d 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 60755 2010-03-22 00:45:06Z steven_watanabe $ + * $Id: inversive_congruential.hpp 71018 2011-04-05 21:27:52Z steven_watanabe $ * * Revision history * 2001-02-18 moved to individual header files @@ -16,20 +16,26 @@ #ifndef BOOST_RANDOM_INVERSIVE_CONGRUENTIAL_HPP #define BOOST_RANDOM_INVERSIVE_CONGRUENTIAL_HPP -#include -#include +#include #include +#include #include -#include +#include +#include #include #include +#include +#include +#include + +#include namespace boost { namespace random { // Eichenauer and Lehn 1986 /** - * Instantiations of class template @c inversive_congruential model a + * Instantiations of class template @c inversive_congruential_engine model a * \pseudo_random_number_generator. It uses the inversive congruential * algorithm (ICG) described in * @@ -57,103 +63,185 @@ namespace random { * not optimal for calculating the multiplicative inverse. * @endxmlnote */ -template -class inversive_congruential +template +class inversive_congruential_engine { public: - typedef IntType result_type; -#ifndef BOOST_NO_INCLASS_MEMBER_INITIALIZATION - static const bool has_fixed_range = true; - static const result_type min_value = (b == 0 ? 1 : 0); - static const result_type max_value = p-1; -#else - BOOST_STATIC_CONSTANT(bool, has_fixed_range = false); -#endif - BOOST_STATIC_CONSTANT(result_type, multiplier = a); - BOOST_STATIC_CONSTANT(result_type, increment = b); - BOOST_STATIC_CONSTANT(result_type, modulus = p); - - result_type min BOOST_PREVENT_MACRO_SUBSTITUTION () const { return b == 0 ? 1 : 0; } - result_type max BOOST_PREVENT_MACRO_SUBSTITUTION () const { return p-1; } - - /** - * Constructs an inversive_congruential generator with - * @c y0 as the initial state. - */ - explicit inversive_congruential(IntType y0 = 1) : value(y0) - { - BOOST_STATIC_ASSERT(b >= 0); - BOOST_STATIC_ASSERT(p > 1); - BOOST_STATIC_ASSERT(a >= 1); - if(b == 0) - assert(y0 > 0); - } - template inversive_congruential(It& first, It last) - { seed(first, last); } - - /** Changes the current state to y0. */ - void seed(IntType y0 = 1) { value = y0; if(b == 0) assert(y0 > 0); } - template void seed(It& first, It last) - { - if(first == last) - throw std::invalid_argument("inversive_congruential::seed"); - value = *first++; - } - IntType operator()() - { - typedef const_mod do_mod; - value = do_mod::mult_add(a, do_mod::invert(value), b); - return value; - } - - static bool validation(result_type x) { return val == x; } - -#ifndef BOOST_NO_OPERATORS_IN_NAMESPACE - -#ifndef BOOST_RANDOM_NO_STREAM_OPERATORS - template - friend std::basic_ostream& - operator<<(std::basic_ostream& os, inversive_congruential x) - { os << x.value; return os; } - - template - friend std::basic_istream& - operator>>(std::basic_istream& is, inversive_congruential& x) - { is >> x.value; return is; } -#endif + typedef IntType result_type; + BOOST_STATIC_CONSTANT(bool, has_fixed_range = false); + + BOOST_STATIC_CONSTANT(result_type, multiplier = a); + BOOST_STATIC_CONSTANT(result_type, increment = b); + BOOST_STATIC_CONSTANT(result_type, modulus = p); + BOOST_STATIC_CONSTANT(IntType, default_seed = 1); + + static result_type min BOOST_PREVENT_MACRO_SUBSTITUTION () { return b == 0 ? 1 : 0; } + static result_type max BOOST_PREVENT_MACRO_SUBSTITUTION () { return p-1; } + + /** + * Constructs an @c inversive_congruential_engine, seeding it with + * the default seed. + */ + inversive_congruential_engine() { seed(); } + + /** + * Constructs an @c inversive_congruential_engine, seeding it with @c x0. + */ + BOOST_RANDOM_DETAIL_ARITHMETIC_CONSTRUCTOR(inversive_congruential_engine, + IntType, x0) + { seed(x0); } + + /** + * Constructs an @c inversive_congruential_engine, seeding it with values + * produced by a call to @c seq.generate(). + */ + BOOST_RANDOM_DETAIL_SEED_SEQ_CONSTRUCTOR(inversive_congruential_engine, + SeedSeq, seq) + { seed(seq); } + + /** + * Constructs an @c inversive_congruential_engine, seeds it + * with values taken from the itrator range [first, last), + * and adjusts first to point to the element after the last one + * used. If there are not enough elements, throws @c std::invalid_argument. + * + * first and last must be input iterators. + */ + template inversive_congruential_engine(It& first, It last) + { seed(first, last); } + + /** + * Calls seed(default_seed) + */ + void seed() { seed(default_seed); } + + /** + * If c mod m is zero and x0 mod m is zero, changes the current value of + * the generator to 1. Otherwise, changes it to x0 mod m. If c is zero, + * distinct seeds in the range [1,m) will leave the generator in distinct + * states. If c is not zero, the range is [0,m). + */ + BOOST_RANDOM_DETAIL_ARITHMETIC_SEED(inversive_congruential_engine, IntType, x0) + { + // wrap _x if it doesn't fit in the destination + if(modulus == 0) { + _value = x0; + } else { + _value = x0 % modulus; + } + // handle negative seeds + if(_value <= 0 && _value != 0) { + _value += modulus; + } + // adjust to the correct range + if(increment == 0 && _value == 0) { + _value = 1; + } + BOOST_ASSERT(_value >= (min)()); + BOOST_ASSERT(_value <= (max)()); + } + + /** + * Seeds an @c inversive_congruential_engine using values from a SeedSeq. + */ + BOOST_RANDOM_DETAIL_SEED_SEQ_SEED(inversive_congruential_engine, SeedSeq, seq) + { seed(detail::seed_one_int(seq)); } + + /** + * seeds an @c inversive_congruential_engine with values taken + * from the itrator range [first, last) and adjusts @c first to + * point to the element after the last one used. If there are + * not enough elements, throws @c std::invalid_argument. + * + * @c first and @c last must be input iterators. + */ + template void seed(It& first, It last) + { seed(detail::get_one_int(first, last)); } + + /** Returns the next output of the generator. */ + IntType operator()() + { + typedef const_mod do_mod; + _value = do_mod::mult_add(a, do_mod::invert(_value), b); + return _value; + } + + /** Fills a range with random values */ + template + void generate(Iter first, Iter last) + { detail::generate_from_int(*this, first, last); } + + /** 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, inversive_congruential_engine, x) + { + os << x._value; + return os; + } + + /** + * Reads the textual representation of the generator from a @c std::istream. + */ + BOOST_RANDOM_DETAIL_ISTREAM_OPERATOR(is, inversive_congruential_engine, x) + { + is >> x._value; + return is; + } + + /** + * Returns true if the two generators will produce identical + * sequences of outputs. + */ + BOOST_RANDOM_DETAIL_EQUALITY_OPERATOR(inversive_congruential_engine, x, y) + { return x._value == y._value; } + + /** + * Returns true if the two generators will produce different + * sequences of outputs. + */ + BOOST_RANDOM_DETAIL_INEQUALITY_OPERATOR(inversive_congruential_engine) - friend bool operator==(inversive_congruential x, inversive_congruential y) - { return x.value == y.value; } - friend bool operator!=(inversive_congruential x, inversive_congruential y) - { return !(x == y); } -#else - // Use a member function; Streamable concept not supported. - bool operator==(inversive_congruential rhs) const - { return value == rhs.value; } - bool operator!=(inversive_congruential rhs) const - { return !(*this == rhs); } -#endif private: - IntType value; + IntType _value; }; #ifndef BOOST_NO_INCLASS_MEMBER_INITIALIZATION // A definition is required even for integral static constants -template -const bool inversive_congruential::has_fixed_range; -template -const typename inversive_congruential::result_type inversive_congruential::min_value; -template -const typename inversive_congruential::result_type inversive_congruential::max_value; -template -const typename inversive_congruential::result_type inversive_congruential::multiplier; -template -const typename inversive_congruential::result_type inversive_congruential::increment; -template -const typename inversive_congruential::result_type inversive_congruential::modulus; +template +const bool inversive_congruential_engine::has_fixed_range; +template +const typename inversive_congruential_engine::result_type inversive_congruential_engine::multiplier; +template +const typename inversive_congruential_engine::result_type inversive_congruential_engine::increment; +template +const typename inversive_congruential_engine::result_type inversive_congruential_engine::modulus; +template +const typename inversive_congruential_engine::result_type inversive_congruential_engine::default_seed; #endif -} // namespace random +/// \cond show_deprecated + +// provided for backwards compatibility +template +class inversive_congruential : public inversive_congruential_engine +{ + typedef inversive_congruential_engine base_type; +public: + inversive_congruential(IntType x0 = 1) : base_type(x0) {} + template + inversive_congruential(It& first, It last) : base_type(first, last) {} +}; + +/// \endcond /** * The specialization hellekalek1995 was suggested in @@ -165,9 +253,15 @@ const typename inversive_congruential::result_type invers * (editors), 1995, pp. 255-262. ftp://random.mat.sbg.ac.at/pub/data/wsc95.ps * @endblockquote */ -typedef random::inversive_congruential hellekalek1995; +typedef inversive_congruential_engine hellekalek1995; + +} // namespace random + +using random::hellekalek1995; } // namespace boost +#include + #endif // BOOST_RANDOM_INVERSIVE_CONGRUENTIAL_HPP