PageRenderTime 48ms CodeModel.GetById 8ms app.highlight 29ms RepoModel.GetById 5ms app.codeStats 0ms

/Src/Dependencies/Boost/boost/random/shuffle_order.hpp

http://hadesmem.googlecode.com/
C++ Header | 269 lines | 132 code | 32 blank | 105 comment | 16 complexity | 425ac0426924890666aabe5387dc8b73 MD5 | raw file
  1/* boost random/shuffle_order.hpp header file
  2 *
  3 * Copyright Jens Maurer 2000-2001
  4 * Copyright Steven Watanabe 2010
  5 * Distributed under the Boost Software License, Version 1.0. (See
  6 * accompanying file LICENSE_1_0.txt or copy at
  7 * http://www.boost.org/LICENSE_1_0.txt)
  8 *
  9 * See http://www.boost.org for most recent version including documentation.
 10 *
 11 * $Id: shuffle_order.hpp 71018 2011-04-05 21:27:52Z steven_watanabe $
 12 *
 13 */
 14
 15#ifndef BOOST_RANDOM_SHUFFLE_ORDER_HPP
 16#define BOOST_RANDOM_SHUFFLE_ORDER_HPP
 17
 18#include <iostream>
 19#include <algorithm>     // std::copy
 20#include <cassert>
 21#include <boost/config.hpp>
 22#include <boost/limits.hpp>
 23#include <boost/static_assert.hpp>
 24#include <boost/cstdint.hpp>
 25#include <boost/random/detail/operators.hpp>
 26#include <boost/random/detail/seed.hpp>
 27#include <boost/random/detail/signed_unsigned_tools.hpp>
 28#include <boost/random/linear_congruential.hpp>
 29
 30#include <boost/random/detail/disable_warnings.hpp>
 31
 32namespace boost {
 33namespace random {
 34
 35/**
 36 * Instatiations of class template @c shuffle_order_engine model a
 37 * \pseudo_random_number_generator. It mixes the output
 38 * of some (usually \linear_congruential_engine)
 39 * \uniform_random_number_generator to get better statistical properties.
 40 * The algorithm is described in
 41 *
 42 *  @blockquote
 43 *  "Improving a poor random number generator", Carter Bays
 44 *  and S.D. Durham, ACM Transactions on Mathematical Software,
 45 *  Vol 2, No. 1, March 1976, pp. 59-64.
 46 *  http://doi.acm.org/10.1145/355666.355670
 47 *  @endblockquote
 48 *
 49 * The output of the base generator is buffered in an array of
 50 * length k. Every output X(n) has a second role: It gives an
 51 * index into the array where X(n+1) will be retrieved. Used
 52 * array elements are replaced with fresh output from the base
 53 * generator.
 54 *
 55 * Template parameters are the base generator and the array
 56 * length k, which should be around 100.
 57 */
 58template<class UniformRandomNumberGenerator, std::size_t k>
 59class shuffle_order_engine
 60{
 61public:
 62    typedef UniformRandomNumberGenerator base_type;
 63    typedef typename base_type::result_type result_type;
 64
 65    BOOST_STATIC_CONSTANT(bool, has_fixed_range = false);
 66    BOOST_STATIC_CONSTANT(std::size_t, buffer_size = k);
 67    BOOST_STATIC_CONSTANT(std::size_t, table_size = k);
 68
 69    BOOST_STATIC_ASSERT(std::numeric_limits<result_type>::is_integer);
 70    BOOST_STATIC_ASSERT(k > 0);
 71
 72    /**
 73     * Constructs a @c shuffle_order_engine by invoking the
 74     * default constructor of the base generator.
 75     *
 76     * Complexity: Exactly k+1 invocations of the base generator.
 77     */
 78    shuffle_order_engine() : _rng() { init(); }
 79    /**
 80     * Constructs a @c shuffle_output_engine by invoking the one-argument
 81     * constructor of the base generator with the parameter seed.
 82     *
 83     * Complexity: Exactly k+1 invocations of the base generator.
 84     */
 85    BOOST_RANDOM_DETAIL_ARITHMETIC_CONSTRUCTOR(shuffle_order_engine,
 86                                               result_type, s)
 87    { _rng.seed(s); init(); }
 88    BOOST_RANDOM_DETAIL_SEED_SEQ_CONSTRUCTOR(shuffle_order_engine, SeedSeq, seq)
 89    { _rng.seed(seq); init(); }
 90    /**
 91     * Constructs a @c shuffle_output_engine by using a copy
 92     * of the provided generator.
 93     *
 94     * Precondition: The template argument UniformRandomNumberGenerator
 95     * shall denote a CopyConstructible type.
 96     *
 97     * Complexity: Exactly k+1 invocations of the base generator.
 98     */
 99    explicit shuffle_order_engine(const base_type & rng) : _rng(rng) { init(); }
100
101#ifndef BOOST_NO_RVALUE_REFERENCES
102    explicit shuffle_order_engine(base_type&& rng) : _rng(rng) { init(); }
103#endif
104
105    template<class It> shuffle_order_engine(It& first, It last)
106      : _rng(first, last) { init(); }
107    void seed() { _rng.seed(); init(); }
108    /**
109     * Invokes the one-argument seed method of the base generator
110     * with the parameter seed and re-initializes the internal buffer array.
111     *
112     * Complexity: Exactly k+1 invocations of the base generator.
113     */
114    BOOST_RANDOM_DETAIL_ARITHMETIC_SEED(shuffle_order_engine,
115        result_type, seed_arg)
116    { _rng.seed(seed_arg); init(); }
117    /**
118     * Invokes the one-argument seed method of the base generator
119     * with the parameter seq and re-initializes the internal buffer array.
120     *
121     * Complexity: Exactly k+1 invocations of the base generator.
122     */
123    BOOST_RANDOM_DETAIL_SEED_SEQ_SEED(shuffle_order_engine, SeedSeq, seq)
124    { _rng.seed(seq); init(); }
125    template<class It> void seed(It& first, It last)
126    { _rng.seed(first, last); init(); }
127
128    const base_type& base() const { return _rng; }
129
130    result_type operator()() {
131        // calculating the range every time may seem wasteful.  However, this
132        // makes the information locally available for the optimizer.
133        typedef typename make_unsigned<result_type>::type base_unsigned;
134        const base_unsigned brange =
135            detail::subtract<result_type>()((max)(), (min)());
136        const base_unsigned off =
137            detail::subtract<result_type>()(y, (min)());
138
139        base_unsigned j;
140        if(k == 1) {
141            j = 0;
142        } else if(brange < (std::numeric_limits<base_unsigned>::max)() / k) {
143            // try to do it in the native type if we know that it won't
144            // overflow
145            j = k * off / (brange + 1);
146        } else if(brange < (std::numeric_limits<uintmax_t>::max)() / k) {
147            // Otherwise try to use uint64_t
148            j = static_cast<base_unsigned>(
149                static_cast<uintmax_t>(off) * k /
150                (static_cast<uintmax_t>(brange) + 1));
151        } else {
152            boost::uintmax_t divisor =
153                static_cast<boost::uintmax_t>(brange) + 1;
154            j = static_cast<base_unsigned>(detail::muldiv(off, k, divisor));
155        }
156        // assert(0 <= j && j < k);
157        y = v[j];
158        v[j] = _rng();
159        return y;
160    }
161
162    /** Advances the generator by z steps. */
163    void discard(boost::uintmax_t z)
164    {
165        for(boost::uintmax_t j = 0; j < z; ++j) {
166            (*this)();
167        }
168    }
169
170    /** Fills a range with pseudo-random values. */
171    template<class Iter>
172    void generate(Iter first, Iter last)
173    { detail::generate_from_int(*this, first, last); }
174
175    /** Returns the smallest value that the generator can produce. */
176    static result_type min BOOST_PREVENT_MACRO_SUBSTITUTION ()
177    { return (base_type::min)(); }
178    /** Returns the largest value that the generator can produce. */
179    static result_type max BOOST_PREVENT_MACRO_SUBSTITUTION ()
180    { return (base_type::max)(); }
181
182    /** Writes a @c shuffle_order_engine to a @c std::ostream. */
183    BOOST_RANDOM_DETAIL_OSTREAM_OPERATOR(os, shuffle_order_engine, s)
184    {
185        os << s._rng;
186        for(std::size_t i = 0; i < k; ++i)
187            os << ' ' << s.v[i];
188        os << ' ' << s.y;
189        return os;
190    }
191
192    /** Reads a @c shuffle_order_engine from a @c std::istream. */
193    BOOST_RANDOM_DETAIL_ISTREAM_OPERATOR(is, shuffle_order_engine, s)
194    {
195        is >> s._rng;
196        for(std::size_t i = 0; i < k; ++i)
197            is >> std::ws >> s.v[i];
198        is >> std::ws >> s.y;
199        return is;
200    }
201
202    /** Returns true if the two generators will produce identical sequences. */
203    BOOST_RANDOM_DETAIL_EQUALITY_OPERATOR(shuffle_order_engine, x, y)
204    { return x._rng == y._rng && x.y == y.y && std::equal(x.v, x.v+k, y.v); }
205    /** Returns true if the two generators will produce different sequences. */
206    BOOST_RANDOM_DETAIL_INEQUALITY_OPERATOR(shuffle_order_engine)
207
208private:
209
210    /// \cond show_private
211
212    void init()
213    {
214        // we cannot use std::generate, because it uses pass-by-value for _rng
215        for(result_type * p = v; p != v+k; ++p)
216            *p = _rng();
217        y = _rng();
218    }
219
220    /// \endcond
221
222    base_type _rng;
223    result_type v[k];
224    result_type y;
225};
226
227#ifndef BOOST_NO_INCLASS_MEMBER_INITIALIZATION
228//  A definition is required even for integral static constants
229template<class URNG, std::size_t k>
230const bool shuffle_order_engine<URNG, k>::has_fixed_range;
231template<class URNG, std::size_t k>
232const std::size_t shuffle_order_engine<URNG, k>::table_size;
233template<class URNG, std::size_t k>
234const std::size_t shuffle_order_engine<URNG, k>::buffer_size;
235#endif
236
237/**
238 * According to Harry Erwin (private e-mail), the specialization
239 * @c kreutzer1986 was suggested in:
240 *
241 * @blockquote
242 * "System Simulation: Programming Styles and Languages (International
243 * Computer Science Series)", Wolfgang Kreutzer, Addison-Wesley, December 1986.
244 * @endblockquote
245 */
246typedef shuffle_order_engine<
247    linear_congruential_engine<uint32_t, 1366, 150889, 714025>,
248    97> kreutzer1986;
249
250/**
251 * The specialization @c knuth_b is specified by the C++ standard.
252 * It is described in
253 *
254 * @blockquote
255 * "The Art of Computer Programming, Second Edition, Volume 2,
256 * Seminumerical Algorithms", Donald Knuth, Addison-Wesley, 1981.
257 * @endblockquote
258 */
259typedef shuffle_order_engine<minstd_rand0, 256> knuth_b;
260
261} // namespace random
262
263using random::kreutzer1986;
264
265} // namespace boost
266
267#include <boost/random/detail/enable_warnings.hpp>
268
269#endif // BOOST_RANDOM_SHUFFLE_OUTPUT_HPP