614 lines
		
	
	
		
			22 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
			
		
		
	
	
			614 lines
		
	
	
		
			22 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
/* 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$
 | 
						|
 *
 | 
						|
 * Revision history
 | 
						|
 *  2002-03-02  created
 | 
						|
 */
 | 
						|
 | 
						|
#ifndef BOOST_RANDOM_SUBTRACT_WITH_CARRY_HPP
 | 
						|
#define BOOST_RANDOM_SUBTRACT_WITH_CARRY_HPP
 | 
						|
 | 
						|
#include <boost/config/no_tr1/cmath.hpp>         // std::pow
 | 
						|
#include <iostream>
 | 
						|
#include <algorithm>     // std::equal
 | 
						|
#include <stdexcept>
 | 
						|
#include <boost/config.hpp>
 | 
						|
#include <boost/limits.hpp>
 | 
						|
#include <boost/cstdint.hpp>
 | 
						|
#include <boost/static_assert.hpp>
 | 
						|
#include <boost/integer/static_log2.hpp>
 | 
						|
#include <boost/integer/integer_mask.hpp>
 | 
						|
#include <boost/detail/workaround.hpp>
 | 
						|
#include <boost/random/detail/config.hpp>
 | 
						|
#include <boost/random/detail/seed.hpp>
 | 
						|
#include <boost/random/detail/operators.hpp>
 | 
						|
#include <boost/random/detail/seed_impl.hpp>
 | 
						|
#include <boost/random/detail/generator_seed_seq.hpp>
 | 
						|
#include <boost/random/linear_congruential.hpp>
 | 
						|
 | 
						|
 | 
						|
namespace boost {
 | 
						|
namespace random {
 | 
						|
 | 
						|
namespace detail {
 | 
						|
   
 | 
						|
struct subtract_with_carry_discard
 | 
						|
{
 | 
						|
    template<class Engine>
 | 
						|
    static void apply(Engine& eng, boost::uintmax_t z)
 | 
						|
    {
 | 
						|
        typedef typename Engine::result_type IntType;
 | 
						|
        const std::size_t short_lag = Engine::short_lag;
 | 
						|
        const std::size_t long_lag = Engine::long_lag;
 | 
						|
        std::size_t k = eng.k;
 | 
						|
        IntType carry = eng.carry;
 | 
						|
        if(k != 0) {
 | 
						|
            // increment k until it becomes 0.
 | 
						|
            if(k < short_lag) {
 | 
						|
                std::size_t limit = (short_lag - k) < z?
 | 
						|
                    short_lag : (k + static_cast<std::size_t>(z));
 | 
						|
                for(std::size_t j = k; j < limit; ++j) {
 | 
						|
                    carry = eng.do_update(j, j + long_lag - short_lag, carry);
 | 
						|
                }
 | 
						|
            }
 | 
						|
            std::size_t limit = (long_lag - k) < z?
 | 
						|
                long_lag : (k + static_cast<std::size_t>(z));
 | 
						|
            std::size_t start = (k < short_lag ? short_lag : k);
 | 
						|
            for(std::size_t j = start; j < limit; ++j) {
 | 
						|
                carry = eng.do_update(j, j - short_lag, carry);
 | 
						|
            }
 | 
						|
        }
 | 
						|
 | 
						|
        k = ((z % long_lag) + k) % long_lag;
 | 
						|
 | 
						|
        if(k < z) {
 | 
						|
            // main loop: update full blocks from k = 0 to long_lag
 | 
						|
            for(std::size_t i = 0; i < (z - k) / long_lag; ++i) {
 | 
						|
                for(std::size_t j = 0; j < short_lag; ++j) {
 | 
						|
                    carry = eng.do_update(j, j + long_lag - short_lag, carry);
 | 
						|
                }
 | 
						|
                for(std::size_t j = short_lag; j < long_lag; ++j) {
 | 
						|
                    carry = eng.do_update(j, j - short_lag, carry);
 | 
						|
                }
 | 
						|
            }
 | 
						|
 | 
						|
            // Update the last partial block
 | 
						|
            std::size_t limit = short_lag < k? short_lag : k; 
 | 
						|
            for(std::size_t j = 0; j < limit; ++j) {
 | 
						|
                carry = eng.do_update(j, j + long_lag - short_lag, carry);
 | 
						|
            }
 | 
						|
            for(std::size_t j = short_lag; j < k; ++j) {
 | 
						|
                carry = eng.do_update(j, j - short_lag, carry);
 | 
						|
            }
 | 
						|
        }
 | 
						|
        eng.carry = carry;
 | 
						|
        eng.k = k;
 | 
						|
    }
 | 
						|
};
 | 
						|
 | 
						|
}
 | 
						|
 | 
						|
/**
 | 
						|
 * Instantiations of @c subtract_with_carry_engine model a
 | 
						|
 * \pseudo_random_number_generator.  The algorithm is
 | 
						|
 * described in
 | 
						|
 *
 | 
						|
 *  @blockquote
 | 
						|
 *  "A New Class of Random Number Generators", George
 | 
						|
 *  Marsaglia and Arif Zaman, Annals of Applied Probability,
 | 
						|
 *  Volume 1, Number 3 (1991), 462-480.
 | 
						|
 *  @endblockquote
 | 
						|
 */
 | 
						|
template<class IntType, std::size_t w, std::size_t s, std::size_t r>
 | 
						|
class subtract_with_carry_engine
 | 
						|
{
 | 
						|
public:
 | 
						|
    typedef IntType result_type;
 | 
						|
    BOOST_STATIC_CONSTANT(std::size_t, word_size = w);
 | 
						|
    BOOST_STATIC_CONSTANT(std::size_t, long_lag = r);
 | 
						|
    BOOST_STATIC_CONSTANT(std::size_t, short_lag = s);
 | 
						|
    BOOST_STATIC_CONSTANT(uint32_t, default_seed = 19780503u);
 | 
						|
 | 
						|
    // Required by the old Boost.Random concepts
 | 
						|
    BOOST_STATIC_CONSTANT(bool, has_fixed_range = false);
 | 
						|
    // Backwards compatibility
 | 
						|
    BOOST_STATIC_CONSTANT(result_type, modulus = (result_type(1) << w));
 | 
						|
    
 | 
						|
    BOOST_STATIC_ASSERT(std::numeric_limits<result_type>::is_integer);
 | 
						|
 | 
						|
    /**
 | 
						|
     * Constructs a new @c subtract_with_carry_engine and seeds
 | 
						|
     * it with the default seed.
 | 
						|
     */
 | 
						|
    subtract_with_carry_engine() { seed(); }
 | 
						|
    /**
 | 
						|
     * Constructs a new @c subtract_with_carry_engine and seeds
 | 
						|
     * it with @c value.
 | 
						|
     */
 | 
						|
    BOOST_RANDOM_DETAIL_ARITHMETIC_CONSTRUCTOR(subtract_with_carry_engine,
 | 
						|
                                               IntType, value)
 | 
						|
    { seed(value); }
 | 
						|
    /**
 | 
						|
     * Constructs a new @c subtract_with_carry_engine and seeds
 | 
						|
     * it with values produced by @c seq.generate().
 | 
						|
     */
 | 
						|
    BOOST_RANDOM_DETAIL_SEED_SEQ_CONSTRUCTOR(subtract_with_carry_engine,
 | 
						|
                                             SeedSeq, seq)
 | 
						|
    { seed(seq); }
 | 
						|
    /**
 | 
						|
     * Constructs a new @c subtract_with_carry_engine and seeds
 | 
						|
     * it with values from a range.  first is updated to point
 | 
						|
     * one past the last value consumed.  If there are not
 | 
						|
     * enough elements in the range to fill the entire state of
 | 
						|
     * the generator, throws @c std::invalid_argument.
 | 
						|
     */
 | 
						|
    template<class It> subtract_with_carry_engine(It& first, It last)
 | 
						|
    { seed(first,last); }
 | 
						|
 | 
						|
    // compiler-generated copy ctor and assignment operator are fine
 | 
						|
 | 
						|
    /** Seeds the generator with the default seed. */
 | 
						|
    void seed() { seed(default_seed); }
 | 
						|
    BOOST_RANDOM_DETAIL_ARITHMETIC_SEED(subtract_with_carry_engine,
 | 
						|
                                        IntType, value)
 | 
						|
    {
 | 
						|
        typedef linear_congruential_engine<uint32_t,40014,0,2147483563> gen_t;
 | 
						|
        gen_t intgen(static_cast<boost::uint32_t>(value == 0 ? default_seed : value));
 | 
						|
        detail::generator_seed_seq<gen_t> gen(intgen);
 | 
						|
        seed(gen);
 | 
						|
    }
 | 
						|
 | 
						|
    /** Seeds the generator with values produced by @c seq.generate(). */
 | 
						|
    BOOST_RANDOM_DETAIL_SEED_SEQ_SEED(subtract_with_carry, SeedSeq, seq)
 | 
						|
    {
 | 
						|
        detail::seed_array_int<w>(seq, x);
 | 
						|
        carry = (x[long_lag-1] == 0);
 | 
						|
        k = 0;
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Seeds the generator with values from a range.  Updates @c first to
 | 
						|
     * point one past the last consumed value.  If the range does not
 | 
						|
     * contain enough elements to fill the entire state of the generator,
 | 
						|
     * throws @c std::invalid_argument.
 | 
						|
     */
 | 
						|
    template<class It>
 | 
						|
    void seed(It& first, It last)
 | 
						|
    {
 | 
						|
        detail::fill_array_int<w>(first, last, x);
 | 
						|
        carry = (x[long_lag-1] == 0);
 | 
						|
        k = 0;
 | 
						|
    }
 | 
						|
 | 
						|
    /** 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 boost::low_bits_mask_t<w>::sig_bits; }
 | 
						|
 | 
						|
    /** Returns the next value of the generator. */
 | 
						|
    result_type operator()()
 | 
						|
    {
 | 
						|
        std::size_t short_index =
 | 
						|
            (k < short_lag)?
 | 
						|
                (k + long_lag - short_lag) :
 | 
						|
                (k - short_lag);
 | 
						|
        carry = do_update(k, short_index, carry);
 | 
						|
        IntType result = x[k];
 | 
						|
        ++k;
 | 
						|
        if(k >= long_lag)
 | 
						|
            k = 0;
 | 
						|
        return result;
 | 
						|
    }
 | 
						|
 | 
						|
    /** Advances the state of the generator by @c z. */
 | 
						|
    void discard(boost::uintmax_t z)
 | 
						|
    {
 | 
						|
        detail::subtract_with_carry_discard::apply(*this, z);
 | 
						|
    }
 | 
						|
 | 
						|
    /** Fills a range with random values. */
 | 
						|
    template<class It>
 | 
						|
    void generate(It first, It last)
 | 
						|
    { detail::generate_from_int(*this, first, last); }
 | 
						|
 
 | 
						|
    /** Writes a @c subtract_with_carry_engine to a @c std::ostream. */
 | 
						|
    BOOST_RANDOM_DETAIL_OSTREAM_OPERATOR(os, subtract_with_carry_engine, f)
 | 
						|
    {
 | 
						|
        for(unsigned int j = 0; j < f.long_lag; ++j)
 | 
						|
            os << f.compute(j) << ' ';
 | 
						|
        os << f.carry;
 | 
						|
        return os;
 | 
						|
    }
 | 
						|
 | 
						|
    /** Reads a @c subtract_with_carry_engine from a @c std::istream. */
 | 
						|
    BOOST_RANDOM_DETAIL_ISTREAM_OPERATOR(is, subtract_with_carry_engine, f)
 | 
						|
    {
 | 
						|
        for(unsigned int j = 0; j < f.long_lag; ++j)
 | 
						|
            is >> f.x[j] >> std::ws;
 | 
						|
        is >> f.carry;
 | 
						|
        f.k = 0;
 | 
						|
        return is;
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Returns true if the two generators will produce identical
 | 
						|
     * sequences of values.
 | 
						|
     */
 | 
						|
    BOOST_RANDOM_DETAIL_EQUALITY_OPERATOR(subtract_with_carry_engine, x, y)
 | 
						|
    {
 | 
						|
        for(unsigned int j = 0; j < r; ++j)
 | 
						|
            if(x.compute(j) != y.compute(j))
 | 
						|
                return false;
 | 
						|
        return true;
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Returns true if the two generators will produce different
 | 
						|
     * sequences of values.
 | 
						|
     */
 | 
						|
    BOOST_RANDOM_DETAIL_INEQUALITY_OPERATOR(subtract_with_carry_engine)
 | 
						|
 | 
						|
private:
 | 
						|
    /// \cond show_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];
 | 
						|
    }
 | 
						|
 | 
						|
    friend struct detail::subtract_with_carry_discard;
 | 
						|
 | 
						|
    IntType do_update(std::size_t current, std::size_t short_index, IntType carry)
 | 
						|
    {
 | 
						|
        IntType delta;
 | 
						|
        IntType temp = x[current] + carry;
 | 
						|
        if (x[short_index] >= temp) {
 | 
						|
            // x(n) >= 0
 | 
						|
            delta =  x[short_index] - temp;
 | 
						|
            carry = 0;
 | 
						|
        } else {
 | 
						|
            // x(n) < 0
 | 
						|
            delta = modulus - temp + x[short_index];
 | 
						|
            carry = 1;
 | 
						|
        }
 | 
						|
        x[current] = delta;
 | 
						|
        return carry;
 | 
						|
    }
 | 
						|
    /// \endcond
 | 
						|
 | 
						|
    // 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];
 | 
						|
    std::size_t k;
 | 
						|
    IntType carry;
 | 
						|
};
 | 
						|
 | 
						|
#ifndef BOOST_NO_INCLASS_MEMBER_INITIALIZATION
 | 
						|
//  A definition is required even for integral static constants
 | 
						|
template<class IntType, std::size_t w, std::size_t s, std::size_t r>
 | 
						|
const bool subtract_with_carry_engine<IntType, w, s, r>::has_fixed_range;
 | 
						|
template<class IntType, std::size_t w, std::size_t s, std::size_t r>
 | 
						|
const IntType subtract_with_carry_engine<IntType, w, s, r>::modulus;
 | 
						|
template<class IntType, std::size_t w, std::size_t s, std::size_t r>
 | 
						|
const std::size_t subtract_with_carry_engine<IntType, w, s, r>::word_size;
 | 
						|
template<class IntType, std::size_t w, std::size_t s, std::size_t r>
 | 
						|
const std::size_t subtract_with_carry_engine<IntType, w, s, r>::long_lag;
 | 
						|
template<class IntType, std::size_t w, std::size_t s, std::size_t r>
 | 
						|
const std::size_t subtract_with_carry_engine<IntType, w, s, r>::short_lag;
 | 
						|
template<class IntType, std::size_t w, std::size_t s, std::size_t r>
 | 
						|
const uint32_t subtract_with_carry_engine<IntType, w, s, r>::default_seed;
 | 
						|
#endif
 | 
						|
 | 
						|
 | 
						|
// use a floating-point representation to produce values in [0..1)
 | 
						|
/**
 | 
						|
 * Instantiations of \subtract_with_carry_01_engine model a
 | 
						|
 * \pseudo_random_number_generator.  The algorithm is
 | 
						|
 * described in
 | 
						|
 *
 | 
						|
 *  @blockquote
 | 
						|
 *  "A New Class of Random Number Generators", George
 | 
						|
 *  Marsaglia and Arif Zaman, Annals of Applied Probability,
 | 
						|
 *  Volume 1, Number 3 (1991), 462-480.
 | 
						|
 *  @endblockquote
 | 
						|
 */
 | 
						|
template<class RealType, std::size_t w, std::size_t s, std::size_t r>
 | 
						|
class subtract_with_carry_01_engine
 | 
						|
{
 | 
						|
public:
 | 
						|
    typedef RealType result_type;
 | 
						|
    BOOST_STATIC_CONSTANT(bool, has_fixed_range = false);
 | 
						|
    BOOST_STATIC_CONSTANT(std::size_t, word_size = w);
 | 
						|
    BOOST_STATIC_CONSTANT(std::size_t, long_lag = r);
 | 
						|
    BOOST_STATIC_CONSTANT(std::size_t, short_lag = s);
 | 
						|
    BOOST_STATIC_CONSTANT(boost::uint32_t, default_seed = 19780503u);
 | 
						|
 | 
						|
    BOOST_STATIC_ASSERT(!std::numeric_limits<result_type>::is_integer);
 | 
						|
 | 
						|
    /** Creates a new \subtract_with_carry_01_engine using the default seed. */
 | 
						|
    subtract_with_carry_01_engine() { init_modulus(); seed(); }
 | 
						|
    /** Creates a new subtract_with_carry_01_engine and seeds it with value. */
 | 
						|
    BOOST_RANDOM_DETAIL_ARITHMETIC_CONSTRUCTOR(subtract_with_carry_01_engine,
 | 
						|
                                               boost::uint32_t, value)
 | 
						|
    { init_modulus(); seed(value); }
 | 
						|
    /**
 | 
						|
     * Creates a new \subtract_with_carry_01_engine and seeds with values
 | 
						|
     * produced by seq.generate().
 | 
						|
     */
 | 
						|
    BOOST_RANDOM_DETAIL_SEED_SEQ_CONSTRUCTOR(subtract_with_carry_01_engine,
 | 
						|
                                             SeedSeq, seq)
 | 
						|
    { init_modulus(); seed(seq); }
 | 
						|
    /**
 | 
						|
     * Creates a new \subtract_with_carry_01_engine and seeds it with values
 | 
						|
     * from a range.  Advances first to point one past the last consumed
 | 
						|
     * value.  If the range does not contain enough elements to fill the
 | 
						|
     * entire state, throws @c std::invalid_argument.
 | 
						|
     */
 | 
						|
    template<class It> subtract_with_carry_01_engine(It& first, It last)
 | 
						|
    { init_modulus(); seed(first,last); }
 | 
						|
 | 
						|
private:
 | 
						|
    /// \cond show_private
 | 
						|
    void init_modulus()
 | 
						|
    {
 | 
						|
#ifndef BOOST_NO_STDC_NAMESPACE
 | 
						|
        // allow for Koenig lookup
 | 
						|
        using std::pow;
 | 
						|
#endif
 | 
						|
        _modulus = pow(RealType(2), RealType(word_size));
 | 
						|
    }
 | 
						|
    /// \endcond
 | 
						|
 | 
						|
public:
 | 
						|
    // compiler-generated copy ctor and assignment operator are fine
 | 
						|
 | 
						|
    /** Seeds the generator with the default seed. */
 | 
						|
    void seed() { seed(default_seed); }
 | 
						|
 | 
						|
    /** Seeds the generator with @c value. */
 | 
						|
    BOOST_RANDOM_DETAIL_ARITHMETIC_SEED(subtract_with_carry_01_engine,
 | 
						|
                                        boost::uint32_t, value)
 | 
						|
    {
 | 
						|
        typedef linear_congruential_engine<uint32_t, 40014, 0, 2147483563> gen_t;
 | 
						|
        gen_t intgen(value == 0 ? default_seed : value);
 | 
						|
        detail::generator_seed_seq<gen_t> gen(intgen);
 | 
						|
        seed(gen);
 | 
						|
    }
 | 
						|
 | 
						|
    /** Seeds the generator with values produced by @c seq.generate(). */
 | 
						|
    BOOST_RANDOM_DETAIL_SEED_SEQ_SEED(subtract_with_carry_01_engine,
 | 
						|
                                      SeedSeq, seq)
 | 
						|
    {
 | 
						|
        detail::seed_array_real<w>(seq, x);
 | 
						|
        carry = (x[long_lag-1] ? result_type(0) : result_type(1 / _modulus));
 | 
						|
        k = 0;
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * Seeds the generator with values from a range.  Updates first to
 | 
						|
     * point one past the last consumed element.  If there are not
 | 
						|
     * enough elements in the range to fill the entire state, throws
 | 
						|
     * @c std::invalid_argument.
 | 
						|
     */
 | 
						|
    template<class It>
 | 
						|
    void seed(It& first, It last)
 | 
						|
    {
 | 
						|
        detail::fill_array_real<w>(first, last, x);
 | 
						|
        carry = (x[long_lag-1] ? result_type(0) : result_type(1 / _modulus));
 | 
						|
        k = 0;
 | 
						|
    }
 | 
						|
 | 
						|
    /** Returns the smallest value that the generator can produce. */
 | 
						|
    static result_type min BOOST_PREVENT_MACRO_SUBSTITUTION ()
 | 
						|
    { return result_type(0); }
 | 
						|
    /** Returns the largest value that the generator can produce. */
 | 
						|
    static result_type max BOOST_PREVENT_MACRO_SUBSTITUTION ()
 | 
						|
    { return result_type(1); }
 | 
						|
 | 
						|
    /** Returns the next value of the generator. */
 | 
						|
    result_type operator()()
 | 
						|
    {
 | 
						|
        std::size_t short_index =
 | 
						|
            (k < short_lag) ?
 | 
						|
                (k + long_lag - short_lag) :
 | 
						|
                (k - short_lag);
 | 
						|
        carry = do_update(k, short_index, carry);
 | 
						|
        RealType result = x[k];
 | 
						|
        ++k;
 | 
						|
        if(k >= long_lag)
 | 
						|
            k = 0;
 | 
						|
        return result;
 | 
						|
    }
 | 
						|
 | 
						|
    /** Advances the state of the generator by @c z. */
 | 
						|
    void discard(boost::uintmax_t z)
 | 
						|
    { detail::subtract_with_carry_discard::apply(*this, z); }
 | 
						|
 | 
						|
    /** Fills a range with random values. */
 | 
						|
    template<class Iter>
 | 
						|
    void generate(Iter first, Iter last)
 | 
						|
    { detail::generate_from_real(*this, first, last); }
 | 
						|
 | 
						|
    /** Writes a \subtract_with_carry_01_engine to a @c std::ostream. */
 | 
						|
    BOOST_RANDOM_DETAIL_OSTREAM_OPERATOR(os, subtract_with_carry_01_engine, f)
 | 
						|
    {
 | 
						|
        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;
 | 
						|
    }
 | 
						|
    
 | 
						|
    /** Reads a \subtract_with_carry_01_engine from a @c std::istream. */
 | 
						|
    BOOST_RANDOM_DETAIL_ISTREAM_OPERATOR(is, subtract_with_carry_01_engine, f)
 | 
						|
    {
 | 
						|
        RealType value;
 | 
						|
        for(unsigned int j = 0; j < long_lag; ++j) {
 | 
						|
            is >> value >> std::ws;
 | 
						|
            f.x[j] = value / f._modulus;
 | 
						|
        }
 | 
						|
        is >> value;
 | 
						|
        f.carry = value / f._modulus;
 | 
						|
        f.k = 0;
 | 
						|
        return is;
 | 
						|
    }
 | 
						|
 | 
						|
    /** Returns true if the two generators will produce identical sequences. */
 | 
						|
    BOOST_RANDOM_DETAIL_EQUALITY_OPERATOR(subtract_with_carry_01_engine, x, y)
 | 
						|
    {
 | 
						|
        for(unsigned int j = 0; j < r; ++j)
 | 
						|
            if(x.compute(j) != y.compute(j))
 | 
						|
                return false;
 | 
						|
        return true;
 | 
						|
    }
 | 
						|
 | 
						|
    /** Returns true if the two generators will produce different sequences. */
 | 
						|
    BOOST_RANDOM_DETAIL_INEQUALITY_OPERATOR(subtract_with_carry_01_engine)
 | 
						|
 | 
						|
private:
 | 
						|
    /// \cond show_private
 | 
						|
    RealType compute(unsigned int index) const
 | 
						|
    {
 | 
						|
        return x[(k+index) % long_lag];
 | 
						|
    }
 | 
						|
 | 
						|
    friend struct detail::subtract_with_carry_discard;
 | 
						|
 | 
						|
    RealType do_update(std::size_t current, std::size_t short_index, RealType carry)
 | 
						|
    {
 | 
						|
        RealType delta = x[short_index] - x[current] - carry;
 | 
						|
        if(delta < 0) {
 | 
						|
            delta += RealType(1);
 | 
						|
            carry = RealType(1)/_modulus;
 | 
						|
        } else {
 | 
						|
            carry = 0;
 | 
						|
        }
 | 
						|
        x[current] = delta;
 | 
						|
        return carry;
 | 
						|
    }
 | 
						|
    /// \endcond
 | 
						|
    std::size_t 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<class RealType, std::size_t w, std::size_t s, std::size_t r>
 | 
						|
const bool subtract_with_carry_01_engine<RealType, w, s, r>::has_fixed_range;
 | 
						|
template<class RealType, std::size_t w, std::size_t s, std::size_t r>
 | 
						|
const std::size_t subtract_with_carry_01_engine<RealType, w, s, r>::word_size;
 | 
						|
template<class RealType, std::size_t w, std::size_t s, std::size_t r>
 | 
						|
const std::size_t subtract_with_carry_01_engine<RealType, w, s, r>::long_lag;
 | 
						|
template<class RealType, std::size_t w, std::size_t s, std::size_t r>
 | 
						|
const std::size_t subtract_with_carry_01_engine<RealType, w, s, r>::short_lag;
 | 
						|
template<class RealType, std::size_t w, std::size_t s, std::size_t r>
 | 
						|
const uint32_t subtract_with_carry_01_engine<RealType, w, s, r>::default_seed;
 | 
						|
#endif
 | 
						|
 | 
						|
 | 
						|
/// \cond show_deprecated
 | 
						|
 | 
						|
template<class IntType, IntType m, unsigned s, unsigned r, IntType v>
 | 
						|
class subtract_with_carry :
 | 
						|
    public subtract_with_carry_engine<IntType,
 | 
						|
        boost::static_log2<m>::value, s, r>
 | 
						|
{
 | 
						|
    typedef subtract_with_carry_engine<IntType,
 | 
						|
        boost::static_log2<m>::value, s, r> base_type;
 | 
						|
public:
 | 
						|
    subtract_with_carry() {}
 | 
						|
    BOOST_RANDOM_DETAIL_GENERATOR_CONSTRUCTOR(subtract_with_carry, Gen, gen)
 | 
						|
    { seed(gen); }
 | 
						|
    BOOST_RANDOM_DETAIL_ARITHMETIC_CONSTRUCTOR(subtract_with_carry,
 | 
						|
                                               IntType, val)
 | 
						|
    { seed(val); }
 | 
						|
    template<class It>
 | 
						|
    subtract_with_carry(It& first, It last) : base_type(first, last) {}
 | 
						|
    void seed() { base_type::seed(); }
 | 
						|
    BOOST_RANDOM_DETAIL_GENERATOR_SEED(subtract_with_carry, Gen, gen)
 | 
						|
    {
 | 
						|
        detail::generator_seed_seq<Gen> seq(gen);
 | 
						|
        base_type::seed(seq);
 | 
						|
    }
 | 
						|
    BOOST_RANDOM_DETAIL_ARITHMETIC_SEED(subtract_with_carry, IntType, val)
 | 
						|
    { base_type::seed(val); }
 | 
						|
    template<class It>
 | 
						|
    void seed(It& first, It last) { base_type::seed(first, last); }
 | 
						|
};
 | 
						|
 | 
						|
template<class RealType, int w, unsigned s, unsigned r, int v = 0>
 | 
						|
class subtract_with_carry_01 :
 | 
						|
    public subtract_with_carry_01_engine<RealType, w, s, r>
 | 
						|
{
 | 
						|
    typedef subtract_with_carry_01_engine<RealType, w, s, r> base_type;
 | 
						|
public:
 | 
						|
    subtract_with_carry_01() {}
 | 
						|
    BOOST_RANDOM_DETAIL_GENERATOR_CONSTRUCTOR(subtract_with_carry_01, Gen, gen)
 | 
						|
    { seed(gen); }
 | 
						|
    BOOST_RANDOM_DETAIL_ARITHMETIC_CONSTRUCTOR(subtract_with_carry_01,
 | 
						|
                                               uint32_t, val)
 | 
						|
    { seed(val); }
 | 
						|
    template<class It>
 | 
						|
    subtract_with_carry_01(It& first, It last) : base_type(first, last) {}
 | 
						|
    void seed() { base_type::seed(); }
 | 
						|
    BOOST_RANDOM_DETAIL_GENERATOR_SEED(subtract_with_carry_01, Gen, gen)
 | 
						|
    {
 | 
						|
        detail::generator_seed_seq<Gen> seq(gen);
 | 
						|
        base_type::seed(seq);
 | 
						|
    }
 | 
						|
    BOOST_RANDOM_DETAIL_ARITHMETIC_SEED(subtract_with_carry_01, uint32_t, val)
 | 
						|
    { base_type::seed(val); }
 | 
						|
    template<class It>
 | 
						|
    void seed(It& first, It last) { base_type::seed(first, last); }
 | 
						|
};
 | 
						|
 | 
						|
/// \endcond
 | 
						|
 | 
						|
namespace detail {
 | 
						|
 | 
						|
template<class Engine>
 | 
						|
struct generator_bits;
 | 
						|
 | 
						|
template<class RealType, std::size_t w, std::size_t s, std::size_t r>
 | 
						|
struct generator_bits<subtract_with_carry_01_engine<RealType, w, s, r> > {
 | 
						|
    static std::size_t value() { return w; }
 | 
						|
};
 | 
						|
 | 
						|
template<class RealType, int w, unsigned s, unsigned r, int v>
 | 
						|
struct generator_bits<subtract_with_carry_01<RealType, w, s, r, v> > {
 | 
						|
    static std::size_t value() { return w; }
 | 
						|
};
 | 
						|
 | 
						|
}
 | 
						|
 | 
						|
} // namespace random
 | 
						|
} // namespace boost
 | 
						|
 | 
						|
#endif // BOOST_RANDOM_SUBTRACT_WITH_CARRY_HPP
 |