From e2be750780e14e4cdd50b7984b9fcf2371e503a4 Mon Sep 17 00:00:00 2001 From: "Xawotihs@gmail.com" Date: Sun, 6 Jan 2013 19:44:18 +0000 Subject: [PATCH] Adding boost random support and system libs --- Boost/boost/random.hpp | 84 +++ Boost/boost/random/additive_combine.hpp | 234 +++++++ Boost/boost/random/bernoulli_distribution.hpp | 109 ++++ Boost/boost/random/binomial_distribution.hpp | 111 ++++ Boost/boost/random/cauchy_distribution.hpp | 121 ++++ Boost/boost/random/detail/auto_link.hpp | 42 ++ Boost/boost/random/detail/config.hpp | 18 + Boost/boost/random/detail/const_mod.hpp | 363 +++++++++++ .../boost/random/detail/disable_warnings.hpp | 23 + Boost/boost/random/detail/enable_warnings.hpp | 18 + Boost/boost/random/detail/iterator_mixin.hpp | 45 ++ .../random/detail/pass_through_engine.hpp | 100 +++ Boost/boost/random/detail/ptr_helper.hpp | 94 +++ Boost/boost/random/detail/seed.hpp | 89 +++ .../random/detail/signed_unsigned_tools.hpp | 89 +++ .../boost/random/detail/uniform_int_float.hpp | 85 +++ Boost/boost/random/discard_block.hpp | 132 ++++ .../boost/random/exponential_distribution.hpp | 86 +++ Boost/boost/random/gamma_distribution.hpp | 143 +++++ Boost/boost/random/geometric_distribution.hpp | 118 ++++ Boost/boost/random/inversive_congruential.hpp | 173 +++++ Boost/boost/random/lagged_fibonacci.hpp | 605 ++++++++++++++++++ Boost/boost/random/linear_congruential.hpp | 403 ++++++++++++ Boost/boost/random/linear_feedback_shift.hpp | 160 +++++ Boost/boost/random/lognormal_distribution.hpp | 129 ++++ Boost/boost/random/mersenne_twister.hpp | 367 +++++++++++ Boost/boost/random/normal_distribution.hpp | 131 ++++ Boost/boost/random/poisson_distribution.hpp | 116 ++++ .../boost/random/random_number_generator.hpp | 71 ++ Boost/boost/random/ranlux.hpp | 81 +++ Boost/boost/random/shuffle_output.hpp | 234 +++++++ Boost/boost/random/subtract_with_carry.hpp | 465 ++++++++++++++ Boost/boost/random/triangle_distribution.hpp | 118 ++++ Boost/boost/random/uniform_01.hpp | 273 ++++++++ Boost/boost/random/uniform_int.hpp | 300 +++++++++ Boost/boost/random/uniform_on_sphere.hpp | 101 +++ Boost/boost/random/uniform_real.hpp | 108 ++++ Boost/boost/random/uniform_smallint.hpp | 158 +++++ Boost/boost/random/variate_generator.hpp | 220 +++++++ Boost/boost/random/xor_combine.hpp | 184 ++++++ Boost/lib/libboost_system-vc100-mt-1_44.lib | Bin 0 -> 83066 bytes .../lib/libboost_system-vc100-mt-gd-1_44.lib | Bin 0 -> 415016 bytes 42 files changed, 6501 insertions(+) create mode 100644 Boost/boost/random.hpp create mode 100644 Boost/boost/random/additive_combine.hpp create mode 100644 Boost/boost/random/bernoulli_distribution.hpp create mode 100644 Boost/boost/random/binomial_distribution.hpp create mode 100644 Boost/boost/random/cauchy_distribution.hpp create mode 100644 Boost/boost/random/detail/auto_link.hpp create mode 100644 Boost/boost/random/detail/config.hpp create mode 100644 Boost/boost/random/detail/const_mod.hpp create mode 100644 Boost/boost/random/detail/disable_warnings.hpp create mode 100644 Boost/boost/random/detail/enable_warnings.hpp create mode 100644 Boost/boost/random/detail/iterator_mixin.hpp create mode 100644 Boost/boost/random/detail/pass_through_engine.hpp create mode 100644 Boost/boost/random/detail/ptr_helper.hpp create mode 100644 Boost/boost/random/detail/seed.hpp create mode 100644 Boost/boost/random/detail/signed_unsigned_tools.hpp create mode 100644 Boost/boost/random/detail/uniform_int_float.hpp create mode 100644 Boost/boost/random/discard_block.hpp create mode 100644 Boost/boost/random/exponential_distribution.hpp create mode 100644 Boost/boost/random/gamma_distribution.hpp create mode 100644 Boost/boost/random/geometric_distribution.hpp create mode 100644 Boost/boost/random/inversive_congruential.hpp create mode 100644 Boost/boost/random/lagged_fibonacci.hpp create mode 100644 Boost/boost/random/linear_congruential.hpp create mode 100644 Boost/boost/random/linear_feedback_shift.hpp create mode 100644 Boost/boost/random/lognormal_distribution.hpp create mode 100644 Boost/boost/random/mersenne_twister.hpp create mode 100644 Boost/boost/random/normal_distribution.hpp create mode 100644 Boost/boost/random/poisson_distribution.hpp create mode 100644 Boost/boost/random/random_number_generator.hpp create mode 100644 Boost/boost/random/ranlux.hpp create mode 100644 Boost/boost/random/shuffle_output.hpp create mode 100644 Boost/boost/random/subtract_with_carry.hpp create mode 100644 Boost/boost/random/triangle_distribution.hpp create mode 100644 Boost/boost/random/uniform_01.hpp create mode 100644 Boost/boost/random/uniform_int.hpp create mode 100644 Boost/boost/random/uniform_on_sphere.hpp create mode 100644 Boost/boost/random/uniform_real.hpp create mode 100644 Boost/boost/random/uniform_smallint.hpp create mode 100644 Boost/boost/random/variate_generator.hpp create mode 100644 Boost/boost/random/xor_combine.hpp create mode 100644 Boost/lib/libboost_system-vc100-mt-1_44.lib create mode 100644 Boost/lib/libboost_system-vc100-mt-gd-1_44.lib diff --git a/Boost/boost/random.hpp b/Boost/boost/random.hpp new file mode 100644 index 000000000..4939e7d9b --- /dev/null +++ b/Boost/boost/random.hpp @@ -0,0 +1,84 @@ +/* boost random.hpp header file + * + * Copyright Jens Maurer 2000-2001 + * 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/libs/random for documentation. + * + * $Id: random.hpp 60755 2010-03-22 00:45:06Z steven_watanabe $ + * + * Revision history + * 2000-02-18 portability fixes (thanks to Beman Dawes) + * 2000-02-21 shuffle_output, inversive_congruential_schrage, + * generator_iterator, uniform_smallint + * 2000-02-23 generic modulus arithmetic helper, removed *_schrage classes, + * implemented Streamable and EqualityComparable concepts for + * generators, added Bernoulli distribution and Box-Muller + * transform + * 2000-03-01 cauchy, lognormal, triangle distributions; fixed + * uniform_smallint; renamed gaussian to normal distribution + * 2000-03-05 implemented iterator syntax for distribution functions + * 2000-04-21 removed some optimizations for better BCC/MSVC compatibility + * 2000-05-10 adapted to BCC and MSVC + * 2000-06-13 incorporated review results + * 2000-07-06 moved basic templates from namespace detail to random + * 2000-09-23 warning removals and int64 fixes (Ed Brey) + * 2000-09-24 added lagged_fibonacci generator (Matthias Troyer) + * 2001-02-18 moved to individual header files + */ + +#ifndef BOOST_RANDOM_HPP +#define BOOST_RANDOM_HPP + +// generators +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost { + /** + * The specialization taus88 was suggested in + * + * @blockquote + * "Maximally Equidistributed Combined Tausworthe Generators", + * Pierre L'Ecuyer, Mathematics of Computation, Volume 65, + * Number 213, January 1996, Pages 203-213 + * @endblockquote + */ + typedef random::xor_combine, 0, + random::linear_feedback_shift, 0, 0>, 0, + random::linear_feedback_shift, 0, 0> taus88; +} // namespace boost + +// misc +#include + +// distributions +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#endif // BOOST_RANDOM_HPP diff --git a/Boost/boost/random/additive_combine.hpp b/Boost/boost/random/additive_combine.hpp new file mode 100644 index 000000000..3e8b0c312 --- /dev/null +++ b/Boost/boost/random/additive_combine.hpp @@ -0,0 +1,234 @@ +/* boost random/additive_combine.hpp header file + * + * Copyright Jens Maurer 2000-2001 + * 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: additive_combine.hpp 60755 2010-03-22 00:45:06Z steven_watanabe $ + * + * Revision history + * 2001-02-18 moved to individual header files + */ + +#ifndef BOOST_RANDOM_ADDITIVE_COMBINE_HPP +#define BOOST_RANDOM_ADDITIVE_COMBINE_HPP + +#include +#include // for std::min and std::max +#include +#include +#include +#include + +namespace boost { +namespace random { + +/** + * An instantiation of class template \additive_combine model a + * \pseudo_random_number_generator. It combines two multiplicative + * \linear_congruential number generators, i.e. those with @c c = 0. + * It is described in + * + * @blockquote + * "Efficient and Portable Combined Random Number Generators", Pierre L'Ecuyer, + * Communications of the ACM, Vol. 31, No. 6, June 1988, pp. 742-749, 774 + * @endblockquote + * + * The template parameters MLCG1 and MLCG2 shall denote two different + * \linear_congruential number generators, each with c = 0. Each invocation + * returns a random number X(n) := (MLCG1(n) - MLCG2(n)) mod (m1 - 1), where + * m1 denotes the modulus of MLCG1. + * + * The template parameter @c val is the validation value checked by validation. + */ +template +class additive_combine +{ +public: + typedef MLCG1 first_base; + typedef MLCG2 second_base; + typedef typename MLCG1::result_type result_type; +#ifndef BOOST_NO_INCLASS_MEMBER_INITIALIZATION + static const bool has_fixed_range = true; + static const result_type min_value = 1; + static const result_type max_value = MLCG1::max_value-1; +#else + enum { has_fixed_range = false }; +#endif + /** + * Returns: The smallest value that the generator can produce + */ + result_type min BOOST_PREVENT_MACRO_SUBSTITUTION () const { return 1; } + /** + * Returns: The largest value that the generator can produce + */ + result_type max BOOST_PREVENT_MACRO_SUBSTITUTION () const { return (_mlcg1.max)()-1; } + + /** + * Constructs an \additive_combine generator using the + * default constructors of the two base generators. + */ + additive_combine() : _mlcg1(), _mlcg2() { } + /** + * Constructs an \additive_combine generator, using aseed as + * the constructor argument for both base generators. + */ + explicit additive_combine(result_type aseed) + : _mlcg1(aseed), _mlcg2(aseed) { } + /** + * Constructs an \additive_combine generator, using + * @c seed1 and @c seed2 as the constructor argument to + * the first and second base generators, respectively. + */ + additive_combine(typename MLCG1::result_type seed1, + typename MLCG2::result_type seed2) + : _mlcg1(seed1), _mlcg2(seed2) { } + /** + * Contructs an \additive_combine generator with + * values from the range defined by the input iterators first + * and last. first will be modified to point to the element + * after the last one used. + * + * Throws: @c std::invalid_argument if the input range is too small. + * + * Exception Safety: Basic + */ + template additive_combine(It& first, It last) + : _mlcg1(first, last), _mlcg2(first, last) { } + + /** + * Seeds an \additive_combine generator using the default + * seeds of the two base generators. + */ + void seed() + { + _mlcg1.seed(); + _mlcg2.seed(); + } + + /** + * Seeds an \additive_combine generator, using @c aseed as the + * seed for both base generators. + */ + void seed(result_type aseed) + { + _mlcg1.seed(aseed); + _mlcg2.seed(aseed); + } + + /** + * Seeds an \additive_combine generator, using @c seed1 and @c seed2 as + * the seeds to the first and second base generators, respectively. + */ + void seed(typename MLCG1::result_type seed1, + typename MLCG2::result_type seed2) + { + _mlcg1.seed(seed1); + _mlcg2.seed(seed2); + } + + /** + * Seeds an \additive_combine generator with + * values from the range defined by the input iterators first + * and last. first will be modified to point to the element + * after the last one used. + * + * Throws: @c std::invalid_argument if the input range is too small. + * + * Exception Safety: Basic + */ + template void seed(It& first, It last) + { + _mlcg1.seed(first, last); + _mlcg2.seed(first, last); + } + + /** + * Returns: the next value of the generator + */ + result_type operator()() { + result_type z = _mlcg1() - _mlcg2(); + if(z < 1) + z += MLCG1::modulus-1; + return z; + } + + static bool validation(result_type x) { return val == x; } + +#ifndef BOOST_NO_OPERATORS_IN_NAMESPACE + +#ifndef BOOST_RANDOM_NO_STREAM_OPERATORS + /** + * Writes the state of an \additive_combine generator to a @c + * std::ostream. The textual representation of an \additive_combine + * generator is the textual representation of the first base + * generator followed by the textual representation of the + * second base generator. + */ + template + friend std::basic_ostream& + operator<<(std::basic_ostream& os, const additive_combine& r) + { os << r._mlcg1 << " " << r._mlcg2; return os; } + + /** + * Reads the state of an \additive_combine generator from a + * @c std::istream. + */ + template + friend std::basic_istream& + operator>>(std::basic_istream& is, additive_combine& r) + { is >> r._mlcg1 >> std::ws >> r._mlcg2; return is; } +#endif + + /** + * Returns: true iff the two \additive_combine generators will + * produce the same sequence of values. + */ + friend bool operator==(const additive_combine& x, const additive_combine& y) + { return x._mlcg1 == y._mlcg1 && x._mlcg2 == y._mlcg2; } + /** + * Returns: true iff the two \additive_combine generators will + * produce different sequences of values. + */ + friend bool operator!=(const additive_combine& x, const additive_combine& y) + { return !(x == y); } +#else + // Use a member function; Streamable concept not supported. + bool operator==(const additive_combine& rhs) const + { return _mlcg1 == rhs._mlcg1 && _mlcg2 == rhs._mlcg2; } + bool operator!=(const additive_combine& rhs) const + { return !(*this == rhs); } +#endif + +private: + MLCG1 _mlcg1; + MLCG2 _mlcg2; +}; + +} // namespace random + +/** + * The specialization \ecuyer1988 was suggested in + * + * @blockquote + * "Efficient and Portable Combined Random Number Generators", Pierre L'Ecuyer, + * Communications of the ACM, Vol. 31, No. 6, June 1988, pp. 742-749, 774 + * @endblockquote + */ +typedef random::additive_combine< + random::linear_congruential, + random::linear_congruential, + 2060321752> ecuyer1988; + +} // namespace boost + +#endif // BOOST_RANDOM_ADDITIVE_COMBINE_HPP diff --git a/Boost/boost/random/bernoulli_distribution.hpp b/Boost/boost/random/bernoulli_distribution.hpp new file mode 100644 index 000000000..8b4276314 --- /dev/null +++ b/Boost/boost/random/bernoulli_distribution.hpp @@ -0,0 +1,109 @@ +/* boost random/bernoulli_distribution.hpp header file + * + * Copyright Jens Maurer 2000-2001 + * 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: bernoulli_distribution.hpp 60755 2010-03-22 00:45:06Z steven_watanabe $ + * + * Revision history + * 2001-02-18 moved to individual header files + */ + +#ifndef BOOST_RANDOM_BERNOULLI_DISTRIBUTION_HPP +#define BOOST_RANDOM_BERNOULLI_DISTRIBUTION_HPP + +#include +#include +#include + +namespace boost { + +/** + * Instantiations of class template \bernoulli_distribution model a + * \random_distribution. Such a random distribution produces bool values + * distributed with probabilities P(true) = p and P(false) = 1-p. p is + * the parameter of the distribution. + */ +template +class bernoulli_distribution +{ +public: + // In principle, this could work with both integer and floating-point + // types. Generating floating-point random numbers in the first + // place is probably more expensive, so use integer as input. + typedef int input_type; + typedef bool result_type; + + /** + * Constructs a \bernoulli_distribution object. + * p is the parameter of the distribution. + * + * Requires: 0 <= p <= 1 + */ + explicit bernoulli_distribution(const RealType& p_arg = RealType(0.5)) + : _p(p_arg) + { + assert(_p >= 0); + assert(_p <= 1); + } + + // compiler-generated copy ctor and assignment operator are fine + + /** + * Returns: The "p" parameter of the distribution. + */ + RealType p() const { return _p; } + /** + * Effects: Subsequent uses of the distribution do not depend + * on values produced by any engine prior to invoking reset. + */ + void reset() { } + + /** + * Returns: a random variate distributed according to the + * \bernoulli_distribution. + */ + template + result_type operator()(Engine& eng) + { + if(_p == RealType(0)) + return false; + else + return RealType(eng() - (eng.min)()) <= _p * RealType((eng.max)()-(eng.min)()); + } + +#ifndef BOOST_RANDOM_NO_STREAM_OPERATORS + /** + * Writes the parameters of the distribution to a @c std::ostream. + */ + template + friend std::basic_ostream& + operator<<(std::basic_ostream& os, const bernoulli_distribution& bd) + { + os << bd._p; + return os; + } + + /** + * Reads the parameters of the distribution from a @c std::istream. + */ + template + friend std::basic_istream& + operator>>(std::basic_istream& is, bernoulli_distribution& bd) + { + is >> std::ws >> bd._p; + return is; + } +#endif + +private: + RealType _p; +}; + +} // namespace boost + +#endif // BOOST_RANDOM_BERNOULLI_DISTRIBUTION_HPP diff --git a/Boost/boost/random/binomial_distribution.hpp b/Boost/boost/random/binomial_distribution.hpp new file mode 100644 index 000000000..1ca110d08 --- /dev/null +++ b/Boost/boost/random/binomial_distribution.hpp @@ -0,0 +1,111 @@ +/* boost random/binomial_distribution.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: binomial_distribution.hpp 60755 2010-03-22 00:45:06Z steven_watanabe $ + * + */ + +#ifndef BOOST_RANDOM_BINOMIAL_DISTRIBUTION_HPP +#define BOOST_RANDOM_BINOMIAL_DISTRIBUTION_HPP + +#include +#include +#include +#include + +namespace boost { + +/** + * The binomial distribution is an integer valued distribution with + * two parameters, @c t and @c p. The values of the distribution + * are within the range [0,t]. + * + * The probability that the distribution produces a value k is + * \f${t \choose k}p^k(1-p)^{t-k}\f$. + */ +template +class binomial_distribution +{ +public: + typedef typename bernoulli_distribution::input_type input_type; + typedef IntType result_type; + + /** + * Construct an @c binomial_distribution object. @c t and @c p + * are the parameters of the distribution. + * + * Requires: t >=0 && 0 <= p <= 1 + */ + explicit binomial_distribution(IntType t = 1, + const RealType& p = RealType(0.5)) + : _bernoulli(p), _t(t) + { + assert(_t >= 0); + assert(RealType(0) <= p && p <= RealType(1)); + } + + // compiler-generated copy ctor and assignment operator are fine + + /** Returns: the @c t parameter of the distribution */ + IntType t() const { return _t; } + /** Returns: the @c p parameter of the distribution */ + RealType p() const { return _bernoulli.p(); } + /** + * Effects: Subsequent uses of the distribution do not depend + * on values produced by any engine prior to invoking reset. + */ + void reset() { } + + /** + * Returns: a random variate distributed according to the + * binomial distribution. + */ + template + result_type operator()(Engine& eng) + { + // TODO: This is O(_t), but it should be O(log(_t)) for large _t + result_type n = 0; + for(IntType i = 0; i < _t; ++i) + if(_bernoulli(eng)) + ++n; + return n; + } + +#ifndef BOOST_RANDOM_NO_STREAM_OPERATORS + /** + * Writes the parameters of the distribution to a @c std::ostream. + */ + template + friend std::basic_ostream& + operator<<(std::basic_ostream& os, const binomial_distribution& bd) + { + os << bd._bernoulli << " " << bd._t; + return os; + } + + /** + * Reads the parameters of the distribution from a @c std::istream. + */ + template + friend std::basic_istream& + operator>>(std::basic_istream& is, binomial_distribution& bd) + { + is >> std::ws >> bd._bernoulli >> std::ws >> bd._t; + return is; + } +#endif + +private: + bernoulli_distribution _bernoulli; + IntType _t; +}; + +} // namespace boost + +#endif // BOOST_RANDOM_BINOMIAL_DISTRIBUTION_HPP diff --git a/Boost/boost/random/cauchy_distribution.hpp b/Boost/boost/random/cauchy_distribution.hpp new file mode 100644 index 000000000..8555104d1 --- /dev/null +++ b/Boost/boost/random/cauchy_distribution.hpp @@ -0,0 +1,121 @@ +/* boost random/cauchy_distribution.hpp header file + * + * Copyright Jens Maurer 2000-2001 + * 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: cauchy_distribution.hpp 60755 2010-03-22 00:45:06Z steven_watanabe $ + * + * Revision history + * 2001-02-18 moved to individual header files + */ + +#ifndef BOOST_RANDOM_CAUCHY_DISTRIBUTION_HPP +#define BOOST_RANDOM_CAUCHY_DISTRIBUTION_HPP + +#include +#include +#include +#include +#include + +namespace boost { + +#if defined(__GNUC__) && (__GNUC__ < 3) +// Special gcc workaround: gcc 2.95.x ignores using-declarations +// in template classes (confirmed by gcc author Martin v. Loewis) + using std::tan; +#endif + +// Cauchy distribution: + +/** + * The cauchy distribution is a continuous distribution with two + * parameters, sigma and median. + * + * It has \f$p(x) = \frac{\sigma}{\pi(\sigma^2 + (x-m)^2)}\f$ + */ +template +class cauchy_distribution +{ +public: + typedef RealType input_type; + typedef RealType result_type; + +#ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS + BOOST_STATIC_ASSERT(!std::numeric_limits::is_integer); +#endif + + /** + * Constructs a \cauchy_distribution with the paramters @c median + * and @c sigma. + */ + explicit cauchy_distribution(result_type median_arg = result_type(0), + result_type sigma_arg = result_type(1)) + : _median(median_arg), _sigma(sigma_arg) { } + + // compiler-generated copy ctor and assignment operator are fine + + /** + * Returns: the "median" parameter of the distribution + */ + result_type median() const { return _median; } + /** + * Returns: the "sigma" parameter of the distribution + */ + result_type sigma() const { return _sigma; } + /** + * Effects: Subsequent uses of the distribution do not depend + * on values produced by any engine prior to invoking reset. + */ + void reset() { } + + /** + * Returns: A random variate distributed according to the + * cauchy distribution. + */ + template + result_type operator()(Engine& eng) + { + // Can we have a boost::mathconst please? + const result_type pi = result_type(3.14159265358979323846); +#ifndef BOOST_NO_STDC_NAMESPACE + using std::tan; +#endif + return _median + _sigma * tan(pi*(eng()-result_type(0.5))); + } + +#ifndef BOOST_RANDOM_NO_STREAM_OPERATORS + /** + * Writes the parameters of the distribution to a @c std::ostream. + */ + template + friend std::basic_ostream& + operator<<(std::basic_ostream& os, const cauchy_distribution& cd) + { + os << cd._median << " " << cd._sigma; + return os; + } + + /** + * Reads the parameters of the distribution from a @c std::istream. + */ + template + friend std::basic_istream& + operator>>(std::basic_istream& is, cauchy_distribution& cd) + { + is >> std::ws >> cd._median >> std::ws >> cd._sigma; + return is; + } +#endif + +private: + result_type _median, _sigma; +}; + +} // namespace boost + +#endif // BOOST_RANDOM_CAUCHY_DISTRIBUTION_HPP diff --git a/Boost/boost/random/detail/auto_link.hpp b/Boost/boost/random/detail/auto_link.hpp new file mode 100644 index 000000000..aec0af630 --- /dev/null +++ b/Boost/boost/random/detail/auto_link.hpp @@ -0,0 +1,42 @@ +/* boost random auto_link.hpp header file + * + * Copyright Steven Watanabe 2010 + * 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) + * + * $Id: auto_link.hpp 60755 2010-03-22 00:45:06Z steven_watanabe $ + */ + +#ifndef BOOST_RANDOM_DETAIL_AUTO_LINK_HPP +#define BOOST_RANDOM_DETAIL_AUTO_LINK_HPP + +#include + +#ifdef BOOST_HAS_DECLSPEC + #if defined(BOOST_ALL_DYN_LINK) || defined(BOOST_RANDOM_DYN_LINK) + #if defined(BOOST_RANDOM_SOURCE) + #define BOOST_RANDOM_DECL __declspec(dllexport) + #else + #define BOOST_RANDOM_DECL __declspec(dllimport) + #endif + #endif +#endif + +#ifndef BOOST_RANDOM_DECL + #define BOOST_RANDOM_DECL +#endif + +#if !defined(BOOST_RANDOM_NO_LIB) && !defined(BOOST_ALL_NO_LIB) && !defined(BOOST_RANDOM_SOURCE) + +#define BOOST_LIB_NAME boost_random + +#if defined(BOOST_RANDOM_DYN_LINK) || defined(BOOST_ALL_DYN_LINK) + #define BOOST_DYN_LINK +#endif + +#include + +#endif + +#endif diff --git a/Boost/boost/random/detail/config.hpp b/Boost/boost/random/detail/config.hpp new file mode 100644 index 000000000..bb834534b --- /dev/null +++ b/Boost/boost/random/detail/config.hpp @@ -0,0 +1,18 @@ +/* boost random/detail/config.hpp header file + * + * Copyright Steven Watanabe 2009 + * 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: config.hpp 52492 2009-04-19 14:55:57Z steven_watanabe $ + */ + +#include + +#if (defined(BOOST_NO_OPERATORS_IN_NAMESPACE) || defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)) \ + && !defined(BOOST_MSVC) + #define BOOST_RANDOM_NO_STREAM_OPERATORS +#endif diff --git a/Boost/boost/random/detail/const_mod.hpp b/Boost/boost/random/detail/const_mod.hpp new file mode 100644 index 000000000..07f754506 --- /dev/null +++ b/Boost/boost/random/detail/const_mod.hpp @@ -0,0 +1,363 @@ +/* boost random/detail/const_mod.hpp header file + * + * Copyright Jens Maurer 2000-2001 + * 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: const_mod.hpp 58649 2010-01-02 21:23:17Z steven_watanabe $ + * + * Revision history + * 2001-02-18 moved to individual header files + */ + +#ifndef BOOST_RANDOM_CONST_MOD_HPP +#define BOOST_RANDOM_CONST_MOD_HPP + +#include +#include +#include +#include +#include + +#include + +namespace boost { +namespace random { + +/* + * Some random number generators require modular arithmetic. Put + * everything we need here. + * IntType must be an integral type. + */ + +namespace detail { + + template + struct do_add + { }; + + template<> + struct do_add + { + template + static IntType add(IntType m, IntType x, IntType c) + { + if (x < m - c) + return x + c; + else + return x - (m-c); + } + }; + + template<> + struct do_add + { + template + static IntType add(IntType, IntType, IntType) + { + // difficult + assert(!"const_mod::add with c too large"); + return 0; + } + }; +} // namespace detail + +#if !(defined(__BORLANDC__) && (__BORLANDC__ == 0x560)) + +template +class const_mod +{ +public: + static IntType add(IntType x, IntType c) + { + if(c == 0) + return x; + else if(c <= traits::const_max - m) // i.e. m+c < max + return add_small(x, c); + else + return detail::do_add::add(m, x, c); + } + + static IntType mult(IntType a, IntType x) + { + if(a == 1) + return x; + else if(m <= traits::const_max/a) // i.e. a*m <= max + return mult_small(a, x); + else if(traits::is_signed && (m%a < m/a)) + return mult_schrage(a, x); + else { + // difficult + assert(!"const_mod::mult with a too large"); + return 0; + } + } + + static IntType mult_add(IntType a, IntType x, IntType c) + { + if(m <= (traits::const_max-c)/a) // i.e. a*m+c <= max + return (a*x+c) % m; + else + return add(mult(a, x), c); + } + + static IntType invert(IntType x) + { return x == 0 ? 0 : invert_euclidian(x); } + +private: + typedef integer_traits traits; + + const_mod(); // don't instantiate + + static IntType add_small(IntType x, IntType c) + { + x += c; + if(x >= m) + x -= m; + return x; + } + + static IntType mult_small(IntType a, IntType x) + { + return a*x % m; + } + + static IntType mult_schrage(IntType a, IntType value) + { + const IntType q = m / a; + const IntType r = m % a; + + assert(r < q); // check that overflow cannot happen + + value = a*(value%q) - r*(value/q); + // An optimizer bug in the SGI MIPSpro 7.3.1.x compiler requires this + // convoluted formulation of the loop (Synge Todo) + for(;;) { + if (value > 0) + break; + value += m; + } + return value; + } + + // invert c in the finite field (mod m) (m must be prime) + static IntType invert_euclidian(IntType c) + { + // we are interested in the gcd factor for c, because this is our inverse + BOOST_STATIC_ASSERT(m > 0); +#if BOOST_WORKAROUND(__MWERKS__, BOOST_TESTED_AT(0x3003)) + assert(boost::integer_traits::is_signed); +#elif !defined(BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS) + BOOST_STATIC_ASSERT(boost::integer_traits::is_signed); +#endif + assert(c > 0); + IntType l1 = 0; + IntType l2 = 1; + IntType n = c; + IntType p = m; + for(;;) { + IntType q = p / n; + l1 -= q * l2; // this requires a signed IntType! + p -= q * n; + if(p == 0) + return (l2 < 1 ? l2 + m : l2); + IntType q2 = n / p; + l2 -= q2 * l1; + n -= q2 * p; + if(n == 0) + return (l1 < 1 ? l1 + m : l1); + } + } +}; + +// The modulus is exactly the word size: rely on machine overflow handling. +// Due to a GCC bug, we cannot partially specialize in the presence of +// template value parameters. +template<> +class const_mod +{ + typedef unsigned int IntType; +public: + static IntType add(IntType x, IntType c) { return x+c; } + static IntType mult(IntType a, IntType x) { return a*x; } + static IntType mult_add(IntType a, IntType x, IntType c) { return a*x+c; } + + // m is not prime, thus invert is not useful +private: // don't instantiate + const_mod(); +}; + +template<> +class const_mod +{ + typedef unsigned long IntType; +public: + static IntType add(IntType x, IntType c) { return x+c; } + static IntType mult(IntType a, IntType x) { return a*x; } + static IntType mult_add(IntType a, IntType x, IntType c) { return a*x+c; } + + // m is not prime, thus invert is not useful +private: // don't instantiate + const_mod(); +}; + +// the modulus is some power of 2: rely partly on machine overflow handling +// we only specialize for rand48 at the moment +#ifndef BOOST_NO_INT64_T +template<> +class const_mod +{ + typedef uint64_t IntType; +public: + static IntType add(IntType x, IntType c) { return c == 0 ? x : mod(x+c); } + static IntType mult(IntType a, IntType x) { return mod(a*x); } + static IntType mult_add(IntType a, IntType x, IntType c) + { return mod(a*x+c); } + static IntType mod(IntType x) { return x &= ((uint64_t(1) << 48)-1); } + + // m is not prime, thus invert is not useful +private: // don't instantiate + const_mod(); +}; +#endif /* !BOOST_NO_INT64_T */ + +#else + +// +// for some reason Borland C++ Builder 6 has problems with +// the full specialisations of const_mod, define a generic version +// instead, the compiler will optimise away the const-if statements: +// + +template +class const_mod +{ +public: + static IntType add(IntType x, IntType c) + { + if(0 == m) + { + return x+c; + } + else + { + if(c == 0) + return x; + else if(c <= traits::const_max - m) // i.e. m+c < max + return add_small(x, c); + else + return detail::do_add::add(m, x, c); + } + } + + static IntType mult(IntType a, IntType x) + { + if(x == 0) + { + return a*x; + } + else + { + if(a == 1) + return x; + else if(m <= traits::const_max/a) // i.e. a*m <= max + return mult_small(a, x); + else if(traits::is_signed && (m%a < m/a)) + return mult_schrage(a, x); + else { + // difficult + assert(!"const_mod::mult with a too large"); + return 0; + } + } + } + + static IntType mult_add(IntType a, IntType x, IntType c) + { + if(m == 0) + { + return a*x+c; + } + else + { + if(m <= (traits::const_max-c)/a) // i.e. a*m+c <= max + return (a*x+c) % m; + else + return add(mult(a, x), c); + } + } + + static IntType invert(IntType x) + { return x == 0 ? 0 : invert_euclidian(x); } + +private: + typedef integer_traits traits; + + const_mod(); // don't instantiate + + static IntType add_small(IntType x, IntType c) + { + x += c; + if(x >= m) + x -= m; + return x; + } + + static IntType mult_small(IntType a, IntType x) + { + return a*x % m; + } + + static IntType mult_schrage(IntType a, IntType value) + { + const IntType q = m / a; + const IntType r = m % a; + + assert(r < q); // check that overflow cannot happen + + value = a*(value%q) - r*(value/q); + while(value <= 0) + value += m; + return value; + } + + // invert c in the finite field (mod m) (m must be prime) + static IntType invert_euclidian(IntType c) + { + // we are interested in the gcd factor for c, because this is our inverse + BOOST_STATIC_ASSERT(m > 0); +#ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS + BOOST_STATIC_ASSERT(boost::integer_traits::is_signed); +#endif + assert(c > 0); + IntType l1 = 0; + IntType l2 = 1; + IntType n = c; + IntType p = m; + for(;;) { + IntType q = p / n; + l1 -= q * l2; // this requires a signed IntType! + p -= q * n; + if(p == 0) + return (l2 < 1 ? l2 + m : l2); + IntType q2 = n / p; + l2 -= q2 * l1; + n -= q2 * p; + if(n == 0) + return (l1 < 1 ? l1 + m : l1); + } + } +}; + + +#endif + +} // namespace random +} // namespace boost + +#include + +#endif // BOOST_RANDOM_CONST_MOD_HPP diff --git a/Boost/boost/random/detail/disable_warnings.hpp b/Boost/boost/random/detail/disable_warnings.hpp new file mode 100644 index 000000000..ab129e0b9 --- /dev/null +++ b/Boost/boost/random/detail/disable_warnings.hpp @@ -0,0 +1,23 @@ +/* boost random/detail/disable_warnings.hpp header file + * + * Copyright Steven Watanabe 2009 + * 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: disable_warnings.hpp 60755 2010-03-22 00:45:06Z steven_watanabe $ + * + */ + +// No #include guard. This header is intended to be included multiple times. + +#include + +#ifdef BOOST_MSVC +#pragma warning(push) +#pragma warning(disable:4512) +#pragma warning(disable:4127) +#pragma warning(disable:4724) +#endif diff --git a/Boost/boost/random/detail/enable_warnings.hpp b/Boost/boost/random/detail/enable_warnings.hpp new file mode 100644 index 000000000..12f0840ef --- /dev/null +++ b/Boost/boost/random/detail/enable_warnings.hpp @@ -0,0 +1,18 @@ +/* boost random/detail/enable_warnings.hpp header file + * + * Copyright Steven Watanabe 2009 + * 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: enable_warnings.hpp 58649 2010-01-02 21:23:17Z steven_watanabe $ + * + */ + +// No #include guard. This header is intended to be included multiple times. + +#ifdef BOOST_MSVC +#pragma warning(pop) +#endif diff --git a/Boost/boost/random/detail/iterator_mixin.hpp b/Boost/boost/random/detail/iterator_mixin.hpp new file mode 100644 index 000000000..ca67ebb5a --- /dev/null +++ b/Boost/boost/random/detail/iterator_mixin.hpp @@ -0,0 +1,45 @@ +/* boost random/detail/iterator_mixin.hpp header file + * + * Copyright Jens Maurer 2000-2001 + * 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. + * + * Revision history + */ + +#ifndef BOOST_ITERATOR_MIXIN_HPP +#define BOOST_ITERATOR_MIXIN_HPP + +#include + +namespace boost { + +// must be in boost namespace, otherwise the inline friend trick fails +template +class generator_iterator_mixin_adapter + : incrementable, equality_comparable +{ +public: + typedef std::input_iterator_tag iterator_category; + typedef ResultType value_type; + typedef std::ptrdiff_t difference_type; + typedef const value_type * pointer; + typedef const value_type & reference; + Generator& operator++() { v = cast()(); return cast(); } + const value_type& operator*() const { return v; } + +protected: + // instantiate from derived classes only + generator_iterator_mixin_adapter() { } + void iterator_init() { operator++(); } +private: + Generator & cast() { return static_cast(*this); } + value_type v; +}; + +} // namespace boost + +#endif // BOOST_ITERATOR_MIXIN_HPP diff --git a/Boost/boost/random/detail/pass_through_engine.hpp b/Boost/boost/random/detail/pass_through_engine.hpp new file mode 100644 index 000000000..8627025ef --- /dev/null +++ b/Boost/boost/random/detail/pass_through_engine.hpp @@ -0,0 +1,100 @@ +/* boost random/detail/uniform_int_float.hpp header file + * + * Copyright Jens Maurer 2000-2001 + * 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: pass_through_engine.hpp 58649 2010-01-02 21:23:17Z steven_watanabe $ + * + */ + +#ifndef BOOST_RANDOM_DETAIL_PASS_THROUGH_ENGINE_HPP +#define BOOST_RANDOM_DETAIL_PASS_THROUGH_ENGINE_HPP + +#include +#include +#include + +namespace boost { +namespace random { +namespace detail { + +template +class pass_through_engine +{ +private: + typedef ptr_helper helper_type; + +public: + typedef typename helper_type::value_type base_type; + typedef typename base_type::result_type result_type; + + explicit pass_through_engine(UniformRandomNumberGenerator rng) + // make argument an rvalue to avoid matching Generator& constructor + : _rng(static_cast(rng)) + { } + + result_type min BOOST_PREVENT_MACRO_SUBSTITUTION () const { return (base().min)(); } + result_type max BOOST_PREVENT_MACRO_SUBSTITUTION () const { return (base().max)(); } + base_type& base() { return helper_type::ref(_rng); } + const base_type& base() const { return helper_type::ref(_rng); } + + result_type operator()() { return base()(); } + +private: + UniformRandomNumberGenerator _rng; +}; + +#ifndef BOOST_NO_STD_LOCALE + +template +std::basic_ostream& +operator<<( + std::basic_ostream& os + , const pass_through_engine& ud + ) +{ + return os << ud.base(); +} + +template +std::basic_istream& +operator>>( + std::basic_istream& is + , const pass_through_engine& ud + ) +{ + return is >> ud.base(); +} + +#else // no new streams + +template +inline std::ostream& +operator<<(std::ostream& os, + const pass_through_engine& ud) +{ + return os << ud.base(); +} + +template +inline std::istream& +operator>>(std::istream& is, + const pass_through_engine& ud) +{ + return is >> ud.base(); +} + +#endif + +} // namespace detail +} // namespace random +} // namespace boost + +#include + +#endif // BOOST_RANDOM_DETAIL_PASS_THROUGH_ENGINE_HPP + diff --git a/Boost/boost/random/detail/ptr_helper.hpp b/Boost/boost/random/detail/ptr_helper.hpp new file mode 100644 index 000000000..d583afe8e --- /dev/null +++ b/Boost/boost/random/detail/ptr_helper.hpp @@ -0,0 +1,94 @@ +/* boost random/detail/ptr_helper.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: ptr_helper.hpp 24096 2004-07-27 03:43:34Z dgregor $ + * + */ + +#ifndef BOOST_RANDOM_DETAIL_PTR_HELPER_HPP +#define BOOST_RANDOM_DETAIL_PTR_HELPER_HPP + +#include + + +namespace boost { +namespace random { +namespace detail { + +// type_traits could help here, but I don't want to depend on type_traits. +template +struct ptr_helper +{ + typedef T value_type; + typedef T& reference_type; + typedef const T& rvalue_type; + static reference_type ref(T& r) { return r; } + static const T& ref(const T& r) { return r; } +}; + +#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION +template +struct ptr_helper +{ + typedef T value_type; + typedef T& reference_type; + typedef T& rvalue_type; + static reference_type ref(T& r) { return r; } + static const T& ref(const T& r) { return r; } +}; + +template +struct ptr_helper +{ + typedef T value_type; + typedef T& reference_type; + typedef T* rvalue_type; + static reference_type ref(T * p) { return *p; } + static const T& ref(const T * p) { return *p; } +}; +#endif + +} // namespace detail +} // namespace random +} // namespace boost + +// +// BOOST_RANDOM_PTR_HELPER_SPEC -- +// +// Helper macro for broken compilers defines specializations of +// ptr_helper. +// +#ifdef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION +# define BOOST_RANDOM_PTR_HELPER_SPEC(T) \ +namespace boost { namespace random { namespace detail { \ +template<> \ +struct ptr_helper \ +{ \ + typedef T value_type; \ + typedef T& reference_type; \ + typedef T& rvalue_type; \ + static reference_type ref(T& r) { return r; } \ + static const T& ref(const T& r) { return r; } \ +}; \ + \ +template<> \ +struct ptr_helper \ +{ \ + typedef T value_type; \ + typedef T& reference_type; \ + typedef T* rvalue_type; \ + static reference_type ref(T * p) { return *p; } \ + static const T& ref(const T * p) { return *p; } \ +}; \ +}}} +#else +# define BOOST_RANDOM_PTR_HELPER_SPEC(T) +#endif + +#endif // BOOST_RANDOM_DETAIL_PTR_HELPER_HPP diff --git a/Boost/boost/random/detail/seed.hpp b/Boost/boost/random/detail/seed.hpp new file mode 100644 index 000000000..9b0f744b8 --- /dev/null +++ b/Boost/boost/random/detail/seed.hpp @@ -0,0 +1,89 @@ +/* boost random/detail/seed.hpp header file + * + * Copyright Steven Watanabe 2009 + * 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: seed.hpp 60755 2010-03-22 00:45:06Z steven_watanabe $ + */ + +#ifndef BOOST_RANDOM_DETAIL_SEED_HPP +#define BOOST_RANDOM_DETAIL_SEED_HPP + +#include + +// Sun seems to have trouble with the use of SFINAE for the +// templated constructor. So does Borland. +#if !defined(BOOST_NO_SFINAE) && !defined(__SUNPRO_CC) && !defined(__BORLANDC__) + +#include +#include + +namespace boost { +namespace random { +namespace detail { + +template +struct disable_seed : boost::disable_if > {}; + +template +struct disable_constructor : disable_seed {}; + +template +struct disable_constructor {}; + +#define BOOST_RANDOM_DETAIL_GENERATOR_CONSTRUCTOR(Self, Generator, gen) \ + template \ + explicit Self(Generator& gen, typename ::boost::random::detail::disable_constructor::type* = 0) + +#define BOOST_RANDOM_DETAIL_GENERATOR_SEED(Self, Generator, gen) \ + template \ + void seed(Generator& gen, typename ::boost::random::detail::disable_seed::type* = 0) + +#define BOOST_RANDOM_DETAIL_ARITHMETIC_CONSTRUCTOR(Self, T, x) \ + explicit Self(const T& x) + +#define BOOST_RANDOM_DETAIL_ARITHMETIC_SEED(Self, T, x) \ + void seed(const T& x) + +} +} +} + +#else + +#include +#include + +#define BOOST_RANDOM_DETAIL_GENERATOR_CONSTRUCTOR(Self, Generator, gen) \ + Self(Self& other) { *this = other; } \ + Self(const Self& other) { *this = other; } \ + template \ + explicit Self(Generator& gen) { \ + boost_random_constructor_impl(gen, ::boost::is_arithmetic());\ + } \ + template \ + void boost_random_constructor_impl(Generator& gen, ::boost::mpl::false_) + +#define BOOST_RANDOM_DETAIL_GENERATOR_SEED(Self, Generator, gen) \ + template \ + void seed(Generator& gen) { \ + boost_random_seed_impl(gen, ::boost::is_arithmetic());\ + }\ + template\ + void boost_random_seed_impl(Generator& gen, ::boost::mpl::false_) + +#define BOOST_RANDOM_DETAIL_ARITHMETIC_CONSTRUCTOR(Self, T, x) \ + explicit Self(const T& x) { boost_random_constructor_impl(x, ::boost::mpl::true_()); }\ + void boost_random_constructor_impl(const T& x, ::boost::mpl::true_) + +#define BOOST_RANDOM_DETAIL_ARITHMETIC_SEED(Self, T, x) \ + void seed(const T& x) { boost_random_seed_impl(x, ::boost::mpl::true_()); }\ + void boost_random_seed_impl(const T& x, ::boost::mpl::true_) + +#endif + +#endif diff --git a/Boost/boost/random/detail/signed_unsigned_tools.hpp b/Boost/boost/random/detail/signed_unsigned_tools.hpp new file mode 100644 index 000000000..c1344a3de --- /dev/null +++ b/Boost/boost/random/detail/signed_unsigned_tools.hpp @@ -0,0 +1,89 @@ +/* boost random/detail/signed_unsigned_tools.hpp header file + * + * Copyright Jens Maurer 2006 + * 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. + */ + +#ifndef BOOST_RANDOM_DETAIL_SIGNED_UNSIGNED_TOOLS +#define BOOST_RANDOM_DETAIL_SIGNED_UNSIGNED_TOOLS + +#include +#include +#include + +namespace boost { +namespace random { +namespace detail { + + +/* + * Compute x - y, we know that x >= y, return an unsigned value. + */ + +template::is_signed> +struct subtract { }; + +template +struct subtract +{ + typedef T result_type; + result_type operator()(T x, T y) { return x - y; } +}; + +template +struct subtract +{ + typedef typename make_unsigned::type result_type; + result_type operator()(T x, T y) + { + if (y >= 0) // because x >= y, it follows that x >= 0, too + return result_type(x) - result_type(y); + if (x >= 0) // y < 0 + // avoid the nasty two's complement case for y == min() + return result_type(x) + result_type(-(y+1)) + 1; + // both x and y are negative: no signed overflow + return result_type(x - y); + } +}; + +/* + * Compute x + y, x is unsigned, result fits in type of "y". + */ + +template::is_signed> +struct add { }; + +template +struct add +{ + typedef T2 result_type; + result_type operator()(T1 x, T2 y) { return T2(x) + y; } +}; + +template +struct add +{ + typedef T2 result_type; + result_type operator()(T1 x, T2 y) + { + if (y >= 0) + return T2(x) + y; + // y < 0 + if (x >= T1(-(y+1))) // result >= 0 after subtraction + // avoid the nasty two's complement edge case for y == min() + return T2(x - T1(-(y+1)) - 1); + // abs(x) < abs(y), thus T2 able to represent x + return T2(x) + y; + } +}; + +} // namespace detail +} // namespace random +} // namespace boost + +#endif // BOOST_RANDOM_DETAIL_SIGNED_UNSIGNED_TOOLS + diff --git a/Boost/boost/random/detail/uniform_int_float.hpp b/Boost/boost/random/detail/uniform_int_float.hpp new file mode 100644 index 000000000..8475f1bf7 --- /dev/null +++ b/Boost/boost/random/detail/uniform_int_float.hpp @@ -0,0 +1,85 @@ +/* boost random/detail/uniform_int_float.hpp header file + * + * Copyright Jens Maurer 2000-2001 + * 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: uniform_int_float.hpp 52492 2009-04-19 14:55:57Z steven_watanabe $ + * + */ + +#ifndef BOOST_RANDOM_DETAIL_UNIFORM_INT_FLOAT_HPP +#define BOOST_RANDOM_DETAIL_UNIFORM_INT_FLOAT_HPP + +#include +#include +#include + + +namespace boost { +namespace random { +namespace detail { + +template +class uniform_int_float +{ +public: + typedef UniformRandomNumberGenerator base_type; + typedef IntType result_type; + + uniform_int_float(base_type rng, IntType min_arg = 0, IntType max_arg = 0xffffffff) + : _rng(rng), _min(min_arg), _max(max_arg) + { + init(); + } + + result_type min BOOST_PREVENT_MACRO_SUBSTITUTION () const { return _min; } + result_type max BOOST_PREVENT_MACRO_SUBSTITUTION () const { return _max; } + base_type& base() { return _rng.base(); } + const base_type& base() const { return _rng.base(); } + + result_type operator()() + { + return static_cast(_rng() * _range) + _min; + } + +#ifndef BOOST_RANDOM_NO_STREAM_OPERATORS + template + friend std::basic_ostream& + operator<<(std::basic_ostream& os, const uniform_int_float& ud) + { + os << ud._min << " " << ud._max; + return os; + } + + template + friend std::basic_istream& + operator>>(std::basic_istream& is, uniform_int_float& ud) + { + is >> std::ws >> ud._min >> std::ws >> ud._max; + ud.init(); + return is; + } +#endif + +private: + void init() + { + _range = static_cast(_max-_min)+1; + } + + typedef typename base_type::result_type base_result; + uniform_01 _rng; + result_type _min, _max; + base_result _range; +}; + + +} // namespace detail +} // namespace random +} // namespace boost + +#endif // BOOST_RANDOM_DETAIL_UNIFORM_INT_FLOAT_HPP diff --git a/Boost/boost/random/discard_block.hpp b/Boost/boost/random/discard_block.hpp new file mode 100644 index 000000000..313363d68 --- /dev/null +++ b/Boost/boost/random/discard_block.hpp @@ -0,0 +1,132 @@ +/* boost random/discard_block.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: discard_block.hpp 60755 2010-03-22 00:45:06Z steven_watanabe $ + * + * Revision history + * 2001-03-02 created + */ + +#ifndef BOOST_RANDOM_DISCARD_BLOCK_HPP +#define BOOST_RANDOM_DISCARD_BLOCK_HPP + +#include +#include +#include +#include +#include + + +namespace boost { +namespace random { + +/** + * The class template \discard_block is a model of + * \pseudo_random_number_generator. It modifies + * another generator by discarding parts of its output. + * Out of every block of @c r results, the first @c p + * will be returned and the rest discarded. + * + * Requires: 0 < p <= r + */ +template +class discard_block +{ +public: + typedef UniformRandomNumberGenerator base_type; + typedef typename base_type::result_type result_type; + + BOOST_STATIC_CONSTANT(bool, has_fixed_range = false); + BOOST_STATIC_CONSTANT(unsigned int, total_block = p); + BOOST_STATIC_CONSTANT(unsigned int, returned_block = r); + +#ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS + BOOST_STATIC_ASSERT(total_block >= returned_block); +#endif + + discard_block() : _rng(), _n(0) { } + explicit discard_block(const base_type & rng) : _rng(rng), _n(0) { } + template explicit discard_block(T s) : _rng(s), _n(0) {} + template discard_block(It& first, It last) + : _rng(first, last), _n(0) { } + void seed() { _rng.seed(); _n = 0; } + template void seed(T s) { _rng.seed(s); _n = 0; } + template void seed(It& first, It last) + { _n = 0; _rng.seed(first, last); } + + const base_type& base() const { return _rng; } + + result_type operator()() + { + if(_n >= returned_block) { + // discard values of random number generator + for( ; _n < total_block; ++_n) + _rng(); + _n = 0; + } + ++_n; + return _rng(); + } + + result_type min BOOST_PREVENT_MACRO_SUBSTITUTION () const { return (_rng.min)(); } + result_type max BOOST_PREVENT_MACRO_SUBSTITUTION () const { return (_rng.max)(); } + static bool validation(result_type x) { return true; } // dummy + +#ifndef BOOST_NO_OPERATORS_IN_NAMESPACE + +#ifndef BOOST_RANDOM_NO_STREAM_OPERATORS + template + friend std::basic_ostream& + operator<<(std::basic_ostream& os, const discard_block& s) + { + os << s._rng << " " << s._n << " "; + return os; + } + + template + friend std::basic_istream& + operator>>(std::basic_istream& is, discard_block& s) + { + is >> s._rng >> std::ws >> s._n >> std::ws; + return is; + } +#endif + + friend bool operator==(const discard_block& x, const discard_block& y) + { return x._rng == y._rng && x._n == y._n; } + friend bool operator!=(const discard_block& x, const discard_block& y) + { return !(x == y); } +#else + // Use a member function; Streamable concept not supported. + bool operator==(const discard_block& rhs) const + { return _rng == rhs._rng && _n == rhs._n; } + bool operator!=(const discard_block& rhs) const + { return !(*this == rhs); } +#endif + +private: + base_type _rng; + unsigned int _n; +}; + +#ifndef BOOST_NO_INCLASS_MEMBER_INITIALIZATION +// A definition is required even for integral static constants +template +const bool discard_block::has_fixed_range; +template +const unsigned int discard_block::total_block; +template +const unsigned int discard_block::returned_block; +#endif + +} // namespace random + +} // namespace boost + +#endif // BOOST_RANDOM_DISCARD_BLOCK_HPP diff --git a/Boost/boost/random/exponential_distribution.hpp b/Boost/boost/random/exponential_distribution.hpp new file mode 100644 index 000000000..63abb0402 --- /dev/null +++ b/Boost/boost/random/exponential_distribution.hpp @@ -0,0 +1,86 @@ +/* boost random/exponential_distribution.hpp header file + * + * Copyright Jens Maurer 2000-2001 + * 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: exponential_distribution.hpp 60755 2010-03-22 00:45:06Z steven_watanabe $ + * + * Revision history + * 2001-02-18 moved to individual header files + */ + +#ifndef BOOST_RANDOM_EXPONENTIAL_DISTRIBUTION_HPP +#define BOOST_RANDOM_EXPONENTIAL_DISTRIBUTION_HPP + +#include +#include +#include +#include +#include +#include + +namespace boost { + +/** + * The exponential distribution has a single parameter lambda. + * + * It has \f$p(x) = \lambda e^{-\lambda x}\f$ + */ +template +class exponential_distribution +{ +public: + typedef RealType input_type; + typedef RealType result_type; + +#if !defined(BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS) && !(defined(BOOST_MSVC) && BOOST_MSVC <= 1300) + BOOST_STATIC_ASSERT(!std::numeric_limits::is_integer); +#endif + + explicit exponential_distribution(result_type lambda_arg = result_type(1)) + : _lambda(lambda_arg) { assert(_lambda > result_type(0)); } + + // compiler-generated copy ctor and assignment operator are fine + + result_type lambda() const { return _lambda; } + + void reset() { } + + template + result_type operator()(Engine& eng) + { +#ifndef BOOST_NO_STDC_NAMESPACE + using std::log; +#endif + return -result_type(1) / _lambda * log(result_type(1)-eng()); + } + +#ifndef BOOST_RANDOM_NO_STREAM_OPERATORS + template + friend std::basic_ostream& + operator<<(std::basic_ostream& os, const exponential_distribution& ed) + { + os << ed._lambda; + return os; + } + + template + friend std::basic_istream& + operator>>(std::basic_istream& is, exponential_distribution& ed) + { + is >> std::ws >> ed._lambda; + return is; + } +#endif + +private: + result_type _lambda; +}; + +} // namespace boost + +#endif // BOOST_RANDOM_EXPONENTIAL_DISTRIBUTION_HPP diff --git a/Boost/boost/random/gamma_distribution.hpp b/Boost/boost/random/gamma_distribution.hpp new file mode 100644 index 000000000..c211286ee --- /dev/null +++ b/Boost/boost/random/gamma_distribution.hpp @@ -0,0 +1,143 @@ +/* boost random/gamma_distribution.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: gamma_distribution.hpp 60755 2010-03-22 00:45:06Z steven_watanabe $ + * + */ + +#ifndef BOOST_RANDOM_GAMMA_DISTRIBUTION_HPP +#define BOOST_RANDOM_GAMMA_DISTRIBUTION_HPP + +#include +#include +#include +#include +#include +#include + +namespace boost { + +// The algorithm is taken from Knuth + +/** + * The gamma distribution is a continuous distribution with a single + * parameter alpha. + * + * It has \f$p(x) = x^{\alpha-1}\frac{e^{-x}}{\Gamma(\alpha)}\f$. + */ +template +class gamma_distribution +{ +public: + typedef RealType input_type; + typedef RealType result_type; + +#ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS + BOOST_STATIC_ASSERT(!std::numeric_limits::is_integer); +#endif + + explicit gamma_distribution(const result_type& alpha_arg = result_type(1)) + : _exp(result_type(1)), _alpha(alpha_arg) + { + assert(_alpha > result_type(0)); + init(); + } + + // compiler-generated copy ctor and assignment operator are fine + + RealType alpha() const { return _alpha; } + + void reset() { _exp.reset(); } + + template + result_type operator()(Engine& eng) + { +#ifndef BOOST_NO_STDC_NAMESPACE + // allow for Koenig lookup + using std::tan; using std::sqrt; using std::exp; using std::log; + using std::pow; +#endif + if(_alpha == result_type(1)) { + return _exp(eng); + } else if(_alpha > result_type(1)) { + // Can we have a boost::mathconst please? + const result_type pi = result_type(3.14159265358979323846); + for(;;) { + result_type y = tan(pi * eng()); + result_type x = sqrt(result_type(2)*_alpha-result_type(1))*y + + _alpha-result_type(1); + if(x <= result_type(0)) + continue; + if(eng() > + (result_type(1)+y*y) * exp((_alpha-result_type(1)) + *log(x/(_alpha-result_type(1))) + - sqrt(result_type(2)*_alpha + -result_type(1))*y)) + continue; + return x; + } + } else /* alpha < 1.0 */ { + for(;;) { + result_type u = eng(); + result_type y = _exp(eng); + result_type x, q; + if(u < _p) { + x = exp(-y/_alpha); + q = _p*exp(-x); + } else { + x = result_type(1)+y; + q = _p + (result_type(1)-_p) * pow(x, _alpha-result_type(1)); + } + if(u >= q) + continue; + return x; + } + } + } + +#ifndef BOOST_RANDOM_NO_STREAM_OPERATORS + template + friend std::basic_ostream& + operator<<(std::basic_ostream& os, const gamma_distribution& gd) + { + os << gd._alpha; + return os; + } + + template + friend std::basic_istream& + operator>>(std::basic_istream& is, gamma_distribution& gd) + { + is >> std::ws >> gd._alpha; + gd.init(); + return is; + } +#endif + +private: + /// \cond hide_private_members + void init() + { +#ifndef BOOST_NO_STDC_NAMESPACE + // allow for Koenig lookup + using std::exp; +#endif + _p = exp(result_type(1)) / (_alpha + exp(result_type(1))); + } + /// \endcond + + exponential_distribution _exp; + result_type _alpha; + // some data precomputed from the parameters + result_type _p; +}; + +} // namespace boost + +#endif // BOOST_RANDOM_GAMMA_DISTRIBUTION_HPP diff --git a/Boost/boost/random/geometric_distribution.hpp b/Boost/boost/random/geometric_distribution.hpp new file mode 100644 index 000000000..6f34287fd --- /dev/null +++ b/Boost/boost/random/geometric_distribution.hpp @@ -0,0 +1,118 @@ +/* boost random/geometric_distribution.hpp header file + * + * Copyright Jens Maurer 2000-2001 + * 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: geometric_distribution.hpp 60755 2010-03-22 00:45:06Z steven_watanabe $ + * + * Revision history + * 2001-02-18 moved to individual header files + */ + +#ifndef BOOST_RANDOM_GEOMETRIC_DISTRIBUTION_HPP +#define BOOST_RANDOM_GEOMETRIC_DISTRIBUTION_HPP + +#include // std::log +#include +#include +#include +#include + +namespace boost { + +#if defined(__GNUC__) && (__GNUC__ < 3) +// Special gcc workaround: gcc 2.95.x ignores using-declarations +// in template classes (confirmed by gcc author Martin v. Loewis) + using std::log; +#endif + +/** + * An instantiation of the class template @c geometric_distribution models + * a \random_distribution. The distribution produces positive + * integers which are the number of bernoulli trials + * with probability @c p required to get one that fails. + * + * For the geometric distribution, \f$p(i) = (1-p) p^{i-1}\f$. + */ +template +class geometric_distribution +{ +public: + typedef RealType input_type; + typedef IntType result_type; + + /** + * Contructs a new geometric_distribution with the paramter @c p. + * + * Requires: 0 < p < 1 + */ + explicit geometric_distribution(const RealType& p = RealType(0.5)) + : _p(p) + { + assert(RealType(0) < _p && _p < RealType(1)); + init(); + } + + // compiler-generated copy ctor and assignment operator are fine + + /** + * Returns: the distribution parameter @c p + */ + RealType p() const { return _p; } + void reset() { } + + template + result_type operator()(Engine& eng) + { +#ifndef BOOST_NO_STDC_NAMESPACE + using std::log; + using std::floor; +#endif + return IntType(floor(log(RealType(1)-eng()) / _log_p)) + IntType(1); + } + +#ifndef BOOST_RANDOM_NO_STREAM_OPERATORS + template + friend std::basic_ostream& + operator<<(std::basic_ostream& os, const geometric_distribution& gd) + { + os << gd._p; + return os; + } + + template + friend std::basic_istream& + operator>>(std::basic_istream& is, geometric_distribution& gd) + { + is >> std::ws >> gd._p; + gd.init(); + return is; + } +#endif + +private: + + /// \cond hide_private_functions + + void init() + { +#ifndef BOOST_NO_STDC_NAMESPACE + using std::log; +#endif + _log_p = log(_p); + } + + /// \endcond + + RealType _p; + RealType _log_p; +}; + +} // namespace boost + +#endif // BOOST_RANDOM_GEOMETRIC_DISTRIBUTION_HPP + diff --git a/Boost/boost/random/inversive_congruential.hpp b/Boost/boost/random/inversive_congruential.hpp new file mode 100644 index 000000000..c901ff7e2 --- /dev/null +++ b/Boost/boost/random/inversive_congruential.hpp @@ -0,0 +1,173 @@ +/* boost random/inversive_congruential.hpp header file + * + * Copyright Jens Maurer 2000-2001 + * 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: inversive_congruential.hpp 60755 2010-03-22 00:45:06Z steven_watanabe $ + * + * Revision history + * 2001-02-18 moved to individual header files + */ + +#ifndef BOOST_RANDOM_INVERSIVE_CONGRUENTIAL_HPP +#define BOOST_RANDOM_INVERSIVE_CONGRUENTIAL_HPP + +#include +#include +#include +#include +#include +#include +#include + +namespace boost { +namespace random { + +// Eichenauer and Lehn 1986 +/** + * Instantiations of class template @c inversive_congruential model a + * \pseudo_random_number_generator. It uses the inversive congruential + * algorithm (ICG) described in + * + * @blockquote + * "Inversive pseudorandom number generators: concepts, results and links", + * Peter Hellekalek, In: "Proceedings of the 1995 Winter Simulation + * Conference", C. Alexopoulos, K. Kang, W.R. Lilegdon, and D. Goldsman + * (editors), 1995, pp. 255-262. ftp://random.mat.sbg.ac.at/pub/data/wsc95.ps + * @endblockquote + * + * The output sequence is defined by x(n+1) = (a*inv(x(n)) - b) (mod p), + * where x(0), a, b, and the prime number p are parameters of the generator. + * The expression inv(k) denotes the multiplicative inverse of k in the + * field of integer numbers modulo p, with inv(0) := 0. + * + * The template parameter IntType shall denote a signed integral type large + * enough to hold p; a, b, and p are the parameters of the generators. The + * template parameter val is the validation value checked by validation. + * + * @xmlnote + * The implementation currently uses the Euclidian Algorithm to compute + * the multiplicative inverse. Therefore, the inversive generators are about + * 10-20 times slower than the others (see section"performance"). However, + * the paper talks of only 3x slowdown, so the Euclidian Algorithm is probably + * not optimal for calculating the multiplicative inverse. + * @endxmlnote + */ +template +class inversive_congruential +{ +public: + typedef IntType result_type; +#ifndef BOOST_NO_INCLASS_MEMBER_INITIALIZATION + static const bool has_fixed_range = true; + static const result_type min_value = (b == 0 ? 1 : 0); + static const result_type max_value = p-1; +#else + BOOST_STATIC_CONSTANT(bool, has_fixed_range = false); +#endif + BOOST_STATIC_CONSTANT(result_type, multiplier = a); + BOOST_STATIC_CONSTANT(result_type, increment = b); + BOOST_STATIC_CONSTANT(result_type, modulus = p); + + result_type min BOOST_PREVENT_MACRO_SUBSTITUTION () const { return b == 0 ? 1 : 0; } + result_type max BOOST_PREVENT_MACRO_SUBSTITUTION () const { return p-1; } + + /** + * Constructs an inversive_congruential generator with + * @c y0 as the initial state. + */ + explicit inversive_congruential(IntType y0 = 1) : value(y0) + { + BOOST_STATIC_ASSERT(b >= 0); + BOOST_STATIC_ASSERT(p > 1); + BOOST_STATIC_ASSERT(a >= 1); + if(b == 0) + assert(y0 > 0); + } + template inversive_congruential(It& first, It last) + { seed(first, last); } + + /** Changes the current state to y0. */ + void seed(IntType y0 = 1) { value = y0; if(b == 0) assert(y0 > 0); } + template void seed(It& first, It last) + { + if(first == last) + throw std::invalid_argument("inversive_congruential::seed"); + value = *first++; + } + IntType operator()() + { + typedef const_mod do_mod; + value = do_mod::mult_add(a, do_mod::invert(value), b); + return value; + } + + static bool validation(result_type x) { return val == x; } + +#ifndef BOOST_NO_OPERATORS_IN_NAMESPACE + +#ifndef BOOST_RANDOM_NO_STREAM_OPERATORS + template + friend std::basic_ostream& + operator<<(std::basic_ostream& os, inversive_congruential x) + { os << x.value; return os; } + + template + friend std::basic_istream& + operator>>(std::basic_istream& is, inversive_congruential& x) + { is >> x.value; return is; } +#endif + + friend bool operator==(inversive_congruential x, inversive_congruential y) + { return x.value == y.value; } + friend bool operator!=(inversive_congruential x, inversive_congruential y) + { return !(x == y); } +#else + // Use a member function; Streamable concept not supported. + bool operator==(inversive_congruential rhs) const + { return value == rhs.value; } + bool operator!=(inversive_congruential rhs) const + { return !(*this == rhs); } +#endif +private: + IntType value; +}; + +#ifndef BOOST_NO_INCLASS_MEMBER_INITIALIZATION +// A definition is required even for integral static constants +template +const bool inversive_congruential::has_fixed_range; +template +const typename inversive_congruential::result_type inversive_congruential::min_value; +template +const typename inversive_congruential::result_type inversive_congruential::max_value; +template +const typename inversive_congruential::result_type inversive_congruential::multiplier; +template +const typename inversive_congruential::result_type inversive_congruential::increment; +template +const typename inversive_congruential::result_type inversive_congruential::modulus; +#endif + +} // namespace random + +/** + * The specialization hellekalek1995 was suggested in + * + * @blockquote + * "Inversive pseudorandom number generators: concepts, results and links", + * Peter Hellekalek, In: "Proceedings of the 1995 Winter Simulation + * Conference", C. Alexopoulos, K. Kang, W.R. Lilegdon, and D. Goldsman + * (editors), 1995, pp. 255-262. ftp://random.mat.sbg.ac.at/pub/data/wsc95.ps + * @endblockquote + */ +typedef random::inversive_congruential hellekalek1995; + +} // namespace boost + +#endif // BOOST_RANDOM_INVERSIVE_CONGRUENTIAL_HPP diff --git a/Boost/boost/random/lagged_fibonacci.hpp b/Boost/boost/random/lagged_fibonacci.hpp new file mode 100644 index 000000000..50db47d88 --- /dev/null +++ b/Boost/boost/random/lagged_fibonacci.hpp @@ -0,0 +1,605 @@ +/* boost random/lagged_fibonacci.hpp header file + * + * Copyright Jens Maurer 2000-2001 + * 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: lagged_fibonacci.hpp 60755 2010-03-22 00:45:06Z steven_watanabe $ + * + * Revision history + * 2001-02-18 moved to individual header files + */ + +#ifndef BOOST_RANDOM_LAGGED_FIBONACCI_HPP +#define BOOST_RANDOM_LAGGED_FIBONACCI_HPP + +#include +#include +#include // std::max +#include +#include // std::pow +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost { +namespace random { + +#if BOOST_WORKAROUND(_MSC_FULL_VER, BOOST_TESTED_AT(13102292)) && BOOST_MSVC > 1300 +# define BOOST_RANDOM_EXTRACT_LF +#endif + +#if defined(__APPLE_CC__) && defined(__GNUC__) && (__GNUC__ == 3) && (__GNUC_MINOR__ <= 3) +# define BOOST_RANDOM_EXTRACT_LF +#endif + +# ifdef BOOST_RANDOM_EXTRACT_LF +namespace detail +{ + template + IStream& + extract_lagged_fibonacci_01( + IStream& is + , F const& f + , unsigned int& i + , RealType* x + , RealType modulus) + { + is >> i >> std::ws; + for(unsigned int i = 0; i < f.long_lag; ++i) + { + RealType value; + is >> value >> std::ws; + x[i] = value / modulus; + } + return is; + } + + template + IStream& + extract_lagged_fibonacci( + IStream& is + , F const& f + , unsigned int& i + , UIntType* x) + { + is >> i >> std::ws; + for(unsigned int i = 0; i < f.long_lag; ++i) + is >> x[i] >> std::ws; + return is; + } +} +# endif + +/** + * Instantiations of class template \lagged_fibonacci model a + * \pseudo_random_number_generator. It uses a lagged Fibonacci + * algorithm with two lags @c p and @c q: + * x(i) = x(i-p) + x(i-q) (mod 2w) with p > q. + */ +template +class lagged_fibonacci +{ +public: + typedef UIntType result_type; + BOOST_STATIC_CONSTANT(bool, has_fixed_range = false); + BOOST_STATIC_CONSTANT(int, word_size = w); + BOOST_STATIC_CONSTANT(unsigned int, long_lag = p); + BOOST_STATIC_CONSTANT(unsigned int, short_lag = q); + + /** + * Returns: the smallest value that the generator can produce + */ + result_type min BOOST_PREVENT_MACRO_SUBSTITUTION () const { return 0; } + /** + * Returns: the largest value that the generator can produce + */ + result_type max BOOST_PREVENT_MACRO_SUBSTITUTION () const { return wordmask; } + + /** + * Creates a new @c lagged_fibonacci generator and calls @c seed() + */ + lagged_fibonacci() { init_wordmask(); seed(); } + /** + * Creates a new @c lagged_fibonacci generator and calls @c seed(value) + */ + explicit lagged_fibonacci(uint32_t value) { init_wordmask(); seed(value); } + /** + * Creates a new @c lagged_fibonacci generator and calls @c seed(first, last) + */ + template lagged_fibonacci(It& first, It last) + { init_wordmask(); seed(first, last); } + // compiler-generated copy ctor and assignment operator are fine + +private: + /// \cond hide_private_members + void init_wordmask() + { + wordmask = 0; + for(int j = 0; j < w; ++j) + wordmask |= (1u << j); + } + /// \endcond + +public: + /** + * Sets the state of the generator to values produced by + * a \minstd_rand generator. + */ + void seed(uint32_t value = 331u) + { + minstd_rand0 gen(value); + for(unsigned int j = 0; j < long_lag; ++j) + x[j] = gen() & wordmask; + i = long_lag; + } + + /** + * Sets the state of the generator to values from the iterator + * range [first, last). If there are not enough elements in the + * range [first, last) throws @c std::invalid_argument. + */ + template + void seed(It& first, It last) + { + // word size could be smaller than the seed values + unsigned int j; + for(j = 0; j < long_lag && first != last; ++j, ++first) + x[j] = *first & wordmask; + i = long_lag; + if(first == last && j < long_lag) + throw std::invalid_argument("lagged_fibonacci::seed"); + } + + /** + * Returns: the next value of the generator + */ + result_type operator()() + { + if(i >= long_lag) + fill(); + return x[i++]; + } + + static bool validation(result_type x) + { + return x == val; + } + +#ifndef BOOST_NO_OPERATORS_IN_NAMESPACE + +#ifndef BOOST_RANDOM_NO_STREAM_OPERATORS + template + friend std::basic_ostream& + operator<<(std::basic_ostream& os, const lagged_fibonacci& f) + { + os << f.i << " "; + for(unsigned int i = 0; i < f.long_lag; ++i) + os << f.x[i] << " "; + return os; + } + + template + friend std::basic_istream& + operator>>(std::basic_istream& is, lagged_fibonacci& f) + { +# ifdef BOOST_RANDOM_EXTRACT_LF + return detail::extract_lagged_fibonacci(is, f, f.i, f.x); +# else + is >> f.i >> std::ws; + for(unsigned int i = 0; i < f.long_lag; ++i) + is >> f.x[i] >> std::ws; + return is; +# endif + } +#endif + + friend bool operator==(const lagged_fibonacci& x, const lagged_fibonacci& y) + { return x.i == y.i && std::equal(x.x, x.x+long_lag, y.x); } + friend bool operator!=(const lagged_fibonacci& x, + const lagged_fibonacci& y) + { return !(x == y); } +#else + // Use a member function; Streamable concept not supported. + bool operator==(const lagged_fibonacci& rhs) const + { return i == rhs.i && std::equal(x, x+long_lag, rhs.x); } + bool operator!=(const lagged_fibonacci& rhs) const + { return !(*this == rhs); } +#endif + +private: + /// \cond hide_private_members + void fill(); + /// \endcond + + UIntType wordmask; + unsigned int i; + UIntType x[long_lag]; +}; + +#ifndef BOOST_NO_INCLASS_MEMBER_INITIALIZATION +// A definition is required even for integral static constants +template +const bool lagged_fibonacci::has_fixed_range; +template +const unsigned int lagged_fibonacci::long_lag; +template +const unsigned int lagged_fibonacci::short_lag; +#endif + +/// \cond hide_private_members + +template +void lagged_fibonacci::fill() +{ + // two loops to avoid costly modulo operations + { // extra scope for MSVC brokenness w.r.t. for scope + for(unsigned int j = 0; j < short_lag; ++j) + x[j] = (x[j] + x[j+(long_lag-short_lag)]) & wordmask; + } + for(unsigned int j = short_lag; j < long_lag; ++j) + x[j] = (x[j] + x[j-short_lag]) & wordmask; + i = 0; +} + + + +// lagged Fibonacci generator for the range [0..1) +// contributed by Matthias Troyer +// for p=55, q=24 originally by G. J. Mitchell and D. P. Moore 1958 + +template +struct fibonacci_validation +{ + BOOST_STATIC_CONSTANT(bool, is_specialized = false); + static T value() { return 0; } + static T tolerance() { return 0; } +}; + +#ifndef BOOST_NO_INCLASS_MEMBER_INITIALIZATION +// A definition is required even for integral static constants +template +const bool fibonacci_validation::is_specialized; +#endif + +#define BOOST_RANDOM_FIBONACCI_VAL(T,P,Q,V,E) \ +template<> \ +struct fibonacci_validation \ +{ \ + BOOST_STATIC_CONSTANT(bool, is_specialized = true); \ + static T value() { return V; } \ + static T tolerance() \ +{ return (std::max)(E, static_cast(5*std::numeric_limits::epsilon())); } \ +}; +// (The extra static_cast in the std::max call above is actually +// unnecessary except for HP aCC 1.30, which claims that +// numeric_limits::epsilon() doesn't actually return a double.) + +BOOST_RANDOM_FIBONACCI_VAL(double, 607, 273, 0.4293817707235914, 1e-14) +BOOST_RANDOM_FIBONACCI_VAL(double, 1279, 418, 0.9421630240437659, 1e-14) +BOOST_RANDOM_FIBONACCI_VAL(double, 2281, 1252, 0.1768114046909004, 1e-14) +BOOST_RANDOM_FIBONACCI_VAL(double, 3217, 576, 0.1956232694868209, 1e-14) +BOOST_RANDOM_FIBONACCI_VAL(double, 4423, 2098, 0.9499762202147172, 1e-14) +BOOST_RANDOM_FIBONACCI_VAL(double, 9689, 5502, 0.05737836943695162, 1e-14) +BOOST_RANDOM_FIBONACCI_VAL(double, 19937, 9842, 0.5076528587449834, 1e-14) +BOOST_RANDOM_FIBONACCI_VAL(double, 23209, 13470, 0.5414473810619185, 1e-14) +BOOST_RANDOM_FIBONACCI_VAL(double, 44497,21034, 0.254135073399297, 1e-14) + +#undef BOOST_RANDOM_FIBONACCI_VAL + +/// \endcond + +/** + * Instantiations of class template @c lagged_fibonacci_01 model a + * \pseudo_random_number_generator. It uses a lagged Fibonacci + * algorithm with two lags @c p and @c q, evaluated in floating-point + * arithmetic: x(i) = x(i-p) + x(i-q) (mod 1) with p > q. See + * + * @blockquote + * "Uniform random number generators for supercomputers", Richard Brent, + * Proc. of Fifth Australian Supercomputer Conference, Melbourne, + * Dec. 1992, pp. 704-706. + * @endblockquote + * + * @xmlnote + * The quality of the generator crucially depends on the choice + * of the parameters. User code should employ one of the sensibly + * parameterized generators such as \lagged_fibonacci607 instead. + * @endxmlnote + * + * The generator requires considerable amounts of memory for the storage + * of its state array. For example, \lagged_fibonacci607 requires about + * 4856 bytes and \lagged_fibonacci44497 requires about 350 KBytes. + */ +template +class lagged_fibonacci_01 +{ +public: + typedef RealType result_type; + BOOST_STATIC_CONSTANT(bool, has_fixed_range = false); + BOOST_STATIC_CONSTANT(int, word_size = w); + BOOST_STATIC_CONSTANT(unsigned int, long_lag = p); + BOOST_STATIC_CONSTANT(unsigned int, short_lag = q); + + /** Constructs a @c lagged_fibonacci_01 generator and calls @c seed(). */ + lagged_fibonacci_01() { init_modulus(); seed(); } + /** Constructs a @c lagged_fibonacci_01 generator and calls @c seed(value). */ + BOOST_RANDOM_DETAIL_ARITHMETIC_CONSTRUCTOR(lagged_fibonacci_01, uint32_t, value) + { init_modulus(); seed(value); } + /** Constructs a @c lagged_fibonacci_01 generator and calls @c seed(gen). */ + BOOST_RANDOM_DETAIL_GENERATOR_CONSTRUCTOR(lagged_fibonacci_01, Generator, gen) + { init_modulus(); seed(gen); } + template lagged_fibonacci_01(It& first, It last) + { init_modulus(); seed(first, last); } + // compiler-generated copy ctor and assignment operator are fine + +private: + /// \cond hide_private_members + void init_modulus() + { +#ifndef BOOST_NO_STDC_NAMESPACE + // allow for Koenig lookup + using std::pow; +#endif + _modulus = pow(RealType(2), word_size); + } + /// \endcond + +public: + /** Calls seed(331u). */ + void seed() { seed(331u); } + /** + * Constructs a \minstd_rand0 generator with the constructor parameter + * value and calls seed with it. Distinct seeds in the range + * [1, 2147483647) will produce generators with different states. Other + * seeds will be equivalent to some seed within this range. See + * \linear_congruential for details. + */ + BOOST_RANDOM_DETAIL_ARITHMETIC_SEED(lagged_fibonacci_01, uint32_t, value) + { + minstd_rand0 intgen(value); + seed(intgen); + } + + /** + * Sets the state of this @c lagged_fibonacci_01 to the values returned + * by p invocations of \uniform_01\()(gen). + * + * Complexity: Exactly p invocations of gen. + */ + BOOST_RANDOM_DETAIL_GENERATOR_SEED(lagged_fibonacci, Generator, gen) + { + // use pass-by-reference, but wrap argument in pass_through_engine + typedef detail::pass_through_engine ref_gen; + uniform_01 gen01 = + uniform_01(ref_gen(gen)); + // I could have used std::generate_n, but it takes "gen" by value + for(unsigned int j = 0; j < long_lag; ++j) + x[j] = gen01(); + i = long_lag; + } + + template + void seed(It& first, It last) + { +#ifndef BOOST_NO_STDC_NAMESPACE + // allow for Koenig lookup + using std::fmod; + using std::pow; +#endif + unsigned long mask = ~((~0u) << (w%32)); // now lowest w bits set + RealType two32 = pow(RealType(2), 32); + unsigned int j; + for(j = 0; j < long_lag && first != last; ++j) { + x[j] = RealType(0); + for(int k = 0; k < w/32 && first != last; ++k, ++first) + x[j] += *first / pow(two32,k+1); + if(first != last && mask != 0) { + x[j] += fmod((*first & mask) / _modulus, RealType(1)); + ++first; + } + } + i = long_lag; + if(first == last && j < long_lag) + throw std::invalid_argument("lagged_fibonacci_01::seed"); + } + + result_type min BOOST_PREVENT_MACRO_SUBSTITUTION () const { return result_type(0); } + result_type max BOOST_PREVENT_MACRO_SUBSTITUTION () const { return result_type(1); } + + result_type operator()() + { + if(i >= long_lag) + fill(); + return x[i++]; + } + + static bool validation(result_type x) + { + result_type v = fibonacci_validation::value(); + result_type epsilon = fibonacci_validation::tolerance(); + // std::abs is a source of trouble: sometimes, it's not overloaded + // for double, plus the usual namespace std noncompliance -> avoid it + // using std::abs; + // return abs(x - v) < 5 * epsilon + return x > v - epsilon && x < v + epsilon; + } + +#ifndef BOOST_NO_OPERATORS_IN_NAMESPACE + +#ifndef BOOST_RANDOM_NO_STREAM_OPERATORS + template + friend std::basic_ostream& + operator<<(std::basic_ostream& os, const lagged_fibonacci_01&f) + { +#ifndef BOOST_NO_STDC_NAMESPACE + // allow for Koenig lookup + using std::pow; +#endif + os << f.i << " "; + std::ios_base::fmtflags oldflags = os.flags(os.dec | os.fixed | os.left); + for(unsigned int i = 0; i < f.long_lag; ++i) + os << f.x[i] * f._modulus << " "; + os.flags(oldflags); + return os; + } + + template + friend std::basic_istream& + operator>>(std::basic_istream& is, lagged_fibonacci_01& f) + { +# ifdef BOOST_RANDOM_EXTRACT_LF + return detail::extract_lagged_fibonacci_01(is, f, f.i, f.x, f._modulus); +# else + is >> f.i >> std::ws; + for(unsigned int i = 0; i < f.long_lag; ++i) { + typename lagged_fibonacci_01::result_type value; + is >> value >> std::ws; + f.x[i] = value / f._modulus; + } + return is; +# endif + } +#endif + + friend bool operator==(const lagged_fibonacci_01& x, + const lagged_fibonacci_01& y) + { return x.i == y.i && std::equal(x.x, x.x+long_lag, y.x); } + friend bool operator!=(const lagged_fibonacci_01& x, + const lagged_fibonacci_01& y) + { return !(x == y); } +#else + // Use a member function; Streamable concept not supported. + bool operator==(const lagged_fibonacci_01& rhs) const + { return i == rhs.i && std::equal(x, x+long_lag, rhs.x); } + bool operator!=(const lagged_fibonacci_01& rhs) const + { return !(*this == rhs); } +#endif + +private: + /// \cond hide_private_members + void fill(); + /// \endcond + unsigned int i; + RealType x[long_lag]; + RealType _modulus; +}; + +#ifndef BOOST_NO_INCLASS_MEMBER_INITIALIZATION +// A definition is required even for integral static constants +template +const bool lagged_fibonacci_01::has_fixed_range; +template +const unsigned int lagged_fibonacci_01::long_lag; +template +const unsigned int lagged_fibonacci_01::short_lag; +template +const int lagged_fibonacci_01::word_size; + +#endif + +/// \cond hide_private_members +template +void lagged_fibonacci_01::fill() +{ + // two loops to avoid costly modulo operations + { // extra scope for MSVC brokenness w.r.t. for scope + for(unsigned int j = 0; j < short_lag; ++j) { + RealType t = x[j] + x[j+(long_lag-short_lag)]; + if(t >= RealType(1)) + t -= RealType(1); + x[j] = t; + } + } + for(unsigned int j = short_lag; j < long_lag; ++j) { + RealType t = x[j] + x[j-short_lag]; + if(t >= RealType(1)) + t -= RealType(1); + x[j] = t; + } + i = 0; +} +/// \endcond + +} // namespace random + +#ifdef BOOST_RANDOM_DOXYGEN +namespace detail { +/** + * The specializations lagged_fibonacci607 ... lagged_fibonacci44497 + * use well tested lags. + * + * See + * + * @blockquote + * "On the Periods of Generalized Fibonacci Recurrences", Richard P. Brent + * Computer Sciences Laboratory Australian National University, December 1992 + * @endblockquote + * + * The lags used here can be found in + * + * @blockquote + * "Uniform random number generators for supercomputers", Richard Brent, + * Proc. of Fifth Australian Supercomputer Conference, Melbourne, + * Dec. 1992, pp. 704-706. + * @endblockquote + */ +struct lagged_fibonacci_doc {}; +} +#endif + +/** + * @copydoc boost::detail::lagged_fibonacci_doc + */ +typedef random::lagged_fibonacci_01 lagged_fibonacci607; +/** + * @copydoc boost::detail::lagged_fibonacci_doc + */ +typedef random::lagged_fibonacci_01 lagged_fibonacci1279; +/** + * @copydoc boost::detail::lagged_fibonacci_doc + */ +typedef random::lagged_fibonacci_01 lagged_fibonacci2281; +/** + * @copydoc boost::detail::lagged_fibonacci_doc + */ +typedef random::lagged_fibonacci_01 lagged_fibonacci3217; +/** + * @copydoc boost::detail::lagged_fibonacci_doc + */ +typedef random::lagged_fibonacci_01 lagged_fibonacci4423; +/** + * @copydoc boost::detail::lagged_fibonacci_doc + */ +typedef random::lagged_fibonacci_01 lagged_fibonacci9689; +/** + * @copydoc boost::detail::lagged_fibonacci_doc + */ +typedef random::lagged_fibonacci_01 lagged_fibonacci19937; +/** + * @copydoc boost::detail::lagged_fibonacci_doc + */ +typedef random::lagged_fibonacci_01 lagged_fibonacci23209; +/** + * @copydoc boost::detail::lagged_fibonacci_doc + */ +typedef random::lagged_fibonacci_01 lagged_fibonacci44497; + + +// It is possible to partially specialize uniform_01<> on lagged_fibonacci_01<> +// to help the compiler generate efficient code. For GCC, this seems useless, +// because GCC optimizes (x-0)/(1-0) to (x-0). This is good enough for now. + +} // namespace boost + +#endif // BOOST_RANDOM_LAGGED_FIBONACCI_HPP diff --git a/Boost/boost/random/linear_congruential.hpp b/Boost/boost/random/linear_congruential.hpp new file mode 100644 index 000000000..d7277f156 --- /dev/null +++ b/Boost/boost/random/linear_congruential.hpp @@ -0,0 +1,403 @@ +/* boost random/linear_congruential.hpp header file + * + * Copyright Jens Maurer 2000-2001 + * 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: linear_congruential.hpp 60755 2010-03-22 00:45:06Z steven_watanabe $ + * + * Revision history + * 2001-02-18 moved to individual header files + */ + +#ifndef BOOST_RANDOM_LINEAR_CONGRUENTIAL_HPP +#define BOOST_RANDOM_LINEAR_CONGRUENTIAL_HPP + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +namespace boost { +namespace random { + +/** + * Instantiations of class template linear_congruential model a + * \pseudo_random_number_generator. Linear congruential pseudo-random + * number generators are described in: + * + * "Mathematical methods in large-scale computing units", D. H. Lehmer, + * Proc. 2nd Symposium on Large-Scale Digital Calculating Machines, + * Harvard University Press, 1951, pp. 141-146 + * + * Let x(n) denote the sequence of numbers returned by some pseudo-random + * number generator. Then for the linear congruential generator, + * x(n+1) := (a * x(n) + c) mod m. Parameters for the generator are + * x(0), a, c, m. The template parameter IntType shall denote an integral + * type. It must be large enough to hold values a, c, and m. The template + * parameters a and c must be smaller than m. + * + * Note: The quality of the generator crucially depends on the choice of + * the parameters. User code should use one of the sensibly parameterized + * generators such as minstd_rand instead. + */ +template +class linear_congruential +{ +public: + typedef IntType result_type; +#ifndef BOOST_NO_INCLASS_MEMBER_INITIALIZATION + static const bool has_fixed_range = true; + static const result_type min_value = ( c == 0 ? 1 : 0 ); + static const result_type max_value = m-1; +#else + BOOST_STATIC_CONSTANT(bool, has_fixed_range = false); +#endif + BOOST_STATIC_CONSTANT(IntType, multiplier = a); + BOOST_STATIC_CONSTANT(IntType, increment = c); + BOOST_STATIC_CONSTANT(IntType, modulus = m); + + // MSVC 6 and possibly others crash when encountering complicated integral + // constant expressions. Avoid the check for now. + // BOOST_STATIC_ASSERT(m == 0 || a < m); + // BOOST_STATIC_ASSERT(m == 0 || c < m); + + /** + * Constructs a linear_congruential generator, seeding it with @c x0. + */ + explicit linear_congruential(IntType x0 = 1) + { + seed(x0); + + // MSVC fails BOOST_STATIC_ASSERT with std::numeric_limits at class scope +#ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS + BOOST_STATIC_ASSERT(std::numeric_limits::is_integer); +#endif + } + + /** + * Constructs a @c linear_congruential generator and seeds it + * with values taken from the itrator range [first, last) + * and adjusts first to point to the element after the last one + * used. If there are not enough elements, throws @c std::invalid_argument. + * + * first and last must be input iterators. + */ + template + linear_congruential(It& first, It last) + { + seed(first, last); + } + + // compiler-generated copy constructor and assignment operator are fine + + /** + * If c mod m is zero and x0 mod m is zero, changes the current value of + * the generator to 1. Otherwise, changes it to x0 mod m. If c is zero, + * distinct seeds in the range [1,m) will leave the generator in distinct + * states. If c is not zero, the range is [0,m). + */ + void seed(IntType x0 = 1) + { + // wrap _x if it doesn't fit in the destination + if(modulus == 0) { + _x = x0; + } else { + _x = x0 % modulus; + } + // handle negative seeds + if(_x <= 0 && _x != 0) { + _x += modulus; + } + // adjust to the correct range + if(increment == 0 && _x == 0) { + _x = 1; + } + assert(_x >= (min)()); + assert(_x <= (max)()); + } + + /** + * seeds a @c linear_congruential generator with values taken + * from the itrator range [first, last) and adjusts @c first to + * point to the element after the last one used. If there are + * not enough elements, throws @c std::invalid_argument. + * + * @c first and @c last must be input iterators. + */ + template + void seed(It& first, It last) + { + if(first == last) + throw std::invalid_argument("linear_congruential::seed"); + seed(*first++); + } + + /** + * Returns the smallest value that the @c linear_congruential generator + * can produce. + */ + result_type min BOOST_PREVENT_MACRO_SUBSTITUTION () const { return c == 0 ? 1 : 0; } + /** + * Returns the largest value that the @c linear_congruential generator + * can produce. + */ + result_type max BOOST_PREVENT_MACRO_SUBSTITUTION () const { return modulus-1; } + + /** Returns the next value of the @c linear_congruential generator. */ + IntType operator()() + { + _x = const_mod::mult_add(a, _x, c); + return _x; + } + + static bool validation(IntType x) { return val == x; } + +#ifdef BOOST_NO_OPERATORS_IN_NAMESPACE + + // Use a member function; Streamable concept not supported. + bool operator==(const linear_congruential& rhs) const + { return _x == rhs._x; } + bool operator!=(const linear_congruential& rhs) const + { return !(*this == rhs); } + +#else + friend bool operator==(const linear_congruential& x, + const linear_congruential& y) + { return x._x == y._x; } + friend bool operator!=(const linear_congruential& x, + const linear_congruential& y) + { return !(x == y); } + +#if !defined(BOOST_RANDOM_NO_STREAM_OPERATORS) && !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x551)) + template + friend std::basic_ostream& + operator<<(std::basic_ostream& os, + const linear_congruential& lcg) + { + return os << lcg._x; + } + + template + friend std::basic_istream& + operator>>(std::basic_istream& is, + linear_congruential& lcg) + { + return is >> lcg._x; + } + +private: +#endif +#endif + + IntType _x; +}; + +// probably needs the "no native streams" caveat for STLPort +#if !defined(__SGI_STL_PORT) && BOOST_WORKAROUND(__GNUC__, == 2) +template +std::ostream& +operator<<(std::ostream& os, + const linear_congruential& lcg) +{ + return os << lcg._x; +} + +template +std::istream& +operator>>(std::istream& is, + linear_congruential& lcg) +{ + return is >> lcg._x; +} +#elif defined(BOOST_RANDOM_NO_STREAM_OPERATORS) || BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x551)) +template +std::basic_ostream& +operator<<(std::basic_ostream& os, + const linear_congruential& lcg) +{ + return os << lcg._x; +} + +template +std::basic_istream& +operator>>(std::basic_istream& is, + linear_congruential& lcg) +{ + return is >> lcg._x; +} +#endif + +#ifndef BOOST_NO_INCLASS_MEMBER_INITIALIZATION +// A definition is required even for integral static constants +template +const bool linear_congruential::has_fixed_range; +template +const typename linear_congruential::result_type linear_congruential::min_value; +template +const typename linear_congruential::result_type linear_congruential::max_value; +template +const IntType linear_congruential::modulus; +#endif + +} // namespace random + +// validation values from the publications +/** + * The specialization \minstd_rand0 was originally suggested in + * + * @blockquote + * A pseudo-random number generator for the System/360, P.A. Lewis, + * A.S. Goodman, J.M. Miller, IBM Systems Journal, Vol. 8, No. 2, + * 1969, pp. 136-146 + * @endblockquote + * + * It is examined more closely together with \minstd_rand in + * + * @blockquote + * "Random Number Generators: Good ones are hard to find", + * Stephen K. Park and Keith W. Miller, Communications of + * the ACM, Vol. 31, No. 10, October 1988, pp. 1192-1201 + * @endblockquote + */ +typedef random::linear_congruential minstd_rand0; + +/** The specialization \minstd_rand was suggested in + * + * @blockquote + * "Random Number Generators: Good ones are hard to find", + * Stephen K. Park and Keith W. Miller, Communications of + * the ACM, Vol. 31, No. 10, October 1988, pp. 1192-1201 + * @endblockquote + */ +typedef random::linear_congruential minstd_rand; + + +#if !defined(BOOST_NO_INT64_T) && !defined(BOOST_NO_INTEGRAL_INT64_T) +/** Class @c rand48 models a \pseudo_random_number_generator. It uses + * the linear congruential algorithm with the parameters a = 0x5DEECE66D, + * c = 0xB, m = 2**48. It delivers identical results to the @c lrand48() + * function available on some systems (assuming lcong48 has not been called). + * + * It is only available on systems where @c uint64_t is provided as an + * integral type, so that for example static in-class constants and/or + * enum definitions with large @c uint64_t numbers work. + */ +class rand48 +{ +public: + typedef int32_t result_type; +#ifndef BOOST_NO_INCLASS_MEMBER_INITIALIZATION + static const bool has_fixed_range = true; + static const int32_t min_value = 0; + static const int32_t max_value = integer_traits::const_max; +#else + enum { has_fixed_range = false }; +#endif + /** + * Returns the smallest value that the generator can produce + */ + int32_t min BOOST_PREVENT_MACRO_SUBSTITUTION () const { return 0; } + /** + * Returns the largest value that the generator can produce + */ + int32_t max BOOST_PREVENT_MACRO_SUBSTITUTION () const { return std::numeric_limits::max BOOST_PREVENT_MACRO_SUBSTITUTION (); } + +#ifdef BOOST_RANDOM_DOXYGEN + /** + * If T is an integral type smaller than int46_t, constructs + * a \rand48 generator with x(0) := (x0 << 16) | 0x330e. Otherwise + * constructs a \rand48 generator with x(0) = x0. + */ + template explicit rand48(T x0 = 1); +#else + rand48() : lcf(cnv(static_cast(1))) {} + template explicit rand48(T x0) : lcf(cnv(x0)) { } +#endif + template rand48(It& first, It last) : lcf(first, last) { } + + // compiler-generated copy ctor and assignment operator are fine + +#ifdef BOOST_RANDOM_DOXYGEN + /** + * If T is an integral type smaller than int46_t, changes + * the current value x(n) of the generator to (x0 << 16) | 0x330e. + * Otherwise changes the current value x(n) to x0. + */ + template void seed(T x0 = 1); +#else + void seed() { seed(static_cast(1)); } + template void seed(T x0) { lcf.seed(cnv(x0)); } +#endif + template void seed(It& first, It last) { lcf.seed(first,last); } + + /** + * Returns the next value of the generator. + */ + int32_t operator()() { return static_cast(lcf() >> 17); } + // by experiment from lrand48() + static bool validation(int32_t x) { return x == 1993516219; } + +#ifndef BOOST_NO_OPERATORS_IN_NAMESPACE + +#ifndef BOOST_RANDOM_NO_STREAM_OPERATORS + template + friend std::basic_ostream& + operator<<(std::basic_ostream& os, const rand48& r) + { os << r.lcf; return os; } + + template + friend std::basic_istream& + operator>>(std::basic_istream& is, rand48& r) + { is >> r.lcf; return is; } +#endif + + friend bool operator==(const rand48& x, const rand48& y) + { return x.lcf == y.lcf; } + friend bool operator!=(const rand48& x, const rand48& y) + { return !(x == y); } +#else + // Use a member function; Streamable concept not supported. + bool operator==(const rand48& rhs) const + { return lcf == rhs.lcf; } + bool operator!=(const rand48& rhs) const + { return !(*this == rhs); } +#endif +private: + /// \cond hide_private_members + random::linear_congruential lcf; + template + static uint64_t cnv(T x) + { + if(sizeof(T) < sizeof(uint64_t)) { + return (static_cast(x) << 16) | 0x330e; + } else { + return(static_cast(x)); + } + } + static uint64_t cnv(float x) { return(static_cast(x)); } + static uint64_t cnv(double x) { return(static_cast(x)); } + static uint64_t cnv(long double x) { return(static_cast(x)); } + /// \endcond +}; +#endif /* !BOOST_NO_INT64_T && !BOOST_NO_INTEGRAL_INT64_T */ + +} // namespace boost + +#include + +#endif // BOOST_RANDOM_LINEAR_CONGRUENTIAL_HPP diff --git a/Boost/boost/random/linear_feedback_shift.hpp b/Boost/boost/random/linear_feedback_shift.hpp new file mode 100644 index 000000000..6b3a87826 --- /dev/null +++ b/Boost/boost/random/linear_feedback_shift.hpp @@ -0,0 +1,160 @@ +/* boost random/tausworthe.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: linear_feedback_shift.hpp 60755 2010-03-22 00:45:06Z steven_watanabe $ + * + */ + +#ifndef BOOST_RANDOM_LINEAR_FEEDBACK_SHIFT_HPP +#define BOOST_RANDOM_LINEAR_FEEDBACK_SHIFT_HPP + +#include +#include +#include +#include +#include +#include +#include + +namespace boost { +namespace random { + +/** + * Instatiation of @c linear_feedback_shift model a + * \pseudo_random_number_generator. It was originally + * proposed in + * + * @blockquote + * "Random numbers generated by linear recurrence modulo two.", + * Tausworthe, R. C.(1965), Mathematics of Computation 19, 201-209. + * @endblockquote + */ +template +class linear_feedback_shift +{ +public: + typedef UIntType result_type; + // avoid the warning trouble when using (1< 0); + // BOOST_STATIC_ASSERT(q > 0); + // BOOST_STATIC_ASSERT(k < w); + // BOOST_STATIC_ASSERT(0 < 2*q && 2*q < k); + // BOOST_STATIC_ASSERT(0 < s && s <= k-q); + + explicit linear_feedback_shift(UIntType s0 = 341) : wordmask(0) + { + // MSVC fails BOOST_STATIC_ASSERT with std::numeric_limits at class scope +#ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS + BOOST_STATIC_ASSERT(std::numeric_limits::is_integer); + BOOST_STATIC_ASSERT(!std::numeric_limits::is_signed); +#endif + + // avoid "left shift count >= with of type" warning + for(int i = 0; i < w; ++i) + wordmask |= (1u << i); + seed(s0); + } + + template linear_feedback_shift(It& first, It last) : wordmask(0) + { + // MSVC fails BOOST_STATIC_ASSERT with std::numeric_limits at class scope +#ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS + BOOST_STATIC_ASSERT(std::numeric_limits::is_integer); + BOOST_STATIC_ASSERT(!std::numeric_limits::is_signed); +#endif + + // avoid "left shift count >= with of type" warning + for(int i = 0; i < w; ++i) + wordmask |= (1u << i); + seed(first, last); + } + + void seed(UIntType s0 = 341) { + if(s0 < (1 << (w-k))) { + s0 += 1 << (w-k); + } + value = s0; + } + template void seed(It& first, It last) + { + if(first == last) + throw std::invalid_argument("linear_feedback_shift::seed"); + value = *first++; + assert(value >= (1 << (w-k))); + } + + result_type operator()() + { + const UIntType b = (((value << q) ^ value) & wordmask) >> (k-s); + const UIntType mask = ( (~static_cast(0)) << (w-k) ) & wordmask; + value = ((value & mask) << s) ^ b; + return value; + } + static bool validation(result_type x) { return val == x; } + +#ifndef BOOST_NO_OPERATORS_IN_NAMESPACE + +#ifndef BOOST_RANDOM_NO_STREAM_OPERATORS + template + friend std::basic_ostream& + operator<<(std::basic_ostream& os, linear_feedback_shift x) + { os << x.value; return os; } + + template + friend std::basic_istream& + operator>>(std::basic_istream& is, linear_feedback_shift& x) + { is >> x.value; return is; } +#endif + + friend bool operator==(linear_feedback_shift x, linear_feedback_shift y) + { return x.value == y.value; } + friend bool operator!=(linear_feedback_shift x, linear_feedback_shift y) + { return !(x == y); } +#else + // Use a member function; Streamable concept not supported. + bool operator==(linear_feedback_shift rhs) const + { return value == rhs.value; } + bool operator!=(linear_feedback_shift rhs) const + { return !(*this == rhs); } +#endif + +private: + UIntType wordmask; // avoid "left shift count >= width of type" warnings + UIntType value; +}; + +#ifndef BOOST_NO_INCLASS_MEMBER_INITIALIZATION +// A definition is required even for integral static constants +template +const bool linear_feedback_shift::has_fixed_range; +template +const int linear_feedback_shift::word_size; +template +const int linear_feedback_shift::exponent1; +template +const int linear_feedback_shift::exponent2; +template +const int linear_feedback_shift::step_size; +#endif + +} // namespace random +} // namespace boost + +#endif // BOOST_RANDOM_LINEAR_FEEDBACK_SHIFT_HPP diff --git a/Boost/boost/random/lognormal_distribution.hpp b/Boost/boost/random/lognormal_distribution.hpp new file mode 100644 index 000000000..bb54829e2 --- /dev/null +++ b/Boost/boost/random/lognormal_distribution.hpp @@ -0,0 +1,129 @@ +/* boost random/lognormal_distribution.hpp header file + * + * Copyright Jens Maurer 2000-2001 + * 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: lognormal_distribution.hpp 60755 2010-03-22 00:45:06Z steven_watanabe $ + * + * Revision history + * 2001-02-18 moved to individual header files + */ + +#ifndef BOOST_RANDOM_LOGNORMAL_DISTRIBUTION_HPP +#define BOOST_RANDOM_LOGNORMAL_DISTRIBUTION_HPP + +#include // std::exp, std::sqrt +#include +#include +#include +#include +#include +#include + +#ifdef BOOST_NO_STDC_NAMESPACE +namespace std { + using ::log; + using ::sqrt; +} +#endif + +namespace boost { + +#if defined(__GNUC__) && (__GNUC__ < 3) +// Special gcc workaround: gcc 2.95.x ignores using-declarations +// in template classes (confirmed by gcc author Martin v. Loewis) + using std::sqrt; + using std::exp; +#endif + +/** + * Instantiations of class template lognormal_distribution model a + * \random_distribution. Such a distribution produces random numbers + * with \f$p(x) = \frac{1}{x \sigma_N \sqrt{2\pi}} e^{\frac{-\left(\log(x)-\mu_N\right)^2}{2\sigma_N^2}}\f$ + * for x > 0, where \f$\mu_N = \log\left(\frac{\mu^2}{\sqrt{\sigma^2 + \mu^2}}\right)\f$ and + * \f$\sigma_N = \sqrt{\log\left(1 + \frac{\sigma^2}{\mu^2}\right)}\f$. + */ +template +class lognormal_distribution +{ +public: + typedef typename normal_distribution::input_type input_type; + typedef RealType result_type; + +#ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS + BOOST_STATIC_ASSERT(!std::numeric_limits::is_integer); +#endif + + /** + * Constructs a lognormal_distribution. @c mean and @c sigma are the + * mean and standard deviation of the lognormal distribution. + */ + explicit lognormal_distribution(result_type mean_arg = result_type(1), + result_type sigma_arg = result_type(1)) + : _mean(mean_arg), _sigma(sigma_arg) + { + assert(_mean > result_type(0)); + init(); + } + + // compiler-generated copy ctor and assignment operator are fine + + RealType mean() const { return _mean; } + RealType sigma() const { return _sigma; } + void reset() { _normal.reset(); } + + template + result_type operator()(Engine& eng) + { +#ifndef BOOST_NO_STDC_NAMESPACE + // allow for Koenig lookup + using std::exp; +#endif + return exp(_normal(eng) * _nsigma + _nmean); + } + +#ifndef BOOST_RANDOM_NO_STREAM_OPERATORS + template + friend std::basic_ostream& + operator<<(std::basic_ostream& os, const lognormal_distribution& ld) + { + os << ld._normal << " " << ld._mean << " " << ld._sigma; + return os; + } + + template + friend std::basic_istream& + operator>>(std::basic_istream& is, lognormal_distribution& ld) + { + is >> std::ws >> ld._normal >> std::ws >> ld._mean >> std::ws >> ld._sigma; + ld.init(); + return is; + } +#endif + +private: + + /// \cond hide_private_members + void init() + { +#ifndef BOOST_NO_STDC_NAMESPACE + // allow for Koenig lookup + using std::exp; using std::log; using std::sqrt; +#endif + _nmean = log(_mean*_mean/sqrt(_sigma*_sigma + _mean*_mean)); + _nsigma = sqrt(log(_sigma*_sigma/_mean/_mean+result_type(1))); + } + /// \endcond + + RealType _mean, _sigma; + RealType _nmean, _nsigma; + normal_distribution _normal; +}; + +} // namespace boost + +#endif // BOOST_RANDOM_LOGNORMAL_DISTRIBUTION_HPP diff --git a/Boost/boost/random/mersenne_twister.hpp b/Boost/boost/random/mersenne_twister.hpp new file mode 100644 index 000000000..fae5cd514 --- /dev/null +++ b/Boost/boost/random/mersenne_twister.hpp @@ -0,0 +1,367 @@ +/* boost random/mersenne_twister.hpp header file + * + * Copyright Jens Maurer 2000-2001 + * 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: mersenne_twister.hpp 60755 2010-03-22 00:45:06Z steven_watanabe $ + * + * Revision history + * 2001-02-18 moved to individual header files + */ + +#ifndef BOOST_RANDOM_MERSENNE_TWISTER_HPP +#define BOOST_RANDOM_MERSENNE_TWISTER_HPP + +#include +#include // std::copy +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost { +namespace random { + +/** + * Instantiations of class template mersenne_twister model a + * \pseudo_random_number_generator. It uses the algorithm described in + * + * @blockquote + * "Mersenne Twister: A 623-dimensionally equidistributed uniform + * pseudo-random number generator", Makoto Matsumoto and Takuji Nishimura, + * ACM Transactions on Modeling and Computer Simulation: Special Issue on + * Uniform Random Number Generation, Vol. 8, No. 1, January 1998, pp. 3-30. + * @endblockquote + * + * @xmlnote + * The boost variant has been implemented from scratch and does not + * derive from or use mt19937.c provided on the above WWW site. However, it + * was verified that both produce identical output. + * @endxmlnote + * + * The seeding from an integer was changed in April 2005 to address a + * weakness. + * + * The quality of the generator crucially depends on the choice of the + * parameters. User code should employ one of the sensibly parameterized + * generators such as \mt19937 instead. + * + * The generator requires considerable amounts of memory for the storage of + * its state array. For example, \mt11213b requires about 1408 bytes and + * \mt19937 requires about 2496 bytes. + */ +template +class mersenne_twister +{ +public: + typedef UIntType result_type; + BOOST_STATIC_CONSTANT(int, word_size = w); + BOOST_STATIC_CONSTANT(int, state_size = n); + BOOST_STATIC_CONSTANT(int, shift_size = m); + BOOST_STATIC_CONSTANT(int, mask_bits = r); + BOOST_STATIC_CONSTANT(UIntType, parameter_a = a); + BOOST_STATIC_CONSTANT(int, output_u = u); + BOOST_STATIC_CONSTANT(int, output_s = s); + BOOST_STATIC_CONSTANT(UIntType, output_b = b); + BOOST_STATIC_CONSTANT(int, output_t = t); + BOOST_STATIC_CONSTANT(UIntType, output_c = c); + BOOST_STATIC_CONSTANT(int, output_l = l); + + BOOST_STATIC_CONSTANT(bool, has_fixed_range = false); + + /** + * Constructs a @c mersenne_twister and calls @c seed(). + */ + mersenne_twister() { seed(); } + + /** + * Constructs a @c mersenne_twister and calls @c seed(value). + */ + BOOST_RANDOM_DETAIL_ARITHMETIC_CONSTRUCTOR(mersenne_twister, UIntType, value) + { seed(value); } + template mersenne_twister(It& first, It last) { seed(first,last); } + + /** + * Constructs a mersenne_twister and calls @c seed(gen). + * + * @xmlnote + * The copy constructor will always be preferred over + * the templated constructor. + * @endxmlnote + */ + BOOST_RANDOM_DETAIL_GENERATOR_CONSTRUCTOR(mersenne_twister, Generator, gen) + { seed(gen); } + + // compiler-generated copy ctor and assignment operator are fine + + /** Calls @c seed(result_type(5489)). */ + void seed() { seed(UIntType(5489)); } + + /** + * Sets the state x(0) to v mod 2w. Then, iteratively, + * sets x(i) to (i + 1812433253 * (x(i-1) xor (x(i-1) rshift w-2))) mod 2w + * for i = 1 .. n-1. x(n) is the first value to be returned by operator(). + */ + BOOST_RANDOM_DETAIL_ARITHMETIC_SEED(mersenne_twister, UIntType, value) + { + // New seeding algorithm from + // http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/MT2002/emt19937ar.html + // In the previous versions, MSBs of the seed affected only MSBs of the + // state x[]. + const UIntType mask = ~0u; + x[0] = value & mask; + for (i = 1; i < n; i++) { + // See Knuth "The Art of Computer Programming" Vol. 2, 3rd ed., page 106 + x[i] = (1812433253UL * (x[i-1] ^ (x[i-1] >> (w-2))) + i) & mask; + } + } + + /** + * Sets the state of this mersenne_twister to the values + * returned by n invocations of gen. + * + * Complexity: Exactly n invocations of gen. + */ + BOOST_RANDOM_DETAIL_GENERATOR_SEED(mersenne_twister, Generator, gen) + { +#ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS + BOOST_STATIC_ASSERT(!std::numeric_limits::is_signed); +#endif + // I could have used std::generate_n, but it takes "gen" by value + for(int j = 0; j < n; j++) + x[j] = gen(); + i = n; + } + + template + void seed(It& first, It last) + { + int j; + for(j = 0; j < n && first != last; ++j, ++first) + x[j] = *first; + i = n; + if(first == last && j < n) + throw std::invalid_argument("mersenne_twister::seed"); + } + + result_type min BOOST_PREVENT_MACRO_SUBSTITUTION () const { return 0; } + result_type max BOOST_PREVENT_MACRO_SUBSTITUTION () const + { + // avoid "left shift count >= with of type" warning + result_type res = 0; + for(int j = 0; j < w; ++j) + res |= (1u << j); + return res; + } + + result_type operator()(); + static bool validation(result_type v) { return val == v; } + +#ifndef BOOST_NO_OPERATORS_IN_NAMESPACE + +#ifndef BOOST_RANDOM_NO_STREAM_OPERATORS + template + friend std::basic_ostream& + operator<<(std::basic_ostream& os, const mersenne_twister& mt) + { + for(int j = 0; j < mt.state_size; ++j) + os << mt.compute(j) << " "; + return os; + } + + template + friend std::basic_istream& + operator>>(std::basic_istream& is, mersenne_twister& mt) + { + for(int j = 0; j < mt.state_size; ++j) + is >> mt.x[j] >> std::ws; + // MSVC (up to 7.1) and Borland (up to 5.64) don't handle the template + // value parameter "n" available from the class template scope, so use + // the static constant with the same value + mt.i = mt.state_size; + return is; + } +#endif + + friend bool operator==(const mersenne_twister& x, const mersenne_twister& y) + { + for(int j = 0; j < state_size; ++j) + if(x.compute(j) != y.compute(j)) + return false; + return true; + } + + friend bool operator!=(const mersenne_twister& x, const mersenne_twister& y) + { return !(x == y); } +#else + // Use a member function; Streamable concept not supported. + bool operator==(const mersenne_twister& rhs) const + { + for(int j = 0; j < state_size; ++j) + if(compute(j) != rhs.compute(j)) + return false; + return true; + } + + bool operator!=(const mersenne_twister& rhs) const + { return !(*this == rhs); } +#endif + +private: + /// \cond hide_private_members + // returns x(i-n+index), where index is in 0..n-1 + UIntType compute(unsigned int index) const + { + // equivalent to (i-n+index) % 2n, but doesn't produce negative numbers + return x[ (i + n + index) % (2*n) ]; + } + void twist(int block); + /// \endcond + + // state representation: next output is o(x(i)) + // x[0] ... x[k] x[k+1] ... x[n-1] x[n] ... x[2*n-1] represents + // x(i-k) ... x(i) x(i+1) ... x(i-k+n-1) x(i-k-n) ... x[i(i-k-1)] + // The goal is to always have x(i-n) ... x(i-1) available for + // operator== and save/restore. + + UIntType x[2*n]; + int i; +}; + +#ifndef BOOST_NO_INCLASS_MEMBER_INITIALIZATION +// A definition is required even for integral static constants +template +const bool mersenne_twister::has_fixed_range; +template +const int mersenne_twister::state_size; +template +const int mersenne_twister::shift_size; +template +const int mersenne_twister::mask_bits; +template +const UIntType mersenne_twister::parameter_a; +template +const int mersenne_twister::output_u; +template +const int mersenne_twister::output_s; +template +const UIntType mersenne_twister::output_b; +template +const int mersenne_twister::output_t; +template +const UIntType mersenne_twister::output_c; +template +const int mersenne_twister::output_l; +#endif + +/// \cond hide_private_members +template +void mersenne_twister::twist(int block) +{ + const UIntType upper_mask = (~0u) << r; + const UIntType lower_mask = ~upper_mask; + + if(block == 0) { + for(int j = n; j < 2*n; j++) { + UIntType y = (x[j-n] & upper_mask) | (x[j-(n-1)] & lower_mask); + x[j] = x[j-(n-m)] ^ (y >> 1) ^ (y&1 ? a : 0); + } + } else if (block == 1) { + // split loop to avoid costly modulo operations + { // extra scope for MSVC brokenness w.r.t. for scope + for(int j = 0; j < n-m; j++) { + UIntType y = (x[j+n] & upper_mask) | (x[j+n+1] & lower_mask); + x[j] = x[j+n+m] ^ (y >> 1) ^ (y&1 ? a : 0); + } + } + + for(int j = n-m; j < n-1; j++) { + UIntType y = (x[j+n] & upper_mask) | (x[j+n+1] & lower_mask); + x[j] = x[j-(n-m)] ^ (y >> 1) ^ (y&1 ? a : 0); + } + // last iteration + UIntType y = (x[2*n-1] & upper_mask) | (x[0] & lower_mask); + x[n-1] = x[m-1] ^ (y >> 1) ^ (y&1 ? a : 0); + i = 0; + } +} +/// \endcond + +template +inline typename mersenne_twister::result_type +mersenne_twister::operator()() +{ + if(i == n) + twist(0); + else if(i >= 2*n) + twist(1); + // Step 4 + UIntType z = x[i]; + ++i; + z ^= (z >> u); + z ^= ((z << s) & b); + z ^= ((z << t) & c); + z ^= (z >> l); + return z; +} + +} // namespace random + +/** + * The specializations \mt11213b and \mt19937 are from + * + * @blockquote + * "Mersenne Twister: A 623-dimensionally equidistributed + * uniform pseudo-random number generator", Makoto Matsumoto + * and Takuji Nishimura, ACM Transactions on Modeling and + * Computer Simulation: Special Issue on Uniform Random Number + * Generation, Vol. 8, No. 1, January 1998, pp. 3-30. + * @endblockquote + */ +typedef random::mersenne_twister mt11213b; + +/** + * The specializations \mt11213b and \mt19937 are from + * + * @blockquote + * "Mersenne Twister: A 623-dimensionally equidistributed + * uniform pseudo-random number generator", Makoto Matsumoto + * and Takuji Nishimura, ACM Transactions on Modeling and + * Computer Simulation: Special Issue on Uniform Random Number + * Generation, Vol. 8, No. 1, January 1998, pp. 3-30. + * @endblockquote + */ +typedef random::mersenne_twister mt19937; + +} // namespace boost + +BOOST_RANDOM_PTR_HELPER_SPEC(boost::mt19937) + +#endif // BOOST_RANDOM_MERSENNE_TWISTER_HPP diff --git a/Boost/boost/random/normal_distribution.hpp b/Boost/boost/random/normal_distribution.hpp new file mode 100644 index 000000000..f6317460c --- /dev/null +++ b/Boost/boost/random/normal_distribution.hpp @@ -0,0 +1,131 @@ +/* boost random/normal_distribution.hpp header file + * + * Copyright Jens Maurer 2000-2001 + * 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: normal_distribution.hpp 60755 2010-03-22 00:45:06Z steven_watanabe $ + * + * Revision history + * 2001-02-18 moved to individual header files + */ + +#ifndef BOOST_RANDOM_NORMAL_DISTRIBUTION_HPP +#define BOOST_RANDOM_NORMAL_DISTRIBUTION_HPP + +#include +#include +#include +#include +#include +#include + +namespace boost { + +/** + * Instantiations of class template normal_distribution model a + * \random_distribution. Such a distribution produces random numbers + * @c x distributed with probability density function + * \f$p(x) = \frac{1}{\sqrt{2\pi\sigma}} e^{-\frac{(x-\mu)^2}{2\sigma^2}}\f$, + * where mean and sigma are the parameters of the distribution. + */ +// deterministic Box-Muller method, uses trigonometric functions +template +class normal_distribution +{ +public: + typedef RealType input_type; + typedef RealType result_type; + +#if !defined(BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS) && !(defined(BOOST_MSVC) && BOOST_MSVC <= 1300) + BOOST_STATIC_ASSERT(!std::numeric_limits::is_integer); +#endif + + /** + * Constructs a normal_distribution object. @c mean and @c sigma are + * the parameters for the distribution. + * + * Requires: sigma > 0 + */ + explicit normal_distribution(const result_type& mean_arg = result_type(0), + const result_type& sigma_arg = result_type(1)) + : _mean(mean_arg), _sigma(sigma_arg), _valid(false) + { + assert(_sigma >= result_type(0)); + } + + // compiler-generated copy constructor is NOT fine, need to purge cache + normal_distribution(const normal_distribution& other) + : _mean(other._mean), _sigma(other._sigma), _valid(false) + { + } + + // compiler-generated copy ctor and assignment operator are fine + + /** + * Returns: The "mean" parameter of the distribution. + */ + RealType mean() const { return _mean; } + /** + * Returns: The "sigma" parameter of the distribution. + */ + RealType sigma() const { return _sigma; } + + void reset() { _valid = false; } + + template + result_type operator()(Engine& eng) + { +#ifndef BOOST_NO_STDC_NAMESPACE + // allow for Koenig lookup + using std::sqrt; using std::log; using std::sin; using std::cos; +#endif + if(!_valid) { + _r1 = eng(); + _r2 = eng(); + _cached_rho = sqrt(-result_type(2) * log(result_type(1)-_r2)); + _valid = true; + } else { + _valid = false; + } + // Can we have a boost::mathconst please? + const result_type pi = result_type(3.14159265358979323846); + + return _cached_rho * (_valid ? + cos(result_type(2)*pi*_r1) : + sin(result_type(2)*pi*_r1)) + * _sigma + _mean; + } + +#ifndef BOOST_RANDOM_NO_STREAM_OPERATORS + template + friend std::basic_ostream& + operator<<(std::basic_ostream& os, const normal_distribution& nd) + { + os << nd._mean << " " << nd._sigma << " " + << nd._valid << " " << nd._cached_rho << " " << nd._r1; + return os; + } + + template + friend std::basic_istream& + operator>>(std::basic_istream& is, normal_distribution& nd) + { + is >> std::ws >> nd._mean >> std::ws >> nd._sigma + >> std::ws >> nd._valid >> std::ws >> nd._cached_rho + >> std::ws >> nd._r1; + return is; + } +#endif +private: + result_type _mean, _sigma; + result_type _r1, _r2, _cached_rho; + bool _valid; +}; + +} // namespace boost + +#endif // BOOST_RANDOM_NORMAL_DISTRIBUTION_HPP diff --git a/Boost/boost/random/poisson_distribution.hpp b/Boost/boost/random/poisson_distribution.hpp new file mode 100644 index 000000000..ae72ee8a1 --- /dev/null +++ b/Boost/boost/random/poisson_distribution.hpp @@ -0,0 +1,116 @@ +/* boost random/poisson_distribution.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: poisson_distribution.hpp 60755 2010-03-22 00:45:06Z steven_watanabe $ + * + */ + +#ifndef BOOST_RANDOM_POISSON_DISTRIBUTION_HPP +#define BOOST_RANDOM_POISSON_DISTRIBUTION_HPP + +#include +#include +#include +#include +#include +#include + +namespace boost { + +// Knuth + +/** + * An instantiation of the class template @c poisson_distribution is a + * model of \random_distribution. The poisson distribution has + * \f$p(i) = \frac{e^{-\lambda}\lambda^i}{i!}\f$ + */ +template +class poisson_distribution +{ +public: + typedef RealType input_type; + typedef IntType result_type; + + /** + * Constructs a @c poisson_distribution with the parameter @c mean. + * + * Requires: mean > 0 + */ + explicit poisson_distribution(const RealType& mean_arg = RealType(1)) + : _mean(mean_arg) + { +#ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS + // MSVC fails BOOST_STATIC_ASSERT with std::numeric_limits at class scope + BOOST_STATIC_ASSERT(std::numeric_limits::is_integer); + BOOST_STATIC_ASSERT(!std::numeric_limits::is_integer); +#endif + + assert(_mean > RealType(0)); + init(); + } + + // compiler-generated copy ctor and assignment operator are fine + + /** + * Returns: the "mean" parameter of the distribution. + */ + RealType mean() const { return _mean; } + void reset() { } + + template + result_type operator()(Engine& eng) + { + // TODO: This is O(_mean), but it should be O(log(_mean)) for large _mean + RealType product = RealType(1); + for(result_type m = 0; ; ++m) { + product *= eng(); + if(product <= _exp_mean) + return m; + } + } + +#ifndef BOOST_RANDOM_NO_STREAM_OPERATORS + template + friend std::basic_ostream& + operator<<(std::basic_ostream& os, const poisson_distribution& pd) + { + os << pd._mean; + return os; + } + + template + friend std::basic_istream& + operator>>(std::basic_istream& is, poisson_distribution& pd) + { + is >> std::ws >> pd._mean; + pd.init(); + return is; + } +#endif + +private: + /// \cond hide_private_members + void init() + { +#ifndef BOOST_NO_STDC_NAMESPACE + // allow for Koenig lookup + using std::exp; +#endif + _exp_mean = exp(-_mean); + } + /// \endcond + + RealType _mean; + // some precomputed data from the parameters + RealType _exp_mean; +}; + +} // namespace boost + +#endif // BOOST_RANDOM_POISSON_DISTRIBUTION_HPP diff --git a/Boost/boost/random/random_number_generator.hpp b/Boost/boost/random/random_number_generator.hpp new file mode 100644 index 000000000..7fb9733d2 --- /dev/null +++ b/Boost/boost/random/random_number_generator.hpp @@ -0,0 +1,71 @@ +/* boost random/random_number_generator.hpp header file + * + * Copyright Jens Maurer 2000-2001 + * 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: random_number_generator.hpp 60755 2010-03-22 00:45:06Z steven_watanabe $ + * + * Revision history + * 2001-02-18 moved to individual header files + */ + +#ifndef BOOST_RANDOM_RANDOM_NUMBER_GENERATOR_HPP +#define BOOST_RANDOM_RANDOM_NUMBER_GENERATOR_HPP + +#include +#include +#include +#include +#include + +namespace boost { + +/** + * Instantiations of class template random_number_generator model a + * RandomNumberGenerator (std:25.2.11 [lib.alg.random.shuffle]). On + * each invocation, it returns a uniformly distributed integer in + * the range [0..n). + * + * The template parameter IntType shall denote some integer-like value type. + */ +template +class random_number_generator +{ +public: + typedef UniformRandomNumberGenerator base_type; + typedef IntType argument_type; + typedef IntType result_type; + /** + * Constructs a random_number_generator functor with the given + * \uniform_random_number_generator as the underlying source of + * random numbers. + */ + random_number_generator(base_type& rng) : _rng(rng) + { +#ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS + BOOST_STATIC_ASSERT(std::numeric_limits::is_integer); +#endif + } + // compiler-generated copy ctor is fine + // assignment is disallowed because there is a reference member + + /** + * Returns a value in the range [0, n) + */ + result_type operator()(argument_type n) + { + typedef uniform_int dist_type; + return variate_generator(_rng, dist_type(0, n-1))(); + } + +private: + base_type& _rng; +}; + +} // namespace boost + +#endif // BOOST_RANDOM_RANDOM_NUMBER_GENERATOR_HPP diff --git a/Boost/boost/random/ranlux.hpp b/Boost/boost/random/ranlux.hpp new file mode 100644 index 000000000..39eb32b3d --- /dev/null +++ b/Boost/boost/random/ranlux.hpp @@ -0,0 +1,81 @@ +/* boost random/ranlux.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: ranlux.hpp 60755 2010-03-22 00:45:06Z steven_watanabe $ + * + * Revision history + * 2001-02-18 created + */ + +#ifndef BOOST_RANDOM_RANLUX_HPP +#define BOOST_RANDOM_RANLUX_HPP + +#include +#include +#include + +namespace boost { + +namespace random { + typedef subtract_with_carry ranlux_base; + typedef subtract_with_carry_01 ranlux_base_01; + typedef subtract_with_carry_01 ranlux64_base_01; +} + +namespace random { +namespace detail { +/** + * The ranlux family of generators are described in + * + * @blockquote + * "A portable high-quality random number generator for lattice field theory + * calculations", M. Luescher, Computer Physics Communications, 79 (1994) + * pp 100-110. + * @endblockquote + * + * The levels are given in + * + * @blockquote + * "RANLUX: A Fortran implementation ofthe high-quality + * pseudorandom number generator of Luescher", F. James, + * Computer Physics Communications 79 (1994) 111-114 + * @endblockquote + */ +class ranlux_documentation {}; +} +} + +/** @copydoc boost::random::detail::ranlux_documentation */ +typedef random::discard_block ranlux3; +/** @copydoc boost::random::detail::ranlux_documentation */ +typedef random::discard_block ranlux4; + +/** @copydoc boost::random::detail::ranlux_documentation */ +typedef random::discard_block ranlux3_01; +/** @copydoc boost::random::detail::ranlux_documentation */ +typedef random::discard_block ranlux4_01; + +/** @copydoc boost::random::detail::ranlux_documentation */ +typedef random::discard_block ranlux64_3_01; +/** @copydoc boost::random::detail::ranlux_documentation */ +typedef random::discard_block ranlux64_4_01; + +#if !defined(BOOST_NO_INT64_T) && !defined(BOOST_NO_INTEGRAL_INT64_T) +namespace random { + typedef random::subtract_with_carry ranlux64_base; +} +/** @copydoc boost::random::detail::ranlux_documentation */ +typedef random::discard_block ranlux64_3; +/** @copydoc boost::random::detail::ranlux_documentation */ +typedef random::discard_block ranlux64_4; +#endif /* !BOOST_NO_INT64_T && !BOOST_NO_INTEGRAL_INT64_T */ + +} // namespace boost + +#endif // BOOST_RANDOM_LINEAR_CONGRUENTIAL_HPP diff --git a/Boost/boost/random/shuffle_output.hpp b/Boost/boost/random/shuffle_output.hpp new file mode 100644 index 000000000..9346a191d --- /dev/null +++ b/Boost/boost/random/shuffle_output.hpp @@ -0,0 +1,234 @@ +/* boost random/shuffle_output.hpp header file + * + * Copyright Jens Maurer 2000-2001 + * 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: shuffle_output.hpp 60755 2010-03-22 00:45:06Z steven_watanabe $ + * + * Revision history + * 2001-02-18 moved to individual header files + */ + +#ifndef BOOST_RANDOM_SHUFFLE_OUTPUT_HPP +#define BOOST_RANDOM_SHUFFLE_OUTPUT_HPP + +#include +#include // std::copy +#include +#include +#include +#include +#include +#include + +namespace boost { +namespace random { + +/** + * Instatiations of class template shuffle_output model a + * \pseudo_random_number_generator. It mixes the output + * of some (usually \linear_congruential) \uniform_random_number_generator + * to get better statistical properties. + * The algorithm is described in + * + * @blockquote + * "Improving a poor random number generator", Carter Bays + * and S.D. Durham, ACM Transactions on Mathematical Software, + * Vol 2, No. 1, March 1976, pp. 59-64. + * http://doi.acm.org/10.1145/355666.355670 + * @endblockquote + * + * The output of the base generator is buffered in an array of + * length k. Every output X(n) has a second role: It gives an + * index into the array where X(n+1) will be retrieved. Used + * array elements are replaced with fresh output from the base + * generator. + * + * Template parameters are the base generator and the array + * length k, which should be around 100. The template parameter + * val is the validation value checked by validation. + */ +template +class shuffle_output +{ +public: + typedef UniformRandomNumberGenerator base_type; + typedef typename base_type::result_type result_type; + + BOOST_STATIC_CONSTANT(bool, has_fixed_range = false); + BOOST_STATIC_CONSTANT(int, buffer_size = k); + + /** + * Constructs a @c shuffle_output generator by invoking the + * default constructor of the base generator. + * + * Complexity: Exactly k+1 invocations of the base generator. + */ + shuffle_output() : _rng() { init(); } +#if defined(BOOST_MSVC) && _MSC_VER < 1300 + // MSVC does not implicitly generate the copy constructor here + shuffle_output(const shuffle_output & x) + : _rng(x._rng), y(x.y) { std::copy(x.v, x.v+k, v); } +#endif + /** + * Constructs a shuffle_output generator by invoking the one-argument + * constructor of the base generator with the parameter seed. + * + * Complexity: Exactly k+1 invocations of the base generator. + */ + template + explicit shuffle_output(T s) : _rng(s) { init(); } + /** + * Constructs a shuffle_output generator by using a copy + * of the provided generator. + * + * Precondition: The template argument UniformRandomNumberGenerator + * shall denote a CopyConstructible type. + * + * Complexity: Exactly k+1 invocations of the base generator. + */ + explicit shuffle_output(const base_type & rng) : _rng(rng) { init(); } + template shuffle_output(It& first, It last) + : _rng(first, last) { init(); } + void seed() { _rng.seed(); init(); } + /** + * Invokes the one-argument seed method of the base generator + * with the parameter seed and re-initializes the internal buffer array. + * + * Complexity: Exactly k+1 invocations of the base generator. + */ + template + void seed(T s) { _rng.seed(s); init(); } + template void seed(It& first, It last) + { + _rng.seed(first, last); + init(); + } + + const base_type& base() const { return _rng; } + + result_type operator()() { + // calculating the range every time may seem wasteful. However, this + // makes the information locally available for the optimizer. + result_type range = (max)()-(min)()+1; + int j = k*(y-(min)())/range; + // assert(0 <= j && j < k); + y = v[j]; + v[j] = _rng(); + return y; + } + + result_type min BOOST_PREVENT_MACRO_SUBSTITUTION () const { return (_rng.min)(); } + result_type max BOOST_PREVENT_MACRO_SUBSTITUTION () const { return (_rng.max)(); } + static bool validation(result_type x) { return val == x; } + +#ifndef BOOST_NO_OPERATORS_IN_NAMESPACE + +#ifndef BOOST_RANDOM_NO_STREAM_OPERATORS + template + friend std::basic_ostream& + operator<<(std::basic_ostream& os, const shuffle_output& s) + { + os << s._rng << " " << s.y << " "; + for(int i = 0; i < s.buffer_size; ++i) + os << s.v[i] << " "; + return os; + } + + template + friend std::basic_istream& + operator>>(std::basic_istream& is, shuffle_output& s) + { + is >> s._rng >> std::ws >> s.y >> std::ws; + for(int i = 0; i < s.buffer_size; ++i) + is >> s.v[i] >> std::ws; + return is; + } +#endif + + friend bool operator==(const shuffle_output& x, const shuffle_output& y) + { return x._rng == y._rng && x.y == y.y && std::equal(x.v, x.v+k, y.v); } + friend bool operator!=(const shuffle_output& x, const shuffle_output& y) + { return !(x == y); } +#else + // Use a member function; Streamable concept not supported. + bool operator==(const shuffle_output& rhs) const + { return _rng == rhs._rng && y == rhs.y && std::equal(v, v+k, rhs.v); } + bool operator!=(const shuffle_output& rhs) const + { return !(*this == rhs); } +#endif +private: + void init() + { +#ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS + BOOST_STATIC_ASSERT(std::numeric_limits::is_integer); +#endif + result_type range = (max)()-(min)(); + assert(range > 0); // otherwise there would be little choice + if(static_cast(k * range) < + static_cast(range)) // not a sufficient condition + // likely overflow with bucket number computation + assert(!"overflow will occur"); + + // we cannot use std::generate, because it uses pass-by-value for _rng + for(result_type * p = v; p != v+k; ++p) + *p = _rng(); + y = _rng(); + } + + base_type _rng; + result_type v[k]; + result_type y; +}; + +#ifndef BOOST_NO_INCLASS_MEMBER_INITIALIZATION +// A definition is required even for integral static constants +template +const bool shuffle_output::has_fixed_range; + +template +const int shuffle_output::buffer_size; +#endif + +} // namespace random + +// validation by experiment from Harry Erwin's generator.h (private e-mail) +/** + * According to Harry Erwin (private e-mail), the specialization + * @c kreutzer1986 was suggested in: + * + * @blockquote + * "System Simulation: Programming Styles and Languages (International + * Computer Science Series)", Wolfgang Kreutzer, Addison-Wesley, December 1986. + * @endblockquote + */ +typedef random::shuffle_output< + random::linear_congruential, + 97, 139726> kreutzer1986; + + +} // namespace boost + +#endif // BOOST_RANDOM_SHUFFLE_OUTPUT_HPP diff --git a/Boost/boost/random/subtract_with_carry.hpp b/Boost/boost/random/subtract_with_carry.hpp new file mode 100644 index 000000000..bdb1401da --- /dev/null +++ b/Boost/boost/random/subtract_with_carry.hpp @@ -0,0 +1,465 @@ +/* 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: subtract_with_carry.hpp 60755 2010-03-22 00:45:06Z steven_watanabe $ + * + * Revision history + * 2002-03-02 created + */ + +#ifndef BOOST_RANDOM_SUBTRACT_WITH_CARRY_HPP +#define BOOST_RANDOM_SUBTRACT_WITH_CARRY_HPP + +#include +#include +#include // std::equal +#include +#include // std::pow +#include +#include +#include +#include +#include +#include +#include +#include + + +namespace boost { +namespace random { + +#if BOOST_WORKAROUND(_MSC_FULL_VER, BOOST_TESTED_AT(13102292)) && BOOST_MSVC > 1300 +# define BOOST_RANDOM_EXTRACT_SWC_01 +#endif + +#if defined(__APPLE_CC__) && defined(__GNUC__) && (__GNUC__ == 3) && (__GNUC_MINOR__ <= 3) +# define BOOST_RANDOM_EXTRACT_SWC_01 +#endif + +# ifdef BOOST_RANDOM_EXTRACT_SWC_01 +namespace detail +{ + template + void extract_subtract_with_carry_01( + IStream& is + , SubtractWithCarry& f + , RealType& carry + , RealType* x + , RealType modulus) + { + RealType value; + for(unsigned int j = 0; j < f.long_lag; ++j) { + is >> value >> std::ws; + x[j] = value / modulus; + } + is >> value >> std::ws; + carry = value / modulus; + } +} +# endif + +/** + * Instantiations of @c subtract_with_carry 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 subtract_with_carry +{ +public: + typedef IntType result_type; + BOOST_STATIC_CONSTANT(bool, has_fixed_range = true); + BOOST_STATIC_CONSTANT(result_type, min_value = 0); + BOOST_STATIC_CONSTANT(result_type, max_value = m-1); + BOOST_STATIC_CONSTANT(result_type, modulus = m); + BOOST_STATIC_CONSTANT(unsigned int, long_lag = r); + BOOST_STATIC_CONSTANT(unsigned int, short_lag = s); + + subtract_with_carry() { + // MSVC fails BOOST_STATIC_ASSERT with std::numeric_limits at class scope +#ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS + BOOST_STATIC_ASSERT(std::numeric_limits::is_signed); + BOOST_STATIC_ASSERT(std::numeric_limits::is_integer); +#endif + seed(); + } + BOOST_RANDOM_DETAIL_ARITHMETIC_CONSTRUCTOR(subtract_with_carry, uint32_t, value) + { seed(value); } + BOOST_RANDOM_DETAIL_GENERATOR_CONSTRUCTOR(subtract_with_carry, Generator, gen) + { seed(gen); } + template subtract_with_carry(It& first, It last) { seed(first,last); } + + // compiler-generated copy ctor and assignment operator are fine + + void seed() { seed(19780503u); } + BOOST_RANDOM_DETAIL_ARITHMETIC_SEED(subtract_with_carry, uint32_t, value) + { + random::linear_congruential intgen(value); + seed(intgen); + } + + // For GCC, moving this function out-of-line prevents inlining, which may + // reduce overall object code size. However, MSVC does not grok + // out-of-line template member functions. + BOOST_RANDOM_DETAIL_GENERATOR_SEED(subtract_with_carry, Generator, gen) + { + // I could have used std::generate_n, but it takes "gen" by value + for(unsigned int j = 0; j < long_lag; ++j) + x[j] = gen() % modulus; + carry = (x[long_lag-1] == 0); + k = 0; + } + + template + void seed(It& first, It last) + { + unsigned int j; + for(j = 0; j < long_lag && first != last; ++j, ++first) + x[j] = *first % modulus; + if(first == last && j < long_lag) + throw std::invalid_argument("subtract_with_carry::seed"); + carry = (x[long_lag-1] == 0); + k = 0; + } + + result_type min BOOST_PREVENT_MACRO_SUBSTITUTION () const { return min_value; } + result_type max BOOST_PREVENT_MACRO_SUBSTITUTION () const { return max_value; } + + result_type operator()() + { + int short_index = k - short_lag; + if(short_index < 0) + short_index += long_lag; + IntType delta; + if (x[short_index] >= x[k] + carry) { + // x(n) >= 0 + delta = x[short_index] - (x[k] + carry); + carry = 0; + } else { + // x(n) < 0 + delta = modulus - x[k] - carry + x[short_index]; + carry = 1; + } + x[k] = delta; + ++k; + if(k >= long_lag) + k = 0; + return delta; + } + +public: + static bool validation(result_type x) { return x == val; } + +#ifndef BOOST_NO_OPERATORS_IN_NAMESPACE + +#ifndef BOOST_RANDOM_NO_STREAM_OPERATORS + template + friend std::basic_ostream& + operator<<(std::basic_ostream& os, + const subtract_with_carry& f) + { + for(unsigned int j = 0; j < f.long_lag; ++j) + os << f.compute(j) << " "; + os << f.carry << " "; + return os; + } + + template + friend std::basic_istream& + operator>>(std::basic_istream& is, subtract_with_carry& f) + { + for(unsigned int j = 0; j < f.long_lag; ++j) + is >> f.x[j] >> std::ws; + is >> f.carry >> std::ws; + f.k = 0; + return is; + } +#endif + + friend bool operator==(const subtract_with_carry& x, const subtract_with_carry& y) + { + for(unsigned int j = 0; j < r; ++j) + if(x.compute(j) != y.compute(j)) + return false; + return true; + } + + friend bool operator!=(const subtract_with_carry& x, const subtract_with_carry& y) + { return !(x == y); } +#else + // Use a member function; Streamable concept not supported. + bool operator==(const subtract_with_carry& rhs) const + { + for(unsigned int j = 0; j < r; ++j) + if(compute(j) != rhs.compute(j)) + return false; + return true; + } + + bool operator!=(const subtract_with_carry& rhs) const + { return !(*this == rhs); } +#endif + +private: + /// \cond hide_private_members + // returns x(i-r+index), where index is in 0..r-1 + IntType compute(unsigned int index) const + { + return x[(k+index) % long_lag]; + } + /// \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]; + unsigned int k; + int carry; +}; + +#ifndef BOOST_NO_INCLASS_MEMBER_INITIALIZATION +// A definition is required even for integral static constants +template +const bool subtract_with_carry::has_fixed_range; +template +const IntType subtract_with_carry::min_value; +template +const IntType subtract_with_carry::max_value; +template +const IntType subtract_with_carry::modulus; +template +const unsigned int subtract_with_carry::long_lag; +template +const unsigned int subtract_with_carry::short_lag; +#endif + + +// use a floating-point representation to produce values in [0..1) +/** @copydoc boost::random::subtract_with_carry */ +template +class subtract_with_carry_01 +{ +public: + typedef RealType result_type; + BOOST_STATIC_CONSTANT(bool, has_fixed_range = false); + BOOST_STATIC_CONSTANT(int, word_size = w); + BOOST_STATIC_CONSTANT(unsigned int, long_lag = r); + BOOST_STATIC_CONSTANT(unsigned int, short_lag = s); + +#ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS + BOOST_STATIC_ASSERT(!std::numeric_limits::is_integer); +#endif + + subtract_with_carry_01() { init_modulus(); seed(); } + explicit subtract_with_carry_01(uint32_t value) + { init_modulus(); seed(value); } + template subtract_with_carry_01(It& first, It last) + { init_modulus(); seed(first,last); } + +private: + /// \cond hide_private_members + void init_modulus() + { +#ifndef BOOST_NO_STDC_NAMESPACE + // allow for Koenig lookup + using std::pow; +#endif + _modulus = pow(RealType(2), word_size); + } + /// \endcond hide_private_members + +public: + // compiler-generated copy ctor and assignment operator are fine + + void seed(uint32_t value = 19780503u) + { +#ifndef BOOST_NO_STDC_NAMESPACE + // allow for Koenig lookup + using std::fmod; +#endif + random::linear_congruential gen(value); + unsigned long array[(w+31)/32 * long_lag]; + for(unsigned int j = 0; j < sizeof(array)/sizeof(unsigned long); ++j) + array[j] = gen(); + unsigned long * start = array; + seed(start, array + sizeof(array)/sizeof(unsigned long)); + } + + template + void seed(It& first, It last) + { +#ifndef BOOST_NO_STDC_NAMESPACE + // allow for Koenig lookup + using std::fmod; + using std::pow; +#endif + unsigned long mask = ~((~0u) << (w%32)); // now lowest (w%32) bits set + RealType two32 = pow(RealType(2), 32); + unsigned int j; + for(j = 0; j < long_lag && first != last; ++j) { + x[j] = RealType(0); + for(int i = 0; i < w/32 && first != last; ++i, ++first) + x[j] += *first / pow(two32,i+1); + if(first != last && mask != 0) { + x[j] += fmod((*first & mask) / _modulus, RealType(1)); + ++first; + } + } + if(first == last && j < long_lag) + throw std::invalid_argument("subtract_with_carry_01::seed"); + carry = (x[long_lag-1] ? 0 : 1 / _modulus); + k = 0; + } + + result_type min BOOST_PREVENT_MACRO_SUBSTITUTION () const { return result_type(0); } + result_type max BOOST_PREVENT_MACRO_SUBSTITUTION () const { return result_type(1); } + + result_type operator()() + { + int short_index = k - short_lag; + if(short_index < 0) + short_index += long_lag; + RealType delta = x[short_index] - x[k] - carry; + if(delta < 0) { + delta += RealType(1); + carry = RealType(1)/_modulus; + } else { + carry = 0; + } + x[k] = delta; + ++k; + if(k >= long_lag) + k = 0; + return delta; + } + + static bool validation(result_type x) + { return x == val/pow(RealType(2), word_size); } + +#ifndef BOOST_NO_OPERATORS_IN_NAMESPACE + +#ifndef BOOST_RANDOM_NO_STREAM_OPERATORS + template + friend std::basic_ostream& + operator<<(std::basic_ostream& os, + const subtract_with_carry_01& f) + { +#ifndef BOOST_NO_STDC_NAMESPACE + // allow for Koenig lookup + using std::pow; +#endif + 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; + } + + template + friend std::basic_istream& + operator>>(std::basic_istream& is, subtract_with_carry_01& f) + { +# ifdef BOOST_RANDOM_EXTRACT_SWC_01 + detail::extract_subtract_with_carry_01(is, f, f.carry, f.x, f._modulus); +# else + // MSVC (up to 7.1) and Borland (up to 5.64) don't handle the template type + // parameter "RealType" available from the class template scope, so use + // the member typedef + typename subtract_with_carry_01::result_type value; + for(unsigned int j = 0; j < long_lag; ++j) { + is >> value >> std::ws; + f.x[j] = value / f._modulus; + } + is >> value >> std::ws; + f.carry = value / f._modulus; +# endif + f.k = 0; + return is; + } +#endif + + friend bool operator==(const subtract_with_carry_01& x, + const subtract_with_carry_01& y) + { + for(unsigned int j = 0; j < r; ++j) + if(x.compute(j) != y.compute(j)) + return false; + return true; + } + + friend bool operator!=(const subtract_with_carry_01& x, + const subtract_with_carry_01& y) + { return !(x == y); } +#else + // Use a member function; Streamable concept not supported. + bool operator==(const subtract_with_carry_01& rhs) const + { + for(unsigned int j = 0; j < r; ++j) + if(compute(j) != rhs.compute(j)) + return false; + return true; + } + + bool operator!=(const subtract_with_carry_01& rhs) const + { return !(*this == rhs); } +#endif + +private: + /// \cond hide_private_members + RealType compute(unsigned int index) const; + /// \endcond + unsigned int 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 +const bool subtract_with_carry_01::has_fixed_range; +template +const int subtract_with_carry_01::word_size; +template +const unsigned int subtract_with_carry_01::long_lag; +template +const unsigned int subtract_with_carry_01::short_lag; +#endif + +/// \cond hide_private_members +template +RealType subtract_with_carry_01::compute(unsigned int index) const +{ + return x[(k+index) % long_lag]; +} +/// \endcond + +} // namespace random +} // namespace boost + +#endif // BOOST_RANDOM_SUBTRACT_WITH_CARRY_HPP diff --git a/Boost/boost/random/triangle_distribution.hpp b/Boost/boost/random/triangle_distribution.hpp new file mode 100644 index 000000000..f4e139e00 --- /dev/null +++ b/Boost/boost/random/triangle_distribution.hpp @@ -0,0 +1,118 @@ +/* boost random/triangle_distribution.hpp header file + * + * Copyright Jens Maurer 2000-2001 + * 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: triangle_distribution.hpp 60755 2010-03-22 00:45:06Z steven_watanabe $ + * + * Revision history + * 2001-02-18 moved to individual header files + */ + +#ifndef BOOST_RANDOM_TRIANGLE_DISTRIBUTION_HPP +#define BOOST_RANDOM_TRIANGLE_DISTRIBUTION_HPP + +#include +#include +#include +#include + +namespace boost { + +/** + * Instantiations of @c triangle_distribution model a \random_distribution. + * A @c triangle_distribution has three parameters, @c a, @c b, and @c c, + * which are the smallest, the most probable and the largest values of + * the distribution respectively. + */ +template +class triangle_distribution +{ +public: + typedef RealType input_type; + typedef RealType result_type; + + /** + * Constructs a @c triangle_distribution with the parameters + * @c a, @c b, and @c c. + * + * Preconditions: a <= b <= c. + */ + explicit triangle_distribution(result_type a_arg = result_type(0), + result_type b_arg = result_type(0.5), + result_type c_arg = result_type(1)) + : _a(a_arg), _b(b_arg), _c(c_arg) + { + assert(_a <= _b && _b <= _c); + init(); + } + + // compiler-generated copy ctor and assignment operator are fine + + /** Returns the @c a parameter of the distribution */ + result_type a() const { return _a; } + /** Returns the @c b parameter of the distribution */ + result_type b() const { return _b; } + /** Returns the @c c parameter of the distribution */ + result_type c() const { return _c; } + + void reset() { } + + template + result_type operator()(Engine& eng) + { +#ifndef BOOST_NO_STDC_NAMESPACE + using std::sqrt; +#endif + result_type u = eng(); + if( u <= q1 ) + return _a + p1*sqrt(u); + else + return _c - d3*sqrt(d2*u-d1); + } + +#ifndef BOOST_RANDOM_NO_STREAM_OPERATORS + template + friend std::basic_ostream& + operator<<(std::basic_ostream& os, const triangle_distribution& td) + { + os << td._a << " " << td._b << " " << td._c; + return os; + } + + template + friend std::basic_istream& + operator>>(std::basic_istream& is, triangle_distribution& td) + { + is >> std::ws >> td._a >> std::ws >> td._b >> std::ws >> td._c; + td.init(); + return is; + } +#endif + +private: + /// \cond hide_private_members + void init() + { +#ifndef BOOST_NO_STDC_NAMESPACE + using std::sqrt; +#endif + d1 = _b - _a; + d2 = _c - _a; + d3 = sqrt(_c - _b); + q1 = d1 / d2; + p1 = sqrt(d1 * d2); + } + /// \endcond + + result_type _a, _b, _c; + result_type d1, d2, d3, q1, p1; +}; + +} // namespace boost + +#endif // BOOST_RANDOM_TRIANGLE_DISTRIBUTION_HPP diff --git a/Boost/boost/random/uniform_01.hpp b/Boost/boost/random/uniform_01.hpp new file mode 100644 index 000000000..87103cb12 --- /dev/null +++ b/Boost/boost/random/uniform_01.hpp @@ -0,0 +1,273 @@ +/* boost random/uniform_01.hpp header file + * + * Copyright Jens Maurer 2000-2001 + * 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: uniform_01.hpp 60755 2010-03-22 00:45:06Z steven_watanabe $ + * + * Revision history + * 2001-02-18 moved to individual header files + */ + +#ifndef BOOST_RANDOM_UNIFORM_01_HPP +#define BOOST_RANDOM_UNIFORM_01_HPP + +#include +#include +#include +#include +#include +#include + +#include + +namespace boost { + +#ifdef BOOST_RANDOM_DOXYGEN + +/** + * The distribution function uniform_01 models a \random_distribution. + * On each invocation, it returns a random floating-point value + * uniformly distributed in the range [0..1). + * + * The template parameter RealType shall denote a float-like value type + * with support for binary operators +, -, and /. + * + * Note: The current implementation is buggy, because it may not fill + * all of the mantissa with random bits. I'm unsure how to fill a + * (to-be-invented) @c boost::bigfloat class with random bits efficiently. + * It's probably time for a traits class. + */ +template +class uniform_01 +{ +public: + typedef RealType input_type; + typedef RealType result_type; + result_type min BOOST_PREVENT_MACRO_SUBSTITUTION () const; + result_type max BOOST_PREVENT_MACRO_SUBSTITUTION () const; + void reset(); + + template + result_type operator()(Engine& eng); + +#ifndef BOOST_RANDOM_NO_STREAM_OPERATORS + template + friend std::basic_ostream& + operator<<(std::basic_ostream& os, const new_uniform_01&) + { + return os; + } + + template + friend std::basic_istream& + operator>>(std::basic_istream& is, new_uniform_01&) + { + return is; + } +#endif +}; + +#else + +namespace detail { + +template +class new_uniform_01 +{ +public: + typedef RealType input_type; + typedef RealType result_type; + // compiler-generated copy ctor and copy assignment are fine + result_type min BOOST_PREVENT_MACRO_SUBSTITUTION () const { return result_type(0); } + result_type max BOOST_PREVENT_MACRO_SUBSTITUTION () const { return result_type(1); } + void reset() { } + + template + result_type operator()(Engine& eng) { + for (;;) { + typedef typename Engine::result_type base_result; + result_type factor = result_type(1) / + (result_type((eng.max)()-(eng.min)()) + + result_type(std::numeric_limits::is_integer ? 1 : 0)); + result_type result = result_type(eng() - (eng.min)()) * factor; + if (result < result_type(1)) + return result; + } + } + +#ifndef BOOST_RANDOM_NO_STREAM_OPERATORS + template + friend std::basic_ostream& + operator<<(std::basic_ostream& os, const new_uniform_01&) + { + return os; + } + + template + friend std::basic_istream& + operator>>(std::basic_istream& is, new_uniform_01&) + { + return is; + } +#endif +}; + +template +class backward_compatible_uniform_01 +{ + typedef boost::random::detail::ptr_helper traits; + typedef boost::random::detail::pass_through_engine internal_engine_type; +public: + typedef UniformRandomNumberGenerator base_type; + typedef RealType result_type; + + BOOST_STATIC_CONSTANT(bool, has_fixed_range = false); + +#if !defined(BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS) && !(defined(BOOST_MSVC) && BOOST_MSVC <= 1300) + BOOST_STATIC_ASSERT(!std::numeric_limits::is_integer); +#endif + + explicit backward_compatible_uniform_01(typename traits::rvalue_type rng) + : _rng(rng), + _factor(result_type(1) / + (result_type((_rng.max)()-(_rng.min)()) + + result_type(std::numeric_limits::is_integer ? 1 : 0))) + { + } + // compiler-generated copy ctor and copy assignment are fine + + result_type min BOOST_PREVENT_MACRO_SUBSTITUTION () const { return result_type(0); } + result_type max BOOST_PREVENT_MACRO_SUBSTITUTION () const { return result_type(1); } + typename traits::value_type& base() { return _rng.base(); } + const typename traits::value_type& base() const { return _rng.base(); } + void reset() { } + + result_type operator()() { + for (;;) { + result_type result = result_type(_rng() - (_rng.min)()) * _factor; + if (result < result_type(1)) + return result; + } + } + +#if !defined(BOOST_NO_OPERATORS_IN_NAMESPACE) && !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS) + template + friend std::basic_ostream& + operator<<(std::basic_ostream& os, const backward_compatible_uniform_01& u) + { + os << u._rng; + return os; + } + + template + friend std::basic_istream& + operator>>(std::basic_istream& is, backward_compatible_uniform_01& u) + { + is >> u._rng; + return is; + } +#endif + +private: + typedef typename internal_engine_type::result_type base_result; + internal_engine_type _rng; + result_type _factor; +}; + +#ifndef BOOST_NO_INCLASS_MEMBER_INITIALIZATION +// A definition is required even for integral static constants +template +const bool backward_compatible_uniform_01::has_fixed_range; +#endif + +template +struct select_uniform_01 +{ + template + struct apply + { + typedef backward_compatible_uniform_01 type; + }; +}; + +template<> +struct select_uniform_01 +{ + template + struct apply + { + typedef new_uniform_01 type; + }; +}; + +template<> +struct select_uniform_01 +{ + template + struct apply + { + typedef new_uniform_01 type; + }; +}; + +template<> +struct select_uniform_01 +{ + template + struct apply + { + typedef new_uniform_01 type; + }; +}; + +} + +// Because it is so commonly used: uniform distribution on the real [0..1) +// range. This allows for specializations to avoid a costly int -> float +// conversion plus float multiplication +template +class uniform_01 + : public detail::select_uniform_01::BOOST_NESTED_TEMPLATE apply::type +{ + typedef typename detail::select_uniform_01::BOOST_NESTED_TEMPLATE apply::type impl_type; + typedef boost::random::detail::ptr_helper traits; +public: + + uniform_01() {} + + explicit uniform_01(typename traits::rvalue_type rng) + : impl_type(rng) + { + } + +#if !defined(BOOST_NO_OPERATORS_IN_NAMESPACE) && !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS) + template + friend std::basic_ostream& + operator<<(std::basic_ostream& os, const uniform_01& u) + { + os << static_cast(u); + return os; + } + + template + friend std::basic_istream& + operator>>(std::basic_istream& is, uniform_01& u) + { + is >> static_cast(u); + return is; + } +#endif +}; + +#endif + +} // namespace boost + +#include + +#endif // BOOST_RANDOM_UNIFORM_01_HPP diff --git a/Boost/boost/random/uniform_int.hpp b/Boost/boost/random/uniform_int.hpp new file mode 100644 index 000000000..ef2f4f96a --- /dev/null +++ b/Boost/boost/random/uniform_int.hpp @@ -0,0 +1,300 @@ +/* boost random/uniform_int.hpp header file + * + * Copyright Jens Maurer 2000-2001 + * 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: uniform_int.hpp 60755 2010-03-22 00:45:06Z steven_watanabe $ + * + * Revision history + * 2001-04-08 added min +#include +#include +#include +#include +#include +#include +#include +#include + +namespace boost { + +/** + * The distribution function uniform_int models a \random_distribution. + * On each invocation, it returns a random integer value uniformly + * distributed in the set of integer numbers {min, min+1, min+2, ..., max}. + * + * The template parameter IntType shall denote an integer-like value type. + */ +template +class uniform_int +{ +public: + typedef IntType input_type; + typedef IntType result_type; + + /// \cond hide_private_members + typedef typename make_unsigned::type range_type; + /// \endcond + + /** + * Constructs a uniform_int object. @c min and @c max are + * the parameters of the distribution. + * + * Requires: min <= max + */ + explicit uniform_int(IntType min_arg = 0, IntType max_arg = 9) + : _min(min_arg), _max(max_arg) + { +#ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS + // MSVC fails BOOST_STATIC_ASSERT with std::numeric_limits at class scope + BOOST_STATIC_ASSERT(std::numeric_limits::is_integer); +#endif + assert(min_arg <= max_arg); + init(); + } + + /** + * Returns: The "min" parameter of the distribution + */ + result_type min BOOST_PREVENT_MACRO_SUBSTITUTION () const { return _min; } + /** + * Returns: The "max" parameter of the distribution + */ + result_type max BOOST_PREVENT_MACRO_SUBSTITUTION () const { return _max; } + void reset() { } + + // can't have member function templates out-of-line due to MSVC bugs + template + result_type operator()(Engine& eng) + { + return generate(eng, _min, _max, _range); + } + + template + result_type operator()(Engine& eng, result_type n) + { + assert(n > 0); + + if (n == 1) + { + return 0; + } + + return generate(eng, 0, n - 1, n - 1); + } + +#ifndef BOOST_RANDOM_NO_STREAM_OPERATORS + template + friend std::basic_ostream& + operator<<(std::basic_ostream& os, const uniform_int& ud) + { + os << ud._min << " " << ud._max; + return os; + } + + template + friend std::basic_istream& + operator>>(std::basic_istream& is, uniform_int& ud) + { + is >> std::ws >> ud._min >> std::ws >> ud._max; + ud.init(); + return is; + } +#endif + +private: + +#ifdef BOOST_MSVC +#pragma warning(push) +// disable division by zero warning, since we can't +// actually divide by zero. +#pragma warning(disable:4723) +#endif + + /// \cond hide_private_members + template + static result_type generate(Engine& eng, result_type min_value, result_type /*max_value*/, range_type range) + { + typedef typename Engine::result_type base_result; + // ranges are always unsigned + typedef typename make_unsigned::type base_unsigned; + const base_result bmin = (eng.min)(); + const base_unsigned brange = + random::detail::subtract()((eng.max)(), (eng.min)()); + + if(range == 0) { + return min_value; + } else if(brange == range) { + // this will probably never happen in real life + // basically nothing to do; just take care we don't overflow / underflow + base_unsigned v = random::detail::subtract()(eng(), bmin); + return random::detail::add()(v, min_value); + } else if(brange < range) { + // use rejection method to handle things like 0..3 --> 0..4 + for(;;) { + // concatenate several invocations of the base RNG + // take extra care to avoid overflows + + // limit == floor((range+1)/(brange+1)) + // Therefore limit*(brange+1) <= range+1 + range_type limit; + if(range == (std::numeric_limits::max)()) { + limit = range/(range_type(brange)+1); + if(range % (range_type(brange)+1) == range_type(brange)) + ++limit; + } else { + limit = (range+1)/(range_type(brange)+1); + } + + // We consider "result" as expressed to base (brange+1): + // For every power of (brange+1), we determine a random factor + range_type result = range_type(0); + range_type mult = range_type(1); + + // loop invariants: + // result < mult + // mult <= range + while(mult <= limit) { + // Postcondition: result <= range, thus no overflow + // + // limit*(brange+1)<=range+1 def. of limit (1) + // eng()-bmin<=brange eng() post. (2) + // and mult<=limit. loop condition (3) + // Therefore mult*(eng()-bmin+1)<=range+1 by (1),(2),(3) (4) + // Therefore mult*(eng()-bmin)+mult<=range+1 rearranging (4) (5) + // result(random::detail::subtract()(eng(), bmin) * mult); + + // equivalent to (mult * (brange+1)) == range+1, but avoids overflow. + if(mult * range_type(brange) == range - mult + 1) { + // The destination range is an integer power of + // the generator's range. + return(result); + } + + // Postcondition: mult <= range + // + // limit*(brange+1)<=range+1 def. of limit (1) + // mult<=limit loop condition (2) + // Therefore mult*(brange+1)<=range+1 by (1), (2) (3) + // mult*(brange+1)!=range+1 preceding if (4) + // Therefore mult*(brange+1) limit loop condition (1) + // Suppose range/mult >= brange+1 Assumption (2) + // range >= mult*(brange+1) by (2) (3) + // range+1 > mult*(brange+1) by (3) (4) + // range+1 > (limit+1)*(brange+1) by (1), (4) (5) + // (range+1)/(brange+1) > limit+1 by (5) (6) + // limit < floor((range+1)/(brange+1)) by (6) (7) + // limit==floor((range+1)/(brange+1)) def. of limit (8) + // not (2) reductio (9) + // + // loop postcondition: (range/mult)*mult+(mult-1) >= range + // + // (range/mult)*mult + range%mult == range identity (1) + // range%mult < mult def. of % (2) + // (range/mult)*mult+mult > range by (1), (2) (3) + // (range/mult)*mult+(mult-1) >= range by (3) (4) + // + // Note that the maximum value of result at this point is (mult-1), + // so after this final step, we generate numbers that can be + // at least as large as range. We have to really careful to avoid + // overflow in this final addition and in the rejection. Anything + // that overflows is larger than range and can thus be rejected. + + // range/mult < brange+1 -> no endless loop + range_type result_increment = uniform_int(0, range/mult)(eng); + if((std::numeric_limits::max)() / mult < result_increment) { + // The multiplcation would overflow. Reject immediately. + continue; + } + result_increment *= mult; + // unsigned integers are guaranteed to wrap on overflow. + result += result_increment; + if(result < result_increment) { + // The addition overflowed. Reject. + continue; + } + if(result > range) { + // Too big. Reject. + continue; + } + return random::detail::add()(result, min_value); + } + } else { // brange > range + base_unsigned bucket_size; + // it's safe to add 1 to range, as long as we cast it first, + // because we know that it is less than brange. However, + // we do need to be careful not to cause overflow by adding 1 + // to brange. + if(brange == (std::numeric_limits::max)()) { + bucket_size = brange / (static_cast(range)+1); + if(brange % (static_cast(range)+1) == static_cast(range)) { + ++bucket_size; + } + } else { + bucket_size = (brange+1) / (static_cast(range)+1); + } + for(;;) { + base_unsigned result = + random::detail::subtract()(eng(), bmin); + result /= bucket_size; + // result and range are non-negative, and result is possibly larger + // than range, so the cast is safe + if(result <= static_cast(range)) + return random::detail::add()(result, min_value); + } + } + } + +#ifdef BOOST_MSVC +#pragma warning(pop) +#endif + + void init() + { + _range = random::detail::subtract()(_max, _min); + } + + /// \endcond + + // The result_type may be signed or unsigned, but the _range is always + // unsigned. + result_type _min, _max; + range_type _range; +}; + +} // namespace boost + +#endif // BOOST_RANDOM_UNIFORM_INT_HPP diff --git a/Boost/boost/random/uniform_on_sphere.hpp b/Boost/boost/random/uniform_on_sphere.hpp new file mode 100644 index 000000000..5dae3439a --- /dev/null +++ b/Boost/boost/random/uniform_on_sphere.hpp @@ -0,0 +1,101 @@ +/* boost random/uniform_on_sphere.hpp header file + * + * Copyright Jens Maurer 2000-2001 + * 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: uniform_on_sphere.hpp 60755 2010-03-22 00:45:06Z steven_watanabe $ + * + * Revision history + * 2001-02-18 moved to individual header files + */ + +#ifndef BOOST_RANDOM_UNIFORM_ON_SPHERE_HPP +#define BOOST_RANDOM_UNIFORM_ON_SPHERE_HPP + +#include +#include // std::transform +#include // std::bind2nd, std::divides +#include +#include + +namespace boost { + +/** + * Instantiations of class template uniform_on_sphere model a + * \random_distribution. Such a distribution produces random + * numbers uniformly distributed on the unit sphere of arbitrary + * dimension @c dim. The @c Cont template parameter must be a STL-like + * container type with begin and end operations returning non-const + * ForwardIterators of type @c Cont::iterator. Each invocation of the + * @c UniformRandomNumberGenerator shall result in a floating-point + * value in the range [0,1). + */ +template > +class uniform_on_sphere +{ +public: + typedef RealType input_type; + typedef Cont result_type; + + /** + * Constructs a @c uniform_on_sphere distribution. + * @c dim is the dimension of the sphere. + */ + explicit uniform_on_sphere(int dim = 2) : _container(dim), _dim(dim) { } + + // compiler-generated copy ctor and assignment operator are fine + + void reset() { _normal.reset(); } + + template + const result_type & operator()(Engine& eng) + { + RealType sqsum = 0; + for(typename Cont::iterator it = _container.begin(); + it != _container.end(); + ++it) { + RealType val = _normal(eng); + *it = val; + sqsum += val * val; + } +#ifndef BOOST_NO_STDC_NAMESPACE + using std::sqrt; +#endif + // for all i: result[i] /= sqrt(sqsum) + std::transform(_container.begin(), _container.end(), _container.begin(), + std::bind2nd(std::divides(), sqrt(sqsum))); + return _container; + } + +#ifndef BOOST_RANDOM_NO_STREAM_OPERATORS + template + friend std::basic_ostream& + operator<<(std::basic_ostream& os, const uniform_on_sphere& sd) + { + os << sd._dim; + return os; + } + + template + friend std::basic_istream& + operator>>(std::basic_istream& is, uniform_on_sphere& sd) + { + is >> std::ws >> sd._dim; + sd._container.resize(sd._dim); + return is; + } +#endif + +private: + normal_distribution _normal; + result_type _container; + int _dim; +}; + +} // namespace boost + +#endif // BOOST_RANDOM_UNIFORM_ON_SPHERE_HPP diff --git a/Boost/boost/random/uniform_real.hpp b/Boost/boost/random/uniform_real.hpp new file mode 100644 index 000000000..0a04540a6 --- /dev/null +++ b/Boost/boost/random/uniform_real.hpp @@ -0,0 +1,108 @@ +/* boost random/uniform_real.hpp header file + * + * Copyright Jens Maurer 2000-2001 + * 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: uniform_real.hpp 60755 2010-03-22 00:45:06Z steven_watanabe $ + * + * Revision history + * 2001-04-08 added min +#include +#include +#include +#include +#include + +namespace boost { + +/** + * The distribution function uniform_real models a random distribution. + * On each invocation, it returns a random floating-point value uniformly + * distributed in the range [min..max). The value is computed using + * std::numeric_limits::digits random binary digits, i.e. + * the mantissa of the floating-point value is completely filled with + * random bits. + * + * Note: The current implementation is buggy, because it may not fill + * all of the mantissa with random bits. + */ +template +class uniform_real +{ +public: + typedef RealType input_type; + typedef RealType result_type; + + /** + * Constructs a uniform_real object. @c min and @c max are the + * parameters of the distribution. + * + * Requires: min <= max + */ + explicit uniform_real(RealType min_arg = RealType(0), + RealType max_arg = RealType(1)) + : _min(min_arg), _max(max_arg) + { +#ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS + BOOST_STATIC_ASSERT(!std::numeric_limits::is_integer); +#endif + assert(min_arg <= max_arg); + } + + // compiler-generated copy ctor and assignment operator are fine + + /** + * Returns: The "min" parameter of the distribution + */ + result_type min BOOST_PREVENT_MACRO_SUBSTITUTION () const { return _min; } + /** + * Returns: The "max" parameter of the distribution + */ + result_type max BOOST_PREVENT_MACRO_SUBSTITUTION () const { return _max; } + void reset() { } + + template + result_type operator()(Engine& eng) { + result_type numerator = static_cast(eng() - eng.min BOOST_PREVENT_MACRO_SUBSTITUTION()); + result_type divisor = static_cast(eng.max BOOST_PREVENT_MACRO_SUBSTITUTION() - eng.min BOOST_PREVENT_MACRO_SUBSTITUTION()); + assert(divisor > 0); + assert(numerator >= 0 && numerator <= divisor); + return numerator / divisor * (_max - _min) + _min; + } + +#ifndef BOOST_RANDOM_NO_STREAM_OPERATORS + template + friend std::basic_ostream& + operator<<(std::basic_ostream& os, const uniform_real& ud) + { + os << ud._min << " " << ud._max; + return os; + } + + template + friend std::basic_istream& + operator>>(std::basic_istream& is, uniform_real& ud) + { + is >> std::ws >> ud._min >> std::ws >> ud._max; + return is; + } +#endif + +private: + RealType _min, _max; +}; + +} // namespace boost + +#endif // BOOST_RANDOM_UNIFORM_REAL_HPP diff --git a/Boost/boost/random/uniform_smallint.hpp b/Boost/boost/random/uniform_smallint.hpp new file mode 100644 index 000000000..93c7b63dc --- /dev/null +++ b/Boost/boost/random/uniform_smallint.hpp @@ -0,0 +1,158 @@ +/* boost random/uniform_smallint.hpp header file + * + * Copyright Jens Maurer 2000-2001 + * 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: uniform_smallint.hpp 60755 2010-03-22 00:45:06Z steven_watanabe $ + * + * Revision history + * 2001-04-08 added min +#include +#include +#include +#include +#include +#include +#include + +namespace boost { + +// uniform integer distribution on a small range [min, max] + +/** + * The distribution function uniform_smallint models a \random_distribution. + * On each invocation, it returns a random integer value uniformly distributed + * in the set of integer numbers {min, min+1, min+2, ..., max}. It assumes + * that the desired range (max-min+1) is small compared to the range of the + * underlying source of random numbers and thus makes no attempt to limit + * quantization errors. + * + * Let rout=(max-min+1) the desired range of integer numbers, and + * let rbase be the range of the underlying source of random + * numbers. Then, for the uniform distribution, the theoretical probability + * for any number i in the range rout will be pout(i) = + * 1/rout. Likewise, assume a uniform distribution on rbase for + * the underlying source of random numbers, i.e. pbase(i) = + * 1/rbase. Let pout_s(i) denote the random + * distribution generated by @c uniform_smallint. Then the sum over all + * i in rout of (pout_s(i)/pout(i) - 1)2 + * shall not exceed rout/rbase2 + * (rbase mod rout)(rout - + * rbase mod rout). + * + * The template parameter IntType shall denote an integer-like value type. + * + * Note: The property above is the square sum of the relative differences + * in probabilities between the desired uniform distribution + * pout(i) and the generated distribution pout_s(i). + * The property can be fulfilled with the calculation + * (base_rng mod rout), as follows: Let r = rbase mod + * rout. The base distribution on rbase is folded onto the + * range rout. The numbers i < r have assigned (rbase + * div rout)+1 numbers of the base distribution, the rest has + * only (rbase div rout). Therefore, + * pout_s(i) = ((rbase div rout)+1) / + * rbase for i < r and pout_s(i) = (rbase + * div rout)/rbase otherwise. Substituting this in the + * above sum formula leads to the desired result. + * + * Note: The upper bound for (rbase mod rout) + * (rout - rbase mod rout) is + * rout2/4. Regarding the upper bound for the + * square sum of the relative quantization error of + * rout3/(4*rbase2), it + * seems wise to either choose rbase so that rbase > + * 10*rout2 or ensure that rbase is + * divisible by rout. + */ +template +class uniform_smallint +{ +public: + typedef IntType input_type; + typedef IntType result_type; + + /** + * Constructs a @c uniform_smallint. @c min and @c max are the + * lower and upper bounds of the output range, respectively. + */ + explicit uniform_smallint(IntType min_arg = 0, IntType max_arg = 9) + : _min(min_arg), _max(max_arg) + { +#ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS + // MSVC fails BOOST_STATIC_ASSERT with std::numeric_limits at class scope + BOOST_STATIC_ASSERT(std::numeric_limits::is_integer); +#endif + } + + result_type min BOOST_PREVENT_MACRO_SUBSTITUTION () const { return _min; } + result_type max BOOST_PREVENT_MACRO_SUBSTITUTION () const { return _max; } + void reset() { } + + template + result_type operator()(Engine& eng) + { + typedef typename Engine::result_type base_result; + base_result _range = static_cast(_max-_min)+1; + base_result _factor = 1; + + // LCGs get bad when only taking the low bits. + // (probably put this logic into a partial template specialization) + // Check how many low bits we can ignore before we get too much + // quantization error. + base_result r_base = (eng.max)() - (eng.min)(); + if(r_base == (std::numeric_limits::max)()) { + _factor = 2; + r_base /= 2; + } + r_base += 1; + if(r_base % _range == 0) { + // No quantization effects, good + _factor = r_base / _range; + } else { + // carefully avoid overflow; pessimizing here + for( ; r_base/_range/32 >= _range; _factor *= 2) + r_base /= 2; + } + + return static_cast(((eng() - (eng.min)()) / _factor) % _range + _min); + } + +#ifndef BOOST_RANDOM_NO_STREAM_OPERATORS + template + friend std::basic_ostream& + operator<<(std::basic_ostream& os, const uniform_smallint& ud) + { + os << ud._min << " " << ud._max; + return os; + } + + template + friend std::basic_istream& + operator>>(std::basic_istream& is, uniform_smallint& ud) + { + is >> std::ws >> ud._min >> std::ws >> ud._max; + return is; + } +#endif + +private: + + result_type _min; + result_type _max; +}; + +} // namespace boost + +#endif // BOOST_RANDOM_UNIFORM_SMALLINT_HPP diff --git a/Boost/boost/random/variate_generator.hpp b/Boost/boost/random/variate_generator.hpp new file mode 100644 index 000000000..92c44e6ef --- /dev/null +++ b/Boost/boost/random/variate_generator.hpp @@ -0,0 +1,220 @@ +/* boost random/variate_generator.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: variate_generator.hpp 60755 2010-03-22 00:45:06Z steven_watanabe $ + * + */ + +#ifndef BOOST_RANDOM_RANDOM_GENERATOR_HPP +#define BOOST_RANDOM_RANDOM_GENERATOR_HPP + +#include + +// implementation details +#include +#include +#include +#include +#include + +// Borland C++ 5.6.0 has problems using its numeric_limits traits as +// template parameters +#if BOOST_WORKAROUND(__BORLANDC__, <= 0x564) +#include +#endif + +#include + +namespace boost { + +/// \cond hide_private_members + +namespace random { +namespace detail { + +template +struct engine_helper; + +// for consistency, always have two levels of decorations +template<> +struct engine_helper +{ + template + struct impl + { + typedef pass_through_engine type; + }; +}; + +template<> +struct engine_helper +{ + template + struct impl + { + typedef uniform_01 type; + }; +}; + +template<> +struct engine_helper +{ + template + struct impl + { + typedef uniform_01 type; + }; +}; + +template<> +struct engine_helper +{ + template + struct impl + { + typedef uniform_int_float type; + }; +}; + +} // namespace detail +} // namespace random + +///\endcond + +/** + * A random variate generator is used to join a random number + * generator together with a random number distribution. + * Boost.Random provides a vast choice of \generators as well + * as \distributions. + * + * Instantations of class template @c variate_generator model + * a \number_generator. + * + * The argument for the template parameter Engine shall be of + * the form U, U&, or U*, where U models a + * \uniform_random_number_generator. Then, the member + * engine_value_type names U (not the pointer or reference to U). + * + * Specializations of @c variate_generator satisfy the + * requirements of CopyConstructible. They also satisfy the + * requirements of Assignable unless the template parameter + * Engine is of the form U&. + * + * The complexity of all functions specified in this section + * is constant. No function described in this section except + * the constructor throws an exception. + */ +template +class variate_generator +{ +private: + typedef random::detail::pass_through_engine decorated_engine; + +public: + typedef typename decorated_engine::base_type engine_value_type; + typedef Engine engine_type; + typedef Distribution distribution_type; + typedef typename Distribution::result_type result_type; + + /** + * Constructs a @c variate_generator object with the associated + * \uniform_random_number_generator eng and the associated + * \random_distribution d. + * + * Throws: If and what the copy constructor of Engine or + * Distribution throws. + */ + variate_generator(Engine e, Distribution d) + : _eng(decorated_engine(e)), _dist(d) { } + + /** + * Returns: distribution()(e) + * + * Notes: The sequence of numbers produced by the + * \uniform_random_number_generator e, se, is + * obtained from the sequence of numbers produced by the + * associated \uniform_random_number_generator eng, seng, + * as follows: Consider the values of @c numeric_limits::is_integer + * for @c T both @c Distribution::input_type and + * @c engine_value_type::result_type. If the values for both types are + * true, then se is identical to seng. Otherwise, if the + * values for both types are false, then the numbers in seng + * are divided by engine().max()-engine().min() to obtain the numbers + * in se. Otherwise, if the value for + * @c engine_value_type::result_type is true and the value for + * @c Distribution::input_type is false, then the numbers in seng + * are divided by engine().max()-engine().min()+1 to obtain the numbers in + * se. Otherwise, the mapping from seng to + * se is implementation-defined. In all cases, an + * implicit conversion from @c engine_value_type::result_type to + * @c Distribution::input_type is performed. If such a conversion does + * not exist, the program is ill-formed. + */ + result_type operator()() { return _dist(_eng); } + /** + * Returns: distribution()(e, value). + * For the semantics of e, see the description of operator()(). + */ + template + result_type operator()(T value) { return _dist(_eng, value); } + + /** + * Returns: A reference to the associated uniform random number generator. + */ + engine_value_type& engine() { return _eng.base().base(); } + /** + * Returns: A reference to the associated uniform random number generator. + */ + const engine_value_type& engine() const { return _eng.base().base(); } + + /** + * Returns: A reference to the associated random distribution. + */ + distribution_type& distribution() { return _dist; } + /** + * Returns: A reference to the associated random distribution. + */ + const distribution_type& distribution() const { return _dist; } + + /** + * Precondition: distribution().min() is well-formed + * + * Returns: distribution().min() + */ + result_type min BOOST_PREVENT_MACRO_SUBSTITUTION () const { return (distribution().min)(); } + /** + * Precondition: distribution().max() is well-formed + * + * Returns: distribution().max() + */ + result_type max BOOST_PREVENT_MACRO_SUBSTITUTION () const { return (distribution().max)(); } + +private: +#if BOOST_WORKAROUND(__BORLANDC__, <= 0x564) + typedef typename random::detail::engine_helper< + ::boost::is_integral::value, + ::boost::is_integral::value + >::BOOST_NESTED_TEMPLATE impl::type internal_engine_type; +#else + enum { + have_int = std::numeric_limits::is_integer, + want_int = std::numeric_limits::is_integer + }; + typedef typename random::detail::engine_helper::BOOST_NESTED_TEMPLATE impl::type internal_engine_type; +#endif + + internal_engine_type _eng; + distribution_type _dist; +}; + +} // namespace boost + +#include + +#endif // BOOST_RANDOM_RANDOM_GENERATOR_HPP diff --git a/Boost/boost/random/xor_combine.hpp b/Boost/boost/random/xor_combine.hpp new file mode 100644 index 000000000..a8e991723 --- /dev/null +++ b/Boost/boost/random/xor_combine.hpp @@ -0,0 +1,184 @@ +/* boost random/xor_combine.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: xor_combine.hpp 60755 2010-03-22 00:45:06Z steven_watanabe $ + * + */ + +#ifndef BOOST_RANDOM_XOR_COMBINE_HPP +#define BOOST_RANDOM_XOR_COMBINE_HPP + +#include +#include +#include // for std::min and std::max +#include +#include +#include +#include // uint32_t +#include + + +namespace boost { +namespace random { + +/// \cond hide_private_members +#ifndef BOOST_NO_DEPENDENT_TYPES_IN_TEMPLATE_VALUE_PARAMETERS + #define BOOST_RANDOM_VAL_TYPE typename URNG1::result_type +#else + #define BOOST_RANDOM_VAL_TYPE uint32_t +#endif +/// \endcond + +/** + * Instantiations of @c xor_combine model a \pseudo_random_number_generator. + * To produce its output it invokes each of the base generators, shifts + * their results and xors them together. + */ +template +class xor_combine +{ +public: + typedef URNG1 base1_type; + typedef URNG2 base2_type; + typedef typename base1_type::result_type result_type; + + BOOST_STATIC_CONSTANT(bool, has_fixed_range = false); + BOOST_STATIC_CONSTANT(int, shift1 = s1); + BOOST_STATIC_CONSTANT(int, shift2 = s2); + + /** + * Constructors a @c xor_combine by default constructing + * both base generators. + */ + xor_combine() : _rng1(), _rng2() + { } + /** + * Constructs a @c xor_combine by copying two base generators. + */ + xor_combine(const base1_type & rng1, const base2_type & rng2) + : _rng1(rng1), _rng2(rng2) { } + /** + * Constructs a @c xor_combine, seeding both base generators + * with @c v. + */ + xor_combine(const result_type & v) + : _rng1(v), _rng2(v) { } + /** + * Constructs a @c xor_combine, seeding both base generators + * with values from the iterator range [first, last) and changes + * first to point to the element after the last one used. If there + * are not enough elements in the range to seed both generators, + * throws @c std::invalid_argument. + */ + template xor_combine(It& first, It last) + : _rng1(first, last), _rng2( /* advanced by other call */ first, last) { } + /** + * Calls @c seed() for both base generators. + */ + void seed() { _rng1.seed(); _rng2.seed(); } + /** + * @c seeds both base generators with @c v. + */ + void seed(const result_type & v) { _rng1.seed(v); _rng2.seed(v); } + /** + * seeds both base generators with values from the iterator + * range [first, last) and changes first to point to the element + * after the last one used. If there are not enough elements in + * the range to seed both generators, throws @c std::invalid_argument. + */ + template void seed(It& first, It last) + { + _rng1.seed(first, last); + _rng2.seed(first, last); + } + + /** Returns the first base generator. */ + const base1_type& base1() { return _rng1; } + /** Returns the second base generator. */ + const base2_type& base2() { return _rng2; } + + /** Returns the next value of the generator. */ + result_type operator()() + { + // MSVC fails BOOST_STATIC_ASSERT with std::numeric_limits at class scope +#if !defined(BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS) && !(defined(BOOST_MSVC) && BOOST_MSVC <= 1300) + BOOST_STATIC_ASSERT(std::numeric_limits::is_integer); + BOOST_STATIC_ASSERT(std::numeric_limits::is_integer); + BOOST_STATIC_ASSERT(std::numeric_limits::digits >= std::numeric_limits::digits); +#endif + return (_rng1() << s1) ^ (_rng2() << s2); + } + + /** + * Returns the smallest value that the generator can produce. + */ + result_type min BOOST_PREVENT_MACRO_SUBSTITUTION () const { return std::min BOOST_PREVENT_MACRO_SUBSTITUTION((_rng1.min)(), (_rng2.min)()); } + /** + * Returns the largest value that the generator can produce. + */ + result_type max BOOST_PREVENT_MACRO_SUBSTITUTION () const { return std::max BOOST_PREVENT_MACRO_SUBSTITUTION((_rng1.min)(), (_rng2.max)()); } + static bool validation(result_type x) { return val == x; } + +#ifndef BOOST_NO_OPERATORS_IN_NAMESPACE + +#ifndef BOOST_RANDOM_NO_STREAM_OPERATORS + template + friend std::basic_ostream& + operator<<(std::basic_ostream& os, const xor_combine& s) + { + os << s._rng1 << " " << s._rng2 << " "; + return os; + } + + template + friend std::basic_istream& + operator>>(std::basic_istream& is, xor_combine& s) + { + is >> s._rng1 >> std::ws >> s._rng2 >> std::ws; + return is; + } +#endif + + friend bool operator==(const xor_combine& x, const xor_combine& y) + { return x._rng1 == y._rng1 && x._rng2 == y._rng2; } + friend bool operator!=(const xor_combine& x, const xor_combine& y) + { return !(x == y); } +#else + // Use a member function; Streamable concept not supported. + bool operator==(const xor_combine& rhs) const + { return _rng1 == rhs._rng1 && _rng2 == rhs._rng2; } + bool operator!=(const xor_combine& rhs) const + { return !(*this == rhs); } +#endif + +private: + base1_type _rng1; + base2_type _rng2; +}; + +#ifndef BOOST_NO_INCLASS_MEMBER_INITIALIZATION +// A definition is required even for integral static constants +template +const bool xor_combine::has_fixed_range; +template +const int xor_combine::shift1; +template +const int xor_combine::shift2; +#endif + +#undef BOOST_RANDOM_VAL_TYPE + +} // namespace random +} // namespace boost + +#endif // BOOST_RANDOM_XOR_COMBINE_HPP diff --git a/Boost/lib/libboost_system-vc100-mt-1_44.lib b/Boost/lib/libboost_system-vc100-mt-1_44.lib new file mode 100644 index 0000000000000000000000000000000000000000..47510e6a56b3d0c709ba92d93ba8bd24b482ab25 GIT binary patch literal 83066 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 literal 0 HcmV?d00001 diff --git a/Boost/lib/libboost_system-vc100-mt-gd-1_44.lib b/Boost/lib/libboost_system-vc100-mt-gd-1_44.lib new file mode 100644 index 0000000000000000000000000000000000000000..49609c46b2e6300a614b0cc0a27a32626ee8a057 GIT binary patch literal 415016 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%0Dd!5=_8CmPY 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 literal 0 HcmV?d00001