Chris@16: /* boost random/linear_feedback_shift.hpp header file Chris@16: * Chris@16: * Copyright Jens Maurer 2002 Chris@16: * Copyright Steven Watanabe 2011 Chris@16: * Distributed under the Boost Software License, Version 1.0. (See Chris@16: * accompanying file LICENSE_1_0.txt or copy at Chris@16: * http://www.boost.org/LICENSE_1_0.txt) Chris@16: * Chris@16: * See http://www.boost.org for most recent version including documentation. Chris@16: * Chris@101: * $Id$ Chris@16: * Chris@16: */ Chris@16: Chris@16: #ifndef BOOST_RANDOM_LINEAR_FEEDBACK_SHIFT_HPP Chris@16: #define BOOST_RANDOM_LINEAR_FEEDBACK_SHIFT_HPP Chris@16: Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: #include Chris@16: Chris@16: namespace boost { Chris@16: namespace random { Chris@16: Chris@16: /** Chris@16: * Instatiations of @c linear_feedback_shift model a Chris@16: * \pseudo_random_number_generator. It was originally Chris@16: * proposed in Chris@16: * Chris@16: * @blockquote Chris@16: * "Random numbers generated by linear recurrence modulo two.", Chris@16: * Tausworthe, R. C.(1965), Mathematics of Computation 19, 201-209. Chris@16: * @endblockquote Chris@16: */ Chris@16: template Chris@16: class linear_feedback_shift_engine Chris@16: { Chris@16: public: Chris@16: typedef UIntType result_type; Chris@16: BOOST_STATIC_CONSTANT(bool, has_fixed_range = false); Chris@16: BOOST_STATIC_CONSTANT(int, word_size = w); Chris@16: BOOST_STATIC_CONSTANT(int, exponent1 = k); Chris@16: BOOST_STATIC_CONSTANT(int, exponent2 = q); Chris@16: BOOST_STATIC_CONSTANT(int, step_size = s); Chris@16: BOOST_STATIC_CONSTANT(UIntType, default_seed = 341); Chris@16: Chris@16: /** Returns the smallest value that the generator can produce. */ Chris@16: static result_type min BOOST_PREVENT_MACRO_SUBSTITUTION () { return 0; } Chris@16: /** Returns the largest value that the generator can produce. */ Chris@16: static result_type max BOOST_PREVENT_MACRO_SUBSTITUTION () Chris@16: { return wordmask(); } Chris@16: Chris@16: BOOST_STATIC_ASSERT(w > 0); Chris@16: BOOST_STATIC_ASSERT(q > 0); Chris@16: BOOST_STATIC_ASSERT(k < w); Chris@16: BOOST_STATIC_ASSERT(0 < 2*q && 2*q < k); Chris@16: BOOST_STATIC_ASSERT(0 < s && s <= k-q); Chris@16: Chris@16: /** Constructs a @c linear_feedback_shift_engine, using the default seed. */ Chris@16: linear_feedback_shift_engine() { seed(); } Chris@16: Chris@16: /** Constructs a @c linear_feedback_shift_engine, seeding it with s0. */ Chris@16: BOOST_RANDOM_DETAIL_ARITHMETIC_CONSTRUCTOR(linear_feedback_shift_engine, Chris@16: UIntType, s0) Chris@16: { seed(s0); } Chris@16: Chris@16: /** Constructs a @c linear_feedback_shift_engine, seeding it with seq. */ Chris@16: BOOST_RANDOM_DETAIL_SEED_SEQ_CONSTRUCTOR(linear_feedback_shift_engine, Chris@16: SeedSeq, seq) Chris@16: { seed(seq); } Chris@16: Chris@16: /** Chris@16: * Constructs a @c linear_feedback_shift_engine, seeding it with Chris@16: * values from the range [first, last). Chris@16: */ Chris@16: template linear_feedback_shift_engine(It& first, It last) Chris@16: { seed(first, last); } Chris@16: Chris@16: /** Seeds a @c linear_feedback_shift_engine with the default seed. */ Chris@16: void seed() { seed(default_seed); } Chris@16: Chris@16: /** Seeds a @c linear_feedback_shift_engine with @c s0. */ Chris@16: BOOST_RANDOM_DETAIL_ARITHMETIC_SEED(linear_feedback_shift_engine, Chris@16: UIntType, s0) Chris@16: { Chris@16: value = s0 & wordmask(); Chris@16: if(value < (1 << (w-k))) { Chris@16: value += 1 << (w-k); Chris@16: } Chris@16: } Chris@16: Chris@16: /** Chris@16: * Seeds a @c linear_feedback_shift_engine with values Chris@16: * produced by @c seq.generate(). Chris@16: */ Chris@16: BOOST_RANDOM_DETAIL_SEED_SEQ_SEED(linear_feedback_shift_engine, Chris@16: SeedSeq, seq) Chris@16: { seed(detail::seed_one_int(seq)); } Chris@16: Chris@16: /** Chris@16: * Seeds a @c linear_feedback_shift_engine with values Chris@16: * from the range [first, last). Chris@16: */ Chris@16: template void seed(It& first, It last) Chris@16: { Chris@16: seed(detail::get_one_int(first, last)); Chris@16: } Chris@16: Chris@16: /** Returns the next value of the generator. */ Chris@16: result_type operator()() Chris@16: { Chris@16: const UIntType b = (((value << q) ^ value) & wordmask()) >> (k-s); Chris@16: const UIntType mask = (wordmask() << (w-k)) & wordmask(); Chris@16: value = ((value & mask) << s) ^ b; Chris@16: return value; Chris@16: } Chris@16: Chris@16: /** Fills a range with random values */ Chris@16: template Chris@16: void generate(Iter first, Iter last) Chris@16: { detail::generate_from_int(*this, first, last); } Chris@16: Chris@16: /** Advances the state of the generator by @c z. */ Chris@16: void discard(boost::uintmax_t z) Chris@16: { Chris@16: for(boost::uintmax_t j = 0; j < z; ++j) { Chris@16: (*this)(); Chris@16: } Chris@16: } Chris@16: Chris@16: /** Chris@16: * Writes the textual representation of the generator to a @c std::ostream. Chris@16: */ Chris@16: BOOST_RANDOM_DETAIL_OSTREAM_OPERATOR(os, linear_feedback_shift_engine, x) Chris@16: { Chris@16: os << x.value; Chris@16: return os; Chris@16: } Chris@16: Chris@16: /** Chris@16: * Reads the textual representation of the generator from a @c std::istream. Chris@16: */ Chris@16: BOOST_RANDOM_DETAIL_ISTREAM_OPERATOR(is, linear_feedback_shift_engine, x) Chris@16: { Chris@16: is >> x.value; Chris@16: return is; Chris@16: } Chris@16: Chris@16: /** Chris@16: * Returns true if the two generators will produce identical Chris@16: * sequences of outputs. Chris@16: */ Chris@16: BOOST_RANDOM_DETAIL_EQUALITY_OPERATOR(linear_feedback_shift_engine, x, y) Chris@16: { return x.value == y.value; } Chris@16: Chris@16: /** Chris@16: * Returns true if the two generators will produce different Chris@16: * sequences of outputs. Chris@16: */ Chris@16: BOOST_RANDOM_DETAIL_INEQUALITY_OPERATOR(linear_feedback_shift_engine) Chris@16: Chris@16: private: Chris@16: /// \cond show_private Chris@16: static UIntType wordmask() { return boost::low_bits_mask_t::sig_bits; } Chris@16: /// \endcond Chris@16: UIntType value; Chris@16: }; Chris@16: Chris@16: #ifndef BOOST_NO_INCLASS_MEMBER_INITIALIZATION Chris@16: // A definition is required even for integral static constants Chris@16: template Chris@16: const bool linear_feedback_shift_engine::has_fixed_range; Chris@16: template Chris@16: const int linear_feedback_shift_engine::word_size; Chris@16: template Chris@16: const int linear_feedback_shift_engine::exponent1; Chris@16: template Chris@16: const int linear_feedback_shift_engine::exponent2; Chris@16: template Chris@16: const int linear_feedback_shift_engine::step_size; Chris@16: template Chris@16: const UIntType linear_feedback_shift_engine::default_seed; Chris@16: #endif Chris@16: Chris@16: /// \cond show_deprecated Chris@16: Chris@16: /** Provided for backwards compatibility. */ Chris@16: template Chris@16: class linear_feedback_shift : Chris@16: public linear_feedback_shift_engine Chris@16: { Chris@16: typedef linear_feedback_shift_engine base_type; Chris@16: public: Chris@16: linear_feedback_shift() {} Chris@16: BOOST_RANDOM_DETAIL_SEED_SEQ_CONSTRUCTOR(linear_feedback_shift, Chris@16: SeedSeq, seq) Chris@16: { seed(seq); } Chris@16: BOOST_RANDOM_DETAIL_ARITHMETIC_CONSTRUCTOR(linear_feedback_shift, Chris@16: UIntType, val) Chris@16: { seed(val); } Chris@16: template Chris@16: linear_feedback_shift(It& first, It last) : base_type(first, last) {} Chris@16: }; Chris@16: Chris@16: /// \endcond Chris@16: Chris@16: } // namespace random Chris@16: } // namespace boost Chris@16: Chris@16: #endif // BOOST_RANDOM_LINEAR_FEEDBACK_SHIFT_HPP