| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613 | /* 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 constantstemplate<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));    }    /// \endcondpublic:    // 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 constantstemplate<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_deprecatedtemplate<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); }};/// \endcondnamespace 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
 |