annotate DEPENDENCIES/generic/include/boost/random/additive_combine.hpp @ 125:34e428693f5d vext

Vext -> Repoint
author Chris Cannam
date Thu, 14 Jun 2018 11:15:39 +0100
parents c530137014c0
children
rev   line source
Chris@16 1 /* boost random/additive_combine.hpp header file
Chris@16 2 *
Chris@16 3 * Copyright Jens Maurer 2000-2001
Chris@16 4 * Distributed under the Boost Software License, Version 1.0. (See
Chris@16 5 * accompanying file LICENSE_1_0.txt or copy at
Chris@16 6 * http://www.boost.org/LICENSE_1_0.txt)
Chris@16 7 *
Chris@16 8 * See http://www.boost.org for most recent version including documentation.
Chris@16 9 *
Chris@101 10 * $Id$
Chris@16 11 *
Chris@16 12 * Revision history
Chris@16 13 * 2001-02-18 moved to individual header files
Chris@16 14 */
Chris@16 15
Chris@16 16 #ifndef BOOST_RANDOM_ADDITIVE_COMBINE_HPP
Chris@16 17 #define BOOST_RANDOM_ADDITIVE_COMBINE_HPP
Chris@16 18
Chris@16 19 #include <istream>
Chris@16 20 #include <iosfwd>
Chris@16 21 #include <algorithm> // for std::min and std::max
Chris@16 22 #include <boost/config.hpp>
Chris@16 23 #include <boost/cstdint.hpp>
Chris@16 24 #include <boost/random/detail/config.hpp>
Chris@16 25 #include <boost/random/detail/operators.hpp>
Chris@16 26 #include <boost/random/detail/seed.hpp>
Chris@16 27 #include <boost/random/linear_congruential.hpp>
Chris@16 28
Chris@16 29 namespace boost {
Chris@16 30 namespace random {
Chris@16 31
Chris@16 32 /**
Chris@16 33 * An instantiation of class template @c additive_combine_engine models a
Chris@16 34 * \pseudo_random_number_generator. It combines two multiplicative
Chris@16 35 * \linear_congruential_engine number generators, i.e. those with @c c = 0.
Chris@16 36 * It is described in
Chris@16 37 *
Chris@16 38 * @blockquote
Chris@16 39 * "Efficient and Portable Combined Random Number Generators", Pierre L'Ecuyer,
Chris@16 40 * Communications of the ACM, Vol. 31, No. 6, June 1988, pp. 742-749, 774
Chris@16 41 * @endblockquote
Chris@16 42 *
Chris@16 43 * The template parameters MLCG1 and MLCG2 shall denote two different
Chris@16 44 * \linear_congruential_engine number generators, each with c = 0. Each
Chris@16 45 * invocation returns a random number
Chris@16 46 * X(n) := (MLCG1(n) - MLCG2(n)) mod (m1 - 1),
Chris@16 47 * where m1 denotes the modulus of MLCG1.
Chris@16 48 */
Chris@16 49 template<class MLCG1, class MLCG2>
Chris@16 50 class additive_combine_engine
Chris@16 51 {
Chris@16 52 public:
Chris@16 53 typedef MLCG1 first_base;
Chris@16 54 typedef MLCG2 second_base;
Chris@16 55 typedef typename MLCG1::result_type result_type;
Chris@16 56
Chris@16 57 // Required by old Boost.Random concept
Chris@16 58 BOOST_STATIC_CONSTANT(bool, has_fixed_range = false);
Chris@16 59 /**
Chris@16 60 * Returns the smallest value that the generator can produce
Chris@16 61 */
Chris@16 62 static result_type min BOOST_PREVENT_MACRO_SUBSTITUTION ()
Chris@16 63 { return 1; }
Chris@16 64 /**
Chris@16 65 * Returns the largest value that the generator can produce
Chris@16 66 */
Chris@16 67 static result_type max BOOST_PREVENT_MACRO_SUBSTITUTION ()
Chris@16 68 { return MLCG1::modulus-1; }
Chris@16 69
Chris@16 70 /**
Chris@16 71 * Constructs an @c additive_combine_engine using the
Chris@16 72 * default constructors of the two base generators.
Chris@16 73 */
Chris@16 74 additive_combine_engine() : _mlcg1(), _mlcg2() { }
Chris@16 75 /**
Chris@16 76 * Constructs an @c additive_combine_engine, using seed as
Chris@16 77 * the constructor argument for both base generators.
Chris@16 78 */
Chris@16 79 BOOST_RANDOM_DETAIL_ARITHMETIC_CONSTRUCTOR(additive_combine_engine,
Chris@16 80 result_type, seed_arg)
Chris@16 81 {
Chris@16 82 _mlcg1.seed(seed_arg);
Chris@16 83 _mlcg2.seed(seed_arg);
Chris@16 84 }
Chris@16 85 /**
Chris@16 86 * Constructs an @c additive_combine_engine, using seq as
Chris@16 87 * the constructor argument for both base generators.
Chris@16 88 *
Chris@16 89 * @xmlwarning
Chris@16 90 * The semantics of this function are liable to change.
Chris@16 91 * A @c seed_seq is designed to generate all the seeds
Chris@16 92 * in one shot, but this seeds the two base engines
Chris@16 93 * independantly and probably ends up giving the same
Chris@16 94 * sequence to both.
Chris@16 95 * @endxmlwarning
Chris@16 96 */
Chris@16 97 BOOST_RANDOM_DETAIL_SEED_SEQ_CONSTRUCTOR(additive_combine_engine,
Chris@16 98 SeedSeq, seq)
Chris@16 99 {
Chris@16 100 _mlcg1.seed(seq);
Chris@16 101 _mlcg2.seed(seq);
Chris@16 102 }
Chris@16 103 /**
Chris@16 104 * Constructs an @c additive_combine_engine, using
Chris@16 105 * @c seed1 and @c seed2 as the constructor argument to
Chris@16 106 * the first and second base generators, respectively.
Chris@16 107 */
Chris@16 108 additive_combine_engine(typename MLCG1::result_type seed1,
Chris@16 109 typename MLCG2::result_type seed2)
Chris@16 110 : _mlcg1(seed1), _mlcg2(seed2) { }
Chris@16 111 /**
Chris@16 112 * Contructs an @c additive_combine_engine with
Chris@16 113 * values from the range defined by the input iterators first
Chris@16 114 * and last. first will be modified to point to the element
Chris@16 115 * after the last one used.
Chris@16 116 *
Chris@16 117 * Throws: @c std::invalid_argument if the input range is too small.
Chris@16 118 *
Chris@16 119 * Exception Safety: Basic
Chris@16 120 */
Chris@16 121 template<class It> additive_combine_engine(It& first, It last)
Chris@16 122 : _mlcg1(first, last), _mlcg2(first, last) { }
Chris@16 123
Chris@16 124 /**
Chris@16 125 * Seeds an @c additive_combine_engine using the default
Chris@16 126 * seeds of the two base generators.
Chris@16 127 */
Chris@16 128 void seed()
Chris@16 129 {
Chris@16 130 _mlcg1.seed();
Chris@16 131 _mlcg2.seed();
Chris@16 132 }
Chris@16 133
Chris@16 134 /**
Chris@16 135 * Seeds an @c additive_combine_engine, using @c seed as the
Chris@16 136 * seed for both base generators.
Chris@16 137 */
Chris@16 138 BOOST_RANDOM_DETAIL_ARITHMETIC_SEED(additive_combine_engine,
Chris@16 139 result_type, seed_arg)
Chris@16 140 {
Chris@16 141 _mlcg1.seed(seed_arg);
Chris@16 142 _mlcg2.seed(seed_arg);
Chris@16 143 }
Chris@16 144
Chris@16 145 /**
Chris@16 146 * Seeds an @c additive_combine_engine, using @c seq to
Chris@16 147 * seed both base generators.
Chris@16 148 *
Chris@16 149 * See the warning on the corresponding constructor.
Chris@16 150 */
Chris@16 151 BOOST_RANDOM_DETAIL_SEED_SEQ_SEED(additive_combine_engine,
Chris@16 152 SeedSeq, seq)
Chris@16 153 {
Chris@16 154 _mlcg1.seed(seq);
Chris@16 155 _mlcg2.seed(seq);
Chris@16 156 }
Chris@16 157
Chris@16 158 /**
Chris@16 159 * Seeds an @c additive_combine generator, using @c seed1 and @c seed2 as
Chris@16 160 * the seeds to the first and second base generators, respectively.
Chris@16 161 */
Chris@16 162 void seed(typename MLCG1::result_type seed1,
Chris@16 163 typename MLCG2::result_type seed2)
Chris@16 164 {
Chris@16 165 _mlcg1.seed(seed1);
Chris@16 166 _mlcg2.seed(seed2);
Chris@16 167 }
Chris@16 168
Chris@16 169 /**
Chris@16 170 * Seeds an @c additive_combine_engine with
Chris@16 171 * values from the range defined by the input iterators first
Chris@16 172 * and last. first will be modified to point to the element
Chris@16 173 * after the last one used.
Chris@16 174 *
Chris@16 175 * Throws: @c std::invalid_argument if the input range is too small.
Chris@16 176 *
Chris@16 177 * Exception Safety: Basic
Chris@16 178 */
Chris@16 179 template<class It> void seed(It& first, It last)
Chris@16 180 {
Chris@16 181 _mlcg1.seed(first, last);
Chris@16 182 _mlcg2.seed(first, last);
Chris@16 183 }
Chris@16 184
Chris@16 185 /** Returns the next value of the generator. */
Chris@16 186 result_type operator()() {
Chris@16 187 result_type val1 = _mlcg1();
Chris@16 188 result_type val2 = _mlcg2();
Chris@16 189 if(val2 < val1) return val1 - val2;
Chris@16 190 else return val1 - val2 + MLCG1::modulus - 1;
Chris@16 191 }
Chris@16 192
Chris@16 193 /** Fills a range with random values */
Chris@16 194 template<class Iter>
Chris@16 195 void generate(Iter first, Iter last)
Chris@16 196 { detail::generate_from_int(*this, first, last); }
Chris@16 197
Chris@16 198 /** Advances the state of the generator by @c z. */
Chris@16 199 void discard(boost::uintmax_t z)
Chris@16 200 {
Chris@16 201 _mlcg1.discard(z);
Chris@16 202 _mlcg2.discard(z);
Chris@16 203 }
Chris@16 204
Chris@16 205 /**
Chris@16 206 * Writes the state of an @c additive_combine_engine to a @c
Chris@16 207 * std::ostream. The textual representation of an @c
Chris@16 208 * additive_combine_engine is the textual representation of
Chris@16 209 * the first base generator followed by the textual representation
Chris@16 210 * of the second base generator.
Chris@16 211 */
Chris@16 212 BOOST_RANDOM_DETAIL_OSTREAM_OPERATOR(os, additive_combine_engine, r)
Chris@16 213 { os << r._mlcg1 << ' ' << r._mlcg2; return os; }
Chris@16 214
Chris@16 215 /**
Chris@16 216 * Reads the state of an @c additive_combine_engine from a
Chris@16 217 * @c std::istream.
Chris@16 218 */
Chris@16 219 BOOST_RANDOM_DETAIL_ISTREAM_OPERATOR(is, additive_combine_engine, r)
Chris@16 220 { is >> r._mlcg1 >> std::ws >> r._mlcg2; return is; }
Chris@16 221
Chris@16 222 /**
Chris@16 223 * Returns: true iff the two @c additive_combine_engines will
Chris@16 224 * produce the same sequence of values.
Chris@16 225 */
Chris@16 226 BOOST_RANDOM_DETAIL_EQUALITY_OPERATOR(additive_combine_engine, x, y)
Chris@16 227 { return x._mlcg1 == y._mlcg1 && x._mlcg2 == y._mlcg2; }
Chris@16 228 /**
Chris@16 229 * Returns: true iff the two @c additive_combine_engines will
Chris@16 230 * produce different sequences of values.
Chris@16 231 */
Chris@16 232 BOOST_RANDOM_DETAIL_INEQUALITY_OPERATOR(additive_combine_engine)
Chris@16 233
Chris@16 234 private:
Chris@16 235 MLCG1 _mlcg1;
Chris@16 236 MLCG2 _mlcg2;
Chris@16 237 };
Chris@16 238
Chris@16 239 #ifndef BOOST_NO_INCLASS_MEMBER_INITIALIZATION
Chris@16 240 template<class MLCG1, class MLCG2>
Chris@16 241 const bool additive_combine_engine<MLCG1, MLCG2>::has_fixed_range;
Chris@16 242 #endif
Chris@16 243
Chris@16 244 /// \cond show_deprecated
Chris@16 245
Chris@16 246 /** Provided for backwards compatibility. */
Chris@16 247 template<class MLCG1, class MLCG2, typename MLCG1::result_type val = 0>
Chris@16 248 class additive_combine : public additive_combine_engine<MLCG1, MLCG2>
Chris@16 249 {
Chris@16 250 typedef additive_combine_engine<MLCG1, MLCG2> base_t;
Chris@16 251 public:
Chris@16 252 typedef typename base_t::result_type result_type;
Chris@16 253 additive_combine() {}
Chris@16 254 template<class T>
Chris@16 255 additive_combine(T& arg) : base_t(arg) {}
Chris@16 256 template<class T>
Chris@16 257 additive_combine(const T& arg) : base_t(arg) {}
Chris@16 258 template<class It>
Chris@16 259 additive_combine(It& first, It last) : base_t(first, last) {}
Chris@16 260 };
Chris@16 261
Chris@16 262 /// \endcond
Chris@16 263
Chris@16 264 /**
Chris@16 265 * The specialization \ecuyer1988 was suggested in
Chris@16 266 *
Chris@16 267 * @blockquote
Chris@16 268 * "Efficient and Portable Combined Random Number Generators", Pierre L'Ecuyer,
Chris@16 269 * Communications of the ACM, Vol. 31, No. 6, June 1988, pp. 742-749, 774
Chris@16 270 * @endblockquote
Chris@16 271 */
Chris@16 272 typedef additive_combine_engine<
Chris@16 273 linear_congruential_engine<uint32_t, 40014, 0, 2147483563>,
Chris@16 274 linear_congruential_engine<uint32_t, 40692, 0, 2147483399>
Chris@16 275 > ecuyer1988;
Chris@16 276
Chris@16 277 } // namespace random
Chris@16 278
Chris@16 279 using random::ecuyer1988;
Chris@16 280
Chris@16 281 } // namespace boost
Chris@16 282
Chris@16 283 #endif // BOOST_RANDOM_ADDITIVE_COMBINE_HPP