annotate DEPENDENCIES/generic/include/boost/random/subtract_with_carry.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/subtract_with_carry.hpp header file
Chris@16 2 *
Chris@16 3 * Copyright Jens Maurer 2002
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 * 2002-03-02 created
Chris@16 14 */
Chris@16 15
Chris@16 16 #ifndef BOOST_RANDOM_SUBTRACT_WITH_CARRY_HPP
Chris@16 17 #define BOOST_RANDOM_SUBTRACT_WITH_CARRY_HPP
Chris@16 18
Chris@16 19 #include <boost/config/no_tr1/cmath.hpp> // std::pow
Chris@16 20 #include <iostream>
Chris@16 21 #include <algorithm> // std::equal
Chris@16 22 #include <stdexcept>
Chris@16 23 #include <boost/config.hpp>
Chris@16 24 #include <boost/limits.hpp>
Chris@16 25 #include <boost/cstdint.hpp>
Chris@16 26 #include <boost/static_assert.hpp>
Chris@16 27 #include <boost/integer/static_log2.hpp>
Chris@16 28 #include <boost/integer/integer_mask.hpp>
Chris@16 29 #include <boost/detail/workaround.hpp>
Chris@16 30 #include <boost/random/detail/config.hpp>
Chris@16 31 #include <boost/random/detail/seed.hpp>
Chris@16 32 #include <boost/random/detail/operators.hpp>
Chris@16 33 #include <boost/random/detail/seed_impl.hpp>
Chris@16 34 #include <boost/random/detail/generator_seed_seq.hpp>
Chris@16 35 #include <boost/random/linear_congruential.hpp>
Chris@16 36
Chris@16 37
Chris@16 38 namespace boost {
Chris@16 39 namespace random {
Chris@16 40
Chris@16 41 namespace detail {
Chris@16 42
Chris@16 43 struct subtract_with_carry_discard
Chris@16 44 {
Chris@16 45 template<class Engine>
Chris@16 46 static void apply(Engine& eng, boost::uintmax_t z)
Chris@16 47 {
Chris@16 48 typedef typename Engine::result_type IntType;
Chris@16 49 const std::size_t short_lag = Engine::short_lag;
Chris@16 50 const std::size_t long_lag = Engine::long_lag;
Chris@16 51 std::size_t k = eng.k;
Chris@16 52 IntType carry = eng.carry;
Chris@16 53 if(k != 0) {
Chris@16 54 // increment k until it becomes 0.
Chris@16 55 if(k < short_lag) {
Chris@16 56 std::size_t limit = (short_lag - k) < z?
Chris@16 57 short_lag : (k + static_cast<std::size_t>(z));
Chris@16 58 for(std::size_t j = k; j < limit; ++j) {
Chris@16 59 carry = eng.do_update(j, j + long_lag - short_lag, carry);
Chris@16 60 }
Chris@16 61 }
Chris@16 62 std::size_t limit = (long_lag - k) < z?
Chris@16 63 long_lag : (k + static_cast<std::size_t>(z));
Chris@16 64 std::size_t start = (k < short_lag ? short_lag : k);
Chris@16 65 for(std::size_t j = start; j < limit; ++j) {
Chris@16 66 carry = eng.do_update(j, j - short_lag, carry);
Chris@16 67 }
Chris@16 68 }
Chris@16 69
Chris@16 70 k = ((z % long_lag) + k) % long_lag;
Chris@16 71
Chris@16 72 if(k < z) {
Chris@16 73 // main loop: update full blocks from k = 0 to long_lag
Chris@16 74 for(std::size_t i = 0; i < (z - k) / long_lag; ++i) {
Chris@16 75 for(std::size_t j = 0; j < short_lag; ++j) {
Chris@16 76 carry = eng.do_update(j, j + long_lag - short_lag, carry);
Chris@16 77 }
Chris@16 78 for(std::size_t j = short_lag; j < long_lag; ++j) {
Chris@16 79 carry = eng.do_update(j, j - short_lag, carry);
Chris@16 80 }
Chris@16 81 }
Chris@16 82
Chris@16 83 // Update the last partial block
Chris@16 84 std::size_t limit = short_lag < k? short_lag : k;
Chris@16 85 for(std::size_t j = 0; j < limit; ++j) {
Chris@16 86 carry = eng.do_update(j, j + long_lag - short_lag, carry);
Chris@16 87 }
Chris@16 88 for(std::size_t j = short_lag; j < k; ++j) {
Chris@16 89 carry = eng.do_update(j, j - short_lag, carry);
Chris@16 90 }
Chris@16 91 }
Chris@16 92 eng.carry = carry;
Chris@16 93 eng.k = k;
Chris@16 94 }
Chris@16 95 };
Chris@16 96
Chris@16 97 }
Chris@16 98
Chris@16 99 /**
Chris@16 100 * Instantiations of @c subtract_with_carry_engine model a
Chris@16 101 * \pseudo_random_number_generator. The algorithm is
Chris@16 102 * described in
Chris@16 103 *
Chris@16 104 * @blockquote
Chris@16 105 * "A New Class of Random Number Generators", George
Chris@16 106 * Marsaglia and Arif Zaman, Annals of Applied Probability,
Chris@16 107 * Volume 1, Number 3 (1991), 462-480.
Chris@16 108 * @endblockquote
Chris@16 109 */
Chris@16 110 template<class IntType, std::size_t w, std::size_t s, std::size_t r>
Chris@16 111 class subtract_with_carry_engine
Chris@16 112 {
Chris@16 113 public:
Chris@16 114 typedef IntType result_type;
Chris@16 115 BOOST_STATIC_CONSTANT(std::size_t, word_size = w);
Chris@16 116 BOOST_STATIC_CONSTANT(std::size_t, long_lag = r);
Chris@16 117 BOOST_STATIC_CONSTANT(std::size_t, short_lag = s);
Chris@16 118 BOOST_STATIC_CONSTANT(uint32_t, default_seed = 19780503u);
Chris@16 119
Chris@16 120 // Required by the old Boost.Random concepts
Chris@16 121 BOOST_STATIC_CONSTANT(bool, has_fixed_range = false);
Chris@16 122 // Backwards compatibility
Chris@16 123 BOOST_STATIC_CONSTANT(result_type, modulus = (result_type(1) << w));
Chris@16 124
Chris@16 125 BOOST_STATIC_ASSERT(std::numeric_limits<result_type>::is_integer);
Chris@16 126
Chris@16 127 /**
Chris@16 128 * Constructs a new @c subtract_with_carry_engine and seeds
Chris@16 129 * it with the default seed.
Chris@16 130 */
Chris@16 131 subtract_with_carry_engine() { seed(); }
Chris@16 132 /**
Chris@16 133 * Constructs a new @c subtract_with_carry_engine and seeds
Chris@16 134 * it with @c value.
Chris@16 135 */
Chris@16 136 BOOST_RANDOM_DETAIL_ARITHMETIC_CONSTRUCTOR(subtract_with_carry_engine,
Chris@16 137 IntType, value)
Chris@16 138 { seed(value); }
Chris@16 139 /**
Chris@16 140 * Constructs a new @c subtract_with_carry_engine and seeds
Chris@16 141 * it with values produced by @c seq.generate().
Chris@16 142 */
Chris@16 143 BOOST_RANDOM_DETAIL_SEED_SEQ_CONSTRUCTOR(subtract_with_carry_engine,
Chris@16 144 SeedSeq, seq)
Chris@16 145 { seed(seq); }
Chris@16 146 /**
Chris@16 147 * Constructs a new @c subtract_with_carry_engine and seeds
Chris@16 148 * it with values from a range. first is updated to point
Chris@16 149 * one past the last value consumed. If there are not
Chris@16 150 * enough elements in the range to fill the entire state of
Chris@16 151 * the generator, throws @c std::invalid_argument.
Chris@16 152 */
Chris@16 153 template<class It> subtract_with_carry_engine(It& first, It last)
Chris@16 154 { seed(first,last); }
Chris@16 155
Chris@16 156 // compiler-generated copy ctor and assignment operator are fine
Chris@16 157
Chris@16 158 /** Seeds the generator with the default seed. */
Chris@16 159 void seed() { seed(default_seed); }
Chris@16 160 BOOST_RANDOM_DETAIL_ARITHMETIC_SEED(subtract_with_carry_engine,
Chris@16 161 IntType, value)
Chris@16 162 {
Chris@16 163 typedef linear_congruential_engine<uint32_t,40014,0,2147483563> gen_t;
Chris@16 164 gen_t intgen(static_cast<boost::uint32_t>(value == 0 ? default_seed : value));
Chris@16 165 detail::generator_seed_seq<gen_t> gen(intgen);
Chris@16 166 seed(gen);
Chris@16 167 }
Chris@16 168
Chris@16 169 /** Seeds the generator with values produced by @c seq.generate(). */
Chris@16 170 BOOST_RANDOM_DETAIL_SEED_SEQ_SEED(subtract_with_carry, SeedSeq, seq)
Chris@16 171 {
Chris@16 172 detail::seed_array_int<w>(seq, x);
Chris@16 173 carry = (x[long_lag-1] == 0);
Chris@16 174 k = 0;
Chris@16 175 }
Chris@16 176
Chris@16 177 /**
Chris@16 178 * Seeds the generator with values from a range. Updates @c first to
Chris@16 179 * point one past the last consumed value. If the range does not
Chris@16 180 * contain enough elements to fill the entire state of the generator,
Chris@16 181 * throws @c std::invalid_argument.
Chris@16 182 */
Chris@16 183 template<class It>
Chris@16 184 void seed(It& first, It last)
Chris@16 185 {
Chris@16 186 detail::fill_array_int<w>(first, last, x);
Chris@16 187 carry = (x[long_lag-1] == 0);
Chris@16 188 k = 0;
Chris@16 189 }
Chris@16 190
Chris@16 191 /** Returns the smallest value that the generator can produce. */
Chris@16 192 static result_type min BOOST_PREVENT_MACRO_SUBSTITUTION ()
Chris@16 193 { return 0; }
Chris@16 194 /** Returns the largest value that the generator can produce. */
Chris@16 195 static result_type max BOOST_PREVENT_MACRO_SUBSTITUTION ()
Chris@16 196 { return boost::low_bits_mask_t<w>::sig_bits; }
Chris@16 197
Chris@16 198 /** Returns the next value of the generator. */
Chris@16 199 result_type operator()()
Chris@16 200 {
Chris@16 201 std::size_t short_index =
Chris@16 202 (k < short_lag)?
Chris@16 203 (k + long_lag - short_lag) :
Chris@16 204 (k - short_lag);
Chris@16 205 carry = do_update(k, short_index, carry);
Chris@16 206 IntType result = x[k];
Chris@16 207 ++k;
Chris@16 208 if(k >= long_lag)
Chris@16 209 k = 0;
Chris@16 210 return result;
Chris@16 211 }
Chris@16 212
Chris@16 213 /** Advances the state of the generator by @c z. */
Chris@16 214 void discard(boost::uintmax_t z)
Chris@16 215 {
Chris@16 216 detail::subtract_with_carry_discard::apply(*this, z);
Chris@16 217 }
Chris@16 218
Chris@16 219 /** Fills a range with random values. */
Chris@16 220 template<class It>
Chris@16 221 void generate(It first, It last)
Chris@16 222 { detail::generate_from_int(*this, first, last); }
Chris@16 223
Chris@16 224 /** Writes a @c subtract_with_carry_engine to a @c std::ostream. */
Chris@16 225 BOOST_RANDOM_DETAIL_OSTREAM_OPERATOR(os, subtract_with_carry_engine, f)
Chris@16 226 {
Chris@16 227 for(unsigned int j = 0; j < f.long_lag; ++j)
Chris@16 228 os << f.compute(j) << ' ';
Chris@16 229 os << f.carry;
Chris@16 230 return os;
Chris@16 231 }
Chris@16 232
Chris@16 233 /** Reads a @c subtract_with_carry_engine from a @c std::istream. */
Chris@16 234 BOOST_RANDOM_DETAIL_ISTREAM_OPERATOR(is, subtract_with_carry_engine, f)
Chris@16 235 {
Chris@16 236 for(unsigned int j = 0; j < f.long_lag; ++j)
Chris@16 237 is >> f.x[j] >> std::ws;
Chris@16 238 is >> f.carry;
Chris@16 239 f.k = 0;
Chris@16 240 return is;
Chris@16 241 }
Chris@16 242
Chris@16 243 /**
Chris@16 244 * Returns true if the two generators will produce identical
Chris@16 245 * sequences of values.
Chris@16 246 */
Chris@16 247 BOOST_RANDOM_DETAIL_EQUALITY_OPERATOR(subtract_with_carry_engine, x, y)
Chris@16 248 {
Chris@16 249 for(unsigned int j = 0; j < r; ++j)
Chris@16 250 if(x.compute(j) != y.compute(j))
Chris@16 251 return false;
Chris@16 252 return true;
Chris@16 253 }
Chris@16 254
Chris@16 255 /**
Chris@16 256 * Returns true if the two generators will produce different
Chris@16 257 * sequences of values.
Chris@16 258 */
Chris@16 259 BOOST_RANDOM_DETAIL_INEQUALITY_OPERATOR(subtract_with_carry_engine)
Chris@16 260
Chris@16 261 private:
Chris@16 262 /// \cond show_private
Chris@16 263 // returns x(i-r+index), where index is in 0..r-1
Chris@16 264 IntType compute(unsigned int index) const
Chris@16 265 {
Chris@16 266 return x[(k+index) % long_lag];
Chris@16 267 }
Chris@16 268
Chris@16 269 friend struct detail::subtract_with_carry_discard;
Chris@16 270
Chris@16 271 IntType do_update(std::size_t current, std::size_t short_index, IntType carry)
Chris@16 272 {
Chris@16 273 IntType delta;
Chris@16 274 IntType temp = x[current] + carry;
Chris@16 275 if (x[short_index] >= temp) {
Chris@16 276 // x(n) >= 0
Chris@16 277 delta = x[short_index] - temp;
Chris@16 278 carry = 0;
Chris@16 279 } else {
Chris@16 280 // x(n) < 0
Chris@16 281 delta = modulus - temp + x[short_index];
Chris@16 282 carry = 1;
Chris@16 283 }
Chris@16 284 x[current] = delta;
Chris@16 285 return carry;
Chris@16 286 }
Chris@16 287 /// \endcond
Chris@16 288
Chris@16 289 // state representation; next output (state) is x(i)
Chris@16 290 // x[0] ... x[k] x[k+1] ... x[long_lag-1] represents
Chris@16 291 // x(i-k) ... x(i) x(i+1) ... x(i-k+long_lag-1)
Chris@16 292 // speed: base: 20-25 nsec
Chris@16 293 // ranlux_4: 230 nsec, ranlux_7: 430 nsec, ranlux_14: 810 nsec
Chris@16 294 // This state representation makes operator== and save/restore more
Chris@16 295 // difficult, because we've already computed "too much" and thus
Chris@16 296 // have to undo some steps to get at x(i-r) etc.
Chris@16 297
Chris@16 298 // state representation: next output (state) is x(i)
Chris@16 299 // x[0] ... x[k] x[k+1] ... x[long_lag-1] represents
Chris@16 300 // x(i-k) ... x(i) x(i-long_lag+1) ... x(i-k-1)
Chris@16 301 // speed: base 28 nsec
Chris@16 302 // ranlux_4: 370 nsec, ranlux_7: 688 nsec, ranlux_14: 1343 nsec
Chris@16 303 IntType x[long_lag];
Chris@16 304 std::size_t k;
Chris@16 305 IntType carry;
Chris@16 306 };
Chris@16 307
Chris@16 308 #ifndef BOOST_NO_INCLASS_MEMBER_INITIALIZATION
Chris@16 309 // A definition is required even for integral static constants
Chris@16 310 template<class IntType, std::size_t w, std::size_t s, std::size_t r>
Chris@16 311 const bool subtract_with_carry_engine<IntType, w, s, r>::has_fixed_range;
Chris@16 312 template<class IntType, std::size_t w, std::size_t s, std::size_t r>
Chris@16 313 const IntType subtract_with_carry_engine<IntType, w, s, r>::modulus;
Chris@16 314 template<class IntType, std::size_t w, std::size_t s, std::size_t r>
Chris@16 315 const std::size_t subtract_with_carry_engine<IntType, w, s, r>::word_size;
Chris@16 316 template<class IntType, std::size_t w, std::size_t s, std::size_t r>
Chris@16 317 const std::size_t subtract_with_carry_engine<IntType, w, s, r>::long_lag;
Chris@16 318 template<class IntType, std::size_t w, std::size_t s, std::size_t r>
Chris@16 319 const std::size_t subtract_with_carry_engine<IntType, w, s, r>::short_lag;
Chris@16 320 template<class IntType, std::size_t w, std::size_t s, std::size_t r>
Chris@16 321 const uint32_t subtract_with_carry_engine<IntType, w, s, r>::default_seed;
Chris@16 322 #endif
Chris@16 323
Chris@16 324
Chris@16 325 // use a floating-point representation to produce values in [0..1)
Chris@16 326 /**
Chris@16 327 * Instantiations of \subtract_with_carry_01_engine model a
Chris@16 328 * \pseudo_random_number_generator. The algorithm is
Chris@16 329 * described in
Chris@16 330 *
Chris@16 331 * @blockquote
Chris@16 332 * "A New Class of Random Number Generators", George
Chris@16 333 * Marsaglia and Arif Zaman, Annals of Applied Probability,
Chris@16 334 * Volume 1, Number 3 (1991), 462-480.
Chris@16 335 * @endblockquote
Chris@16 336 */
Chris@16 337 template<class RealType, std::size_t w, std::size_t s, std::size_t r>
Chris@16 338 class subtract_with_carry_01_engine
Chris@16 339 {
Chris@16 340 public:
Chris@16 341 typedef RealType result_type;
Chris@16 342 BOOST_STATIC_CONSTANT(bool, has_fixed_range = false);
Chris@16 343 BOOST_STATIC_CONSTANT(std::size_t, word_size = w);
Chris@16 344 BOOST_STATIC_CONSTANT(std::size_t, long_lag = r);
Chris@16 345 BOOST_STATIC_CONSTANT(std::size_t, short_lag = s);
Chris@16 346 BOOST_STATIC_CONSTANT(boost::uint32_t, default_seed = 19780503u);
Chris@16 347
Chris@16 348 BOOST_STATIC_ASSERT(!std::numeric_limits<result_type>::is_integer);
Chris@16 349
Chris@16 350 /** Creates a new \subtract_with_carry_01_engine using the default seed. */
Chris@16 351 subtract_with_carry_01_engine() { init_modulus(); seed(); }
Chris@16 352 /** Creates a new subtract_with_carry_01_engine and seeds it with value. */
Chris@16 353 BOOST_RANDOM_DETAIL_ARITHMETIC_CONSTRUCTOR(subtract_with_carry_01_engine,
Chris@16 354 boost::uint32_t, value)
Chris@16 355 { init_modulus(); seed(value); }
Chris@16 356 /**
Chris@16 357 * Creates a new \subtract_with_carry_01_engine and seeds with values
Chris@16 358 * produced by seq.generate().
Chris@16 359 */
Chris@16 360 BOOST_RANDOM_DETAIL_SEED_SEQ_CONSTRUCTOR(subtract_with_carry_01_engine,
Chris@16 361 SeedSeq, seq)
Chris@16 362 { init_modulus(); seed(seq); }
Chris@16 363 /**
Chris@16 364 * Creates a new \subtract_with_carry_01_engine and seeds it with values
Chris@16 365 * from a range. Advances first to point one past the last consumed
Chris@16 366 * value. If the range does not contain enough elements to fill the
Chris@16 367 * entire state, throws @c std::invalid_argument.
Chris@16 368 */
Chris@16 369 template<class It> subtract_with_carry_01_engine(It& first, It last)
Chris@16 370 { init_modulus(); seed(first,last); }
Chris@16 371
Chris@16 372 private:
Chris@16 373 /// \cond show_private
Chris@16 374 void init_modulus()
Chris@16 375 {
Chris@16 376 #ifndef BOOST_NO_STDC_NAMESPACE
Chris@16 377 // allow for Koenig lookup
Chris@16 378 using std::pow;
Chris@16 379 #endif
Chris@16 380 _modulus = pow(RealType(2), RealType(word_size));
Chris@16 381 }
Chris@16 382 /// \endcond
Chris@16 383
Chris@16 384 public:
Chris@16 385 // compiler-generated copy ctor and assignment operator are fine
Chris@16 386
Chris@16 387 /** Seeds the generator with the default seed. */
Chris@16 388 void seed() { seed(default_seed); }
Chris@16 389
Chris@16 390 /** Seeds the generator with @c value. */
Chris@16 391 BOOST_RANDOM_DETAIL_ARITHMETIC_SEED(subtract_with_carry_01_engine,
Chris@16 392 boost::uint32_t, value)
Chris@16 393 {
Chris@16 394 typedef linear_congruential_engine<uint32_t, 40014, 0, 2147483563> gen_t;
Chris@16 395 gen_t intgen(value == 0 ? default_seed : value);
Chris@16 396 detail::generator_seed_seq<gen_t> gen(intgen);
Chris@16 397 seed(gen);
Chris@16 398 }
Chris@16 399
Chris@16 400 /** Seeds the generator with values produced by @c seq.generate(). */
Chris@16 401 BOOST_RANDOM_DETAIL_SEED_SEQ_SEED(subtract_with_carry_01_engine,
Chris@16 402 SeedSeq, seq)
Chris@16 403 {
Chris@16 404 detail::seed_array_real<w>(seq, x);
Chris@16 405 carry = (x[long_lag-1] ? 0 : 1 / _modulus);
Chris@16 406 k = 0;
Chris@16 407 }
Chris@16 408
Chris@16 409 /**
Chris@16 410 * Seeds the generator with values from a range. Updates first to
Chris@16 411 * point one past the last consumed element. If there are not
Chris@16 412 * enough elements in the range to fill the entire state, throws
Chris@16 413 * @c std::invalid_argument.
Chris@16 414 */
Chris@16 415 template<class It>
Chris@16 416 void seed(It& first, It last)
Chris@16 417 {
Chris@16 418 detail::fill_array_real<w>(first, last, x);
Chris@16 419 carry = (x[long_lag-1] ? 0 : 1 / _modulus);
Chris@16 420 k = 0;
Chris@16 421 }
Chris@16 422
Chris@16 423 /** Returns the smallest value that the generator can produce. */
Chris@16 424 static result_type min BOOST_PREVENT_MACRO_SUBSTITUTION ()
Chris@16 425 { return result_type(0); }
Chris@16 426 /** Returns the largest value that the generator can produce. */
Chris@16 427 static result_type max BOOST_PREVENT_MACRO_SUBSTITUTION ()
Chris@16 428 { return result_type(1); }
Chris@16 429
Chris@16 430 /** Returns the next value of the generator. */
Chris@16 431 result_type operator()()
Chris@16 432 {
Chris@16 433 std::size_t short_index =
Chris@16 434 (k < short_lag) ?
Chris@16 435 (k + long_lag - short_lag) :
Chris@16 436 (k - short_lag);
Chris@16 437 carry = do_update(k, short_index, carry);
Chris@16 438 RealType result = x[k];
Chris@16 439 ++k;
Chris@16 440 if(k >= long_lag)
Chris@16 441 k = 0;
Chris@16 442 return result;
Chris@16 443 }
Chris@16 444
Chris@16 445 /** Advances the state of the generator by @c z. */
Chris@16 446 void discard(boost::uintmax_t z)
Chris@16 447 { detail::subtract_with_carry_discard::apply(*this, z); }
Chris@16 448
Chris@16 449 /** Fills a range with random values. */
Chris@16 450 template<class Iter>
Chris@16 451 void generate(Iter first, Iter last)
Chris@16 452 { detail::generate_from_real(*this, first, last); }
Chris@16 453
Chris@16 454 /** Writes a \subtract_with_carry_01_engine to a @c std::ostream. */
Chris@16 455 BOOST_RANDOM_DETAIL_OSTREAM_OPERATOR(os, subtract_with_carry_01_engine, f)
Chris@16 456 {
Chris@16 457 std::ios_base::fmtflags oldflags =
Chris@16 458 os.flags(os.dec | os.fixed | os.left);
Chris@16 459 for(unsigned int j = 0; j < f.long_lag; ++j)
Chris@16 460 os << (f.compute(j) * f._modulus) << ' ';
Chris@16 461 os << (f.carry * f._modulus);
Chris@16 462 os.flags(oldflags);
Chris@16 463 return os;
Chris@16 464 }
Chris@16 465
Chris@16 466 /** Reads a \subtract_with_carry_01_engine from a @c std::istream. */
Chris@16 467 BOOST_RANDOM_DETAIL_ISTREAM_OPERATOR(is, subtract_with_carry_01_engine, f)
Chris@16 468 {
Chris@16 469 RealType value;
Chris@16 470 for(unsigned int j = 0; j < long_lag; ++j) {
Chris@16 471 is >> value >> std::ws;
Chris@16 472 f.x[j] = value / f._modulus;
Chris@16 473 }
Chris@16 474 is >> value;
Chris@16 475 f.carry = value / f._modulus;
Chris@16 476 f.k = 0;
Chris@16 477 return is;
Chris@16 478 }
Chris@16 479
Chris@16 480 /** Returns true if the two generators will produce identical sequences. */
Chris@16 481 BOOST_RANDOM_DETAIL_EQUALITY_OPERATOR(subtract_with_carry_01_engine, x, y)
Chris@16 482 {
Chris@16 483 for(unsigned int j = 0; j < r; ++j)
Chris@16 484 if(x.compute(j) != y.compute(j))
Chris@16 485 return false;
Chris@16 486 return true;
Chris@16 487 }
Chris@16 488
Chris@16 489 /** Returns true if the two generators will produce different sequences. */
Chris@16 490 BOOST_RANDOM_DETAIL_INEQUALITY_OPERATOR(subtract_with_carry_01_engine)
Chris@16 491
Chris@16 492 private:
Chris@16 493 /// \cond show_private
Chris@16 494 RealType compute(unsigned int index) const
Chris@16 495 {
Chris@16 496 return x[(k+index) % long_lag];
Chris@16 497 }
Chris@16 498
Chris@16 499 friend struct detail::subtract_with_carry_discard;
Chris@16 500
Chris@16 501 RealType do_update(std::size_t current, std::size_t short_index, RealType carry)
Chris@16 502 {
Chris@16 503 RealType delta = x[short_index] - x[current] - carry;
Chris@16 504 if(delta < 0) {
Chris@16 505 delta += RealType(1);
Chris@16 506 carry = RealType(1)/_modulus;
Chris@16 507 } else {
Chris@16 508 carry = 0;
Chris@16 509 }
Chris@16 510 x[current] = delta;
Chris@16 511 return carry;
Chris@16 512 }
Chris@16 513 /// \endcond
Chris@16 514 std::size_t k;
Chris@16 515 RealType carry;
Chris@16 516 RealType x[long_lag];
Chris@16 517 RealType _modulus;
Chris@16 518 };
Chris@16 519
Chris@16 520 #ifndef BOOST_NO_INCLASS_MEMBER_INITIALIZATION
Chris@16 521 // A definition is required even for integral static constants
Chris@16 522 template<class RealType, std::size_t w, std::size_t s, std::size_t r>
Chris@16 523 const bool subtract_with_carry_01_engine<RealType, w, s, r>::has_fixed_range;
Chris@16 524 template<class RealType, std::size_t w, std::size_t s, std::size_t r>
Chris@16 525 const std::size_t subtract_with_carry_01_engine<RealType, w, s, r>::word_size;
Chris@16 526 template<class RealType, std::size_t w, std::size_t s, std::size_t r>
Chris@16 527 const std::size_t subtract_with_carry_01_engine<RealType, w, s, r>::long_lag;
Chris@16 528 template<class RealType, std::size_t w, std::size_t s, std::size_t r>
Chris@16 529 const std::size_t subtract_with_carry_01_engine<RealType, w, s, r>::short_lag;
Chris@16 530 template<class RealType, std::size_t w, std::size_t s, std::size_t r>
Chris@16 531 const uint32_t subtract_with_carry_01_engine<RealType, w, s, r>::default_seed;
Chris@16 532 #endif
Chris@16 533
Chris@16 534
Chris@16 535 /// \cond show_deprecated
Chris@16 536
Chris@16 537 template<class IntType, IntType m, unsigned s, unsigned r, IntType v>
Chris@16 538 class subtract_with_carry :
Chris@16 539 public subtract_with_carry_engine<IntType,
Chris@16 540 boost::static_log2<m>::value, s, r>
Chris@16 541 {
Chris@16 542 typedef subtract_with_carry_engine<IntType,
Chris@16 543 boost::static_log2<m>::value, s, r> base_type;
Chris@16 544 public:
Chris@16 545 subtract_with_carry() {}
Chris@16 546 BOOST_RANDOM_DETAIL_GENERATOR_CONSTRUCTOR(subtract_with_carry, Gen, gen)
Chris@16 547 { seed(gen); }
Chris@16 548 BOOST_RANDOM_DETAIL_ARITHMETIC_CONSTRUCTOR(subtract_with_carry,
Chris@16 549 IntType, val)
Chris@16 550 { seed(val); }
Chris@16 551 template<class It>
Chris@16 552 subtract_with_carry(It& first, It last) : base_type(first, last) {}
Chris@16 553 void seed() { base_type::seed(); }
Chris@16 554 BOOST_RANDOM_DETAIL_GENERATOR_SEED(subtract_with_carry, Gen, gen)
Chris@16 555 {
Chris@16 556 detail::generator_seed_seq<Gen> seq(gen);
Chris@16 557 base_type::seed(seq);
Chris@16 558 }
Chris@16 559 BOOST_RANDOM_DETAIL_ARITHMETIC_SEED(subtract_with_carry, IntType, val)
Chris@16 560 { base_type::seed(val); }
Chris@16 561 template<class It>
Chris@16 562 void seed(It& first, It last) { base_type::seed(first, last); }
Chris@16 563 };
Chris@16 564
Chris@16 565 template<class RealType, int w, unsigned s, unsigned r, int v = 0>
Chris@16 566 class subtract_with_carry_01 :
Chris@16 567 public subtract_with_carry_01_engine<RealType, w, s, r>
Chris@16 568 {
Chris@16 569 typedef subtract_with_carry_01_engine<RealType, w, s, r> base_type;
Chris@16 570 public:
Chris@16 571 subtract_with_carry_01() {}
Chris@16 572 BOOST_RANDOM_DETAIL_GENERATOR_CONSTRUCTOR(subtract_with_carry_01, Gen, gen)
Chris@16 573 { seed(gen); }
Chris@16 574 BOOST_RANDOM_DETAIL_ARITHMETIC_CONSTRUCTOR(subtract_with_carry_01,
Chris@16 575 uint32_t, val)
Chris@16 576 { seed(val); }
Chris@16 577 template<class It>
Chris@16 578 subtract_with_carry_01(It& first, It last) : base_type(first, last) {}
Chris@16 579 void seed() { base_type::seed(); }
Chris@16 580 BOOST_RANDOM_DETAIL_GENERATOR_SEED(subtract_with_carry_01, Gen, gen)
Chris@16 581 {
Chris@16 582 detail::generator_seed_seq<Gen> seq(gen);
Chris@16 583 base_type::seed(seq);
Chris@16 584 }
Chris@16 585 BOOST_RANDOM_DETAIL_ARITHMETIC_SEED(subtract_with_carry_01, uint32_t, val)
Chris@16 586 { base_type::seed(val); }
Chris@16 587 template<class It>
Chris@16 588 void seed(It& first, It last) { base_type::seed(first, last); }
Chris@16 589 };
Chris@16 590
Chris@16 591 /// \endcond
Chris@16 592
Chris@16 593 namespace detail {
Chris@16 594
Chris@16 595 template<class Engine>
Chris@16 596 struct generator_bits;
Chris@16 597
Chris@16 598 template<class RealType, std::size_t w, std::size_t s, std::size_t r>
Chris@16 599 struct generator_bits<subtract_with_carry_01_engine<RealType, w, s, r> > {
Chris@16 600 static std::size_t value() { return w; }
Chris@16 601 };
Chris@16 602
Chris@16 603 template<class RealType, int w, unsigned s, unsigned r, int v>
Chris@16 604 struct generator_bits<subtract_with_carry_01<RealType, w, s, r, v> > {
Chris@16 605 static std::size_t value() { return w; }
Chris@16 606 };
Chris@16 607
Chris@16 608 }
Chris@16 609
Chris@16 610 } // namespace random
Chris@16 611 } // namespace boost
Chris@16 612
Chris@16 613 #endif // BOOST_RANDOM_SUBTRACT_WITH_CARRY_HPP