From 9e0bca7c70734bb291d71a876d9dc3a59f2e07bc Mon Sep 17 00:00:00 2001 From: nobody Date: Wed, 6 Mar 2002 14:13:30 +0000 Subject: [PATCH] This commit was manufactured by cvs2svn to create tag 'perforce_2_4_merge_1'. [SVN r13112] --- histogram.cpp | 147 --- include/boost/random/additive_combine.hpp | 94 -- .../boost/random/bernoulli_distribution.hpp | 64 - include/boost/random/cauchy_distribution.hpp | 76 -- include/boost/random/detail/const_mod.hpp | 224 ---- .../boost/random/detail/iterator_mixin.hpp | 34 - .../random/detail/signed_unsigned_compare.hpp | 79 -- .../boost/random/exponential_distribution.hpp | 66 -- .../boost/random/geometric_distribution.hpp | 81 -- .../boost/random/inversive_congruential.hpp | 108 -- include/boost/random/lagged_fibonacci.hpp | 216 ---- include/boost/random/linear_congruential.hpp | 153 --- .../boost/random/lognormal_distribution.hpp | 83 -- include/boost/random/mersenne_twister.hpp | 244 ---- include/boost/random/normal_distribution.hpp | 96 -- .../boost/random/random_number_generator.hpp | 62 - include/boost/random/shuffle_output.hpp | 158 --- .../boost/random/triangle_distribution.hpp | 80 -- include/boost/random/uniform_01.hpp | 78 -- include/boost/random/uniform_int.hpp | 139 --- include/boost/random/uniform_on_sphere.hpp | 79 -- include/boost/random/uniform_real.hpp | 78 -- include/boost/random/uniform_smallint.hpp | 103 -- index.html | 143 --- integrate.hpp | 84 -- nondet_random.html | 121 -- nondet_random_speed.cpp | 69 -- random-concepts.html | 344 ------ random-distributions.html | 781 ------------ random-generators.html | 1042 ----------------- random-misc.html | 93 -- random-performance.html | 241 ---- random_demo.cpp | 126 -- random_device.cpp | 117 -- random_speed.cpp | 219 ---- random_test.cpp | 298 ----- statistic_tests.cpp | 669 ----------- statistic_tests.hpp | 641 ---------- 38 files changed, 7530 deletions(-) delete mode 100644 histogram.cpp delete mode 100644 include/boost/random/additive_combine.hpp delete mode 100644 include/boost/random/bernoulli_distribution.hpp delete mode 100644 include/boost/random/cauchy_distribution.hpp delete mode 100644 include/boost/random/detail/const_mod.hpp delete mode 100644 include/boost/random/detail/iterator_mixin.hpp delete mode 100644 include/boost/random/detail/signed_unsigned_compare.hpp delete mode 100644 include/boost/random/exponential_distribution.hpp delete mode 100644 include/boost/random/geometric_distribution.hpp delete mode 100644 include/boost/random/inversive_congruential.hpp delete mode 100644 include/boost/random/lagged_fibonacci.hpp delete mode 100644 include/boost/random/linear_congruential.hpp delete mode 100644 include/boost/random/lognormal_distribution.hpp delete mode 100644 include/boost/random/mersenne_twister.hpp delete mode 100644 include/boost/random/normal_distribution.hpp delete mode 100644 include/boost/random/random_number_generator.hpp delete mode 100644 include/boost/random/shuffle_output.hpp delete mode 100644 include/boost/random/triangle_distribution.hpp delete mode 100644 include/boost/random/uniform_01.hpp delete mode 100644 include/boost/random/uniform_int.hpp delete mode 100644 include/boost/random/uniform_on_sphere.hpp delete mode 100644 include/boost/random/uniform_real.hpp delete mode 100644 include/boost/random/uniform_smallint.hpp delete mode 100644 index.html delete mode 100644 integrate.hpp delete mode 100644 nondet_random.html delete mode 100644 nondet_random_speed.cpp delete mode 100644 random-concepts.html delete mode 100644 random-distributions.html delete mode 100644 random-generators.html delete mode 100644 random-misc.html delete mode 100644 random-performance.html delete mode 100644 random_demo.cpp delete mode 100644 random_device.cpp delete mode 100644 random_speed.cpp delete mode 100644 random_test.cpp delete mode 100644 statistic_tests.cpp delete mode 100644 statistic_tests.hpp diff --git a/histogram.cpp b/histogram.cpp deleted file mode 100644 index bed5905..0000000 --- a/histogram.cpp +++ /dev/null @@ -1,147 +0,0 @@ -/* boost histogram.cpp graphical verification of distribution functions - * - * Copyright Jens Maurer 2000 - * Permission to use, copy, modify, sell, and distribute this software - * is hereby granted without fee provided that the above copyright notice - * appears in all copies and that both that copyright notice and this - * permission notice appear in supporting documentation, - * - * Jens Maurer makes no representations about the suitability of this - * software for any purpose. It is provided "as is" without express or - * implied warranty. - * - * $Id$ - * - * This test program allows to visibly examine the results of the - * distribution functions. - */ - -#include -#include -#include -#include -#include -#include -#include - - -void plot_histogram(const std::vector& slots, int samples, - double from, double to) -{ - int m = *std::max_element(slots.begin(), slots.end()); - const int nRows = 20; - std::cout.setf(std::ios::fixed|std::ios::left); - std::cout.precision(5); - for(int r = 0; r < nRows; r++) { - double y = ((nRows - r) * double(m))/(nRows * samples); - std::cout << std::setw(10) << y << " "; - for(unsigned int col = 0; col < slots.size(); col++) { - char out = ' '; - if(slots[col]/double(samples) >= y) - out = 'x'; - std::cout << out; - } - std::cout << std::endl; - } - std::cout << std::setw(12) << " " - << std::setw(10) << from; - std::cout.setf(std::ios::right, std::ios::adjustfield); - std::cout << std::setw(slots.size()-10) << to << std::endl; -} - -// I am not sure whether these two should be in the library as well - -// maintain sum of NumberGenerator results -template -class sum_result -{ -public: - typedef NumberGenerator base_type; - typedef typename base_type::result_type result_type; - explicit sum_result(const base_type & g) : gen(g), _sum(0) { } - result_type operator()() { result_type r = gen(); _sum += r; return r; } - base_type & base() { return gen; } - Sum sum() const { return _sum; } - void reset() { _sum = 0; } -private: - base_type gen; - Sum _sum; -}; - - -// maintain square sum of NumberGenerator results -template -class squaresum_result -{ -public: - typedef NumberGenerator base_type; - typedef typename base_type::result_type result_type; - explicit squaresum_result(const base_type & g) : gen(g), _sum(0) { } - result_type operator()() { result_type r = gen(); _sum += r*r; return r; } - base_type & base() { return gen; } - Sum squaresum() const { return _sum; } - void reset() { _sum = 0; } -private: - base_type gen; - Sum _sum; -}; - - -template -void histogram(RNG base, int samples, double from, double to, - const std::string & name) -{ - typedef squaresum_result, double > SRNG; - SRNG gen((sum_result(base))); - const int nSlots = 60; - std::vector slots(nSlots,0); - for(int i = 0; i < samples; i++) { - double val = gen(); - if(val < from || val >= to) // early check avoids overflow - continue; - int slot = int((val-from)/(to-from) * nSlots); - if(slot < 0 || slot > (int)slots.size()) - continue; - slots[slot]++; - } - std::cout << name << std::endl; - plot_histogram(slots, samples, from, to); - double mean = gen.base().sum() / samples; - std::cout << "mean: " << mean - << " sigma: " << std::sqrt(gen.squaresum()/samples-mean*mean) - << "\n" << std::endl; -} - - -template -void histograms() -{ - PRNG rng; - using namespace boost; - histogram(uniform_01(rng), 100000, -0.5, 1.5, "uniform_01(0,1)"); - histogram(bernoulli_distribution(rng, 0.2), 100000, -0.5, 1.5, - "bernoulli(0.2)"); - histogram(triangle_distribution(rng, 1, 2, 8), 100000, 0, 10, - "triangle(1,2,8)"); - histogram(geometric_distribution(rng, 5.0/6.0), 100000, 0, 10, - "geometric(5/6)"); - histogram(exponential_distribution(rng, 0.3), 100000, 0, 10, - "exponential(0.3)"); - histogram(cauchy_distribution(rng), 100000, -5, 5, - "cauchy"); - histogram(lognormal_distribution(rng, 3, 2), 100000, 0, 10, - "lognormal"); - histogram(normal_distribution(rng), 100000, -3, 3, - "normal"); - histogram(normal_distribution(rng, 0.5, 0.5), 100000, -3, 3, - "normal(0.5, 0.5)"); -} - - -int main() -{ - histograms(); -} - diff --git a/include/boost/random/additive_combine.hpp b/include/boost/random/additive_combine.hpp deleted file mode 100644 index 4ad8a97..0000000 --- a/include/boost/random/additive_combine.hpp +++ /dev/null @@ -1,94 +0,0 @@ -/* boost random/additive_combine.hpp header file - * - * Copyright Jens Maurer 2000-2001 - * Permission to use, copy, modify, sell, and distribute this software - * is hereby granted without fee provided that the above copyright notice - * appears in all copies and that both that copyright notice and this - * permission notice appear in supporting documentation, - * - * Jens Maurer makes no representations about the suitability of this - * software for any purpose. It is provided "as is" without express or - * implied warranty. - * - * See http://www.boost.org for most recent version including documentation. - * - * $Id$ - * - * Revision history - * 2001-02-18 moved to individual header files - */ - -#ifndef BOOST_RANDOM_ADDITIVE_COMBINE_HPP -#define BOOST_RANDOM_ADDITIVE_COMBINE_HPP - -#include -#include -#include -#include - -namespace boost { -namespace random { - -// L'Ecuyer 1988 -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 - result_type min() const { return 1; } - result_type max() const { return _mlcg1.max()-1; } - - additive_combine() : _mlcg1(), _mlcg2() { } - additive_combine(typename MLCG1::result_type seed1, - typename MLCG2::result_type seed2) - : _mlcg1(seed1), _mlcg2(seed2) { } - result_type operator()() { - result_type z = _mlcg1() - _mlcg2(); - if(z < 1) - z += MLCG1::modulus-1; - return z; - } - bool validation(result_type x) const { return val == x; } - -#ifndef BOOST_NO_OPERATORS_IN_NAMESPACE - friend std::ostream& operator<<(std::ostream& os, const additive_combine& r) - { os << r._mlcg1 << " " << r._mlcg2; return os; } - friend std::istream& operator>>(std::istream& is, additive_combine& r) - { is >> r._mlcg1 >> std::ws >> r._mlcg2; return is; } - friend bool operator==(const additive_combine& x, const additive_combine& y) - { return x._mlcg1 == y._mlcg1 && x._mlcg2 == y._mlcg2; } -#else - // Use a member function; Streamable concept not supported. - bool operator==(const additive_combine& rhs) const - { return _mlcg1 == rhs._mlcg1 && _mlcg2 == rhs._mlcg2; } -#endif -private: - MLCG1 _mlcg1; - MLCG2 _mlcg2; -}; - -} // namespace random - -typedef random::additive_combine< - random::linear_congruential, - random::linear_congruential, - 2060321752> ecuyer1988; - -} // namespace boost - -#endif // BOOST_RANDOM_ADDITIVE_COMBINE_HPP diff --git a/include/boost/random/bernoulli_distribution.hpp b/include/boost/random/bernoulli_distribution.hpp deleted file mode 100644 index b0fa912..0000000 --- a/include/boost/random/bernoulli_distribution.hpp +++ /dev/null @@ -1,64 +0,0 @@ -/* boost random/bernoulli_distribution.hpp header file - * - * Copyright Jens Maurer 2000-2001 - * Permission to use, copy, modify, sell, and distribute this software - * is hereby granted without fee provided that the above copyright notice - * appears in all copies and that both that copyright notice and this - * permission notice appear in supporting documentation, - * - * Jens Maurer makes no representations about the suitability of this - * software for any purpose. It is provided "as is" without express or - * implied warranty. - * - * See http://www.boost.org for most recent version including documentation. - * - * $Id$ - * - * Revision history - * 2001-02-18 moved to individual header files - */ - -#ifndef BOOST_RANDOM_BERNOULLI_DISTRIBUTION_HPP -#define BOOST_RANDOM_BERNOULLI_DISTRIBUTION_HPP - -#include - -namespace boost { - -// Bernoulli distribution: p(true) = p, p(false) = 1-p (boolean) -template -class bernoulli_distribution -{ -public: - typedef UniformRandomNumberGenerator base_type; - typedef bool result_type; - bernoulli_distribution(base_type & rng, double p) - : _rng(rng), - _threshold(static_cast - (p * (_rng.max() - _rng.min())) + _rng.min()) - { - // for p == 0, we can only set _threshold = 0, which is not enough - assert(p > 0); - } - // compiler-generated copy ctor is fine - // assignment is disallowed because there is a reference member - - result_type operator()() { return _rng() <= _threshold; } -#ifndef BOOST_NO_OPERATORS_IN_NAMESPACE - friend bool operator==(const bernoulli_distribution& x, - const bernoulli_distribution& y) - { return x._threshold == y._threshold && x._rng == y._rng; } -#else - // Use a member function - bool operator==(const bernoulli_distribution& rhs) const - { return _threshold == rhs._threshold && _rng == rhs._rng; } -#endif -private: - typedef typename base_type::result_type base_result; - base_type & _rng; - const base_result _threshold; -}; - -} // namespace boost - -#endif // BOOST_RANDOM_BERNOULLI_DISTRIBUTION_HPP diff --git a/include/boost/random/cauchy_distribution.hpp b/include/boost/random/cauchy_distribution.hpp deleted file mode 100644 index ee9c114..0000000 --- a/include/boost/random/cauchy_distribution.hpp +++ /dev/null @@ -1,76 +0,0 @@ -/* boost random/cauchy_distribution.hpp header file - * - * Copyright Jens Maurer 2000-2001 - * Permission to use, copy, modify, sell, and distribute this software - * is hereby granted without fee provided that the above copyright notice - * appears in all copies and that both that copyright notice and this - * permission notice appear in supporting documentation, - * - * Jens Maurer makes no representations about the suitability of this - * software for any purpose. It is provided "as is" without express or - * implied warranty. - * - * See http://www.boost.org for most recent version including documentation. - * - * $Id$ - * - * Revision history - * 2001-02-18 moved to individual header files - */ - -#ifndef BOOST_RANDOM_CAUCHY_DISTRIBUTION_HPP -#define BOOST_RANDOM_CAUCHY_DISTRIBUTION_HPP - -#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: p(x) = sigma/(pi*(sigma**2 + (x-median)**2)) -template -class cauchy_distribution -{ -public: - typedef UniformRandomNumberGenerator base_type; - typedef RealType result_type; - - cauchy_distribution(base_type & rng, result_type median = 0, - result_type sigma = 1) - : _rng(rng), _median(median), _sigma(sigma) { } - // compiler-generated copy constructor is fine - // uniform_01 cannot be assigned, neither can this class - result_type operator()() - { - const double pi = 3.14159265358979323846; -#ifndef BOOST_NO_STDC_NAMESPACE - using std::tan; -#endif - return _median + _sigma * tan(pi*(_rng()-0.5)); - } -#ifndef BOOST_NO_OPERATORS_IN_NAMESPACE - friend bool operator==(const cauchy_distribution& x, - const cauchy_distribution& y) - { - return x._median == y._median && x._sigma == y._sigma && x._rng == y._rng; - } -#else - // Use a member function - bool operator==(const cauchy_distribution& rhs) const - { - return _median == rhs._median && _sigma == rhs._sigma && _rng == rhs._rng; - } -#endif -private: - uniform_01 _rng; - result_type _median, _sigma; -}; - -} // namespace boost - -#endif // BOOST_RANDOM_CAUCHY_DISTRIBUTION_HPP diff --git a/include/boost/random/detail/const_mod.hpp b/include/boost/random/detail/const_mod.hpp deleted file mode 100644 index 9394ce4..0000000 --- a/include/boost/random/detail/const_mod.hpp +++ /dev/null @@ -1,224 +0,0 @@ -/* boost random/detail/const_mod.hpp header file - * - * Copyright Jens Maurer 2000-2001 - * Permission to use, copy, modify, sell, and distribute this software - * is hereby granted without fee provided that the above copyright notice - * appears in all copies and that both that copyright notice and this - * permission notice appear in supporting documentation, - * - * Jens Maurer makes no representations about the suitability of this - * software for any purpose. It is provided "as is" without express or - * implied warranty. - * - * See http://www.boost.org for most recent version including documentation. - * - * $Id$ - * - * 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 - -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) - { - x += (c-m); - if(x < 0) - x += m; - return x; - } - }; - - template<> - struct do_add - { - template - static IntType add(IntType, IntType, IntType) - { - // difficult - assert(!"const_mod::add with c too large"); - return 0; - } - }; -} // namespace detail - - -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); - 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); - } - } -}; - -// 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 */ - -} // namespace random -} // namespace boost - -#endif // BOOST_RANDOM_CONST_MOD_HPP diff --git a/include/boost/random/detail/iterator_mixin.hpp b/include/boost/random/detail/iterator_mixin.hpp deleted file mode 100644 index 4ca4ad3..0000000 --- a/include/boost/random/detail/iterator_mixin.hpp +++ /dev/null @@ -1,34 +0,0 @@ - -#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/include/boost/random/detail/signed_unsigned_compare.hpp b/include/boost/random/detail/signed_unsigned_compare.hpp deleted file mode 100644 index 8162bb6..0000000 --- a/include/boost/random/detail/signed_unsigned_compare.hpp +++ /dev/null @@ -1,79 +0,0 @@ - -#ifndef BOOST_RANDOM_DETAIL_SIGNED_UNSIGNED_COMPARE -#define BOOST_RANDOM_DETAIL_SIGNED_UNSIGNED_COMPARE - -#include - -namespace boost { -namespace random { - -/* - * Correctly compare two numbers whose types possibly differ in signedness. - * See boost::numeric_cast<> for the general idea. - * Most "if" statements involve only compile-time constants, so the - * optimizing compiler can do its job easily. - * - * With most compilers, the straightforward implementation produces a - * bunch of (legitimate) warnings. Some template magic helps, though. - */ - -namespace detail { -template -struct do_compare -{ }; - -template<> -struct do_compare -{ - // cast to the larger type is automatic with built-in types - template - static bool equal(T1 x, T2 y) { return x == y; } - template - static bool lessthan(T1 x, T2 y) { return x < y; } -}; - -template<> -struct do_compare : do_compare -{ }; - -template<> -struct do_compare -{ - template - static bool equal(T1 x, T2 y) { return x >= 0 && static_cast(x) == y; } - template - static bool lessthan(T1 x, T2 y) { return x < 0 || static_cast(x) < y; } -}; - -template<> -struct do_compare -{ - template - static bool equal(T1 x, T2 y) { return y >= 0 && x == static_cast(y); } - template - static bool lessthan(T1 x, T2 y) { return y >= 0 && x < static_cast(y); } -}; - -} // namespace detail - - -template -int equal_signed_unsigned(T1 x, T2 y) -{ - typedef std::numeric_limits x_traits; - typedef std::numeric_limits y_traits; - return detail::do_compare::equal(x, y); -} - -template -int lessthan_signed_unsigned(T1 x, T2 y) -{ - typedef std::numeric_limits x_traits; - typedef std::numeric_limits y_traits; - return detail::do_compare::lessthan(x, y); -} - -} // namespace random -} // namespace boost - -#endif // BOOST_RANDOM_DETAIL_SIGNED_UNSIGNED_COMPARE diff --git a/include/boost/random/exponential_distribution.hpp b/include/boost/random/exponential_distribution.hpp deleted file mode 100644 index e4eaa6c..0000000 --- a/include/boost/random/exponential_distribution.hpp +++ /dev/null @@ -1,66 +0,0 @@ -/* boost random/exponential_distribution.hpp header file - * - * Copyright Jens Maurer 2000-2001 - * Permission to use, copy, modify, sell, and distribute this software - * is hereby granted without fee provided that the above copyright notice - * appears in all copies and that both that copyright notice and this - * permission notice appear in supporting documentation, - * - * Jens Maurer makes no representations about the suitability of this - * software for any purpose. It is provided "as is" without express or - * implied warranty. - * - * See http://www.boost.org for most recent version including documentation. - * - * $Id$ - * - * 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 - -namespace boost { - -// exponential distribution: p(x) = lambda * exp(-lambda * x) -template -class exponential_distribution -{ -public: - typedef UniformRandomNumberGenerator base_type; - typedef RealType result_type; - - exponential_distribution(base_type& rng, result_type lambda) - : _rng(rng), _lambda(lambda) { assert(lambda > 0); } - // compiler-generated copy ctor is fine - // uniform_01 cannot be assigned, neither can this class - result_type operator()() - { -#ifndef BOOST_NO_STDC_NAMESPACE - using std::log; -#endif - return -1.0 / _lambda * log(1-_rng()); - } - -#ifndef BOOST_NO_OPERATORS_IN_NAMESPACE - friend bool operator==(const exponential_distribution& x, - const exponential_distribution& y) - { return x._lambda == y._lambda && x._rng == y._rng; } -#else - // Use a member function - bool operator==(const exponential_distribution& rhs) const - { return _lambda == rhs._lambda && _rng == rhs._rng; } -#endif -private: - uniform_01 _rng; - const result_type _lambda; -}; - -} // namespace boost - -#endif // BOOST_RANDOM_EXPONENTIAL_DISTRIBUTION_HPP diff --git a/include/boost/random/geometric_distribution.hpp b/include/boost/random/geometric_distribution.hpp deleted file mode 100644 index 1283c0c..0000000 --- a/include/boost/random/geometric_distribution.hpp +++ /dev/null @@ -1,81 +0,0 @@ -/* boost random/geometric_distribution.hpp header file - * - * Copyright Jens Maurer 2000-2001 - * Permission to use, copy, modify, sell, and distribute this software - * is hereby granted without fee provided that the above copyright notice - * appears in all copies and that both that copyright notice and this - * permission notice appear in supporting documentation, - * - * Jens Maurer makes no representations about the suitability of this - * software for any purpose. It is provided "as is" without express or - * implied warranty. - * - * See http://www.boost.org for most recent version including documentation. - * - * $Id$ - * - * 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 - -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 - -// geometric distribution: p(i) = (1-p) * pow(p, i-1) (integer) -template -class geometric_distribution -{ -public: - typedef UniformRandomNumberGenerator base_type; - typedef IntType result_type; - - geometric_distribution(base_type & rng, double p) - : _rng(rng) - { - assert(0.0 < p && p < 1.0); -#ifndef BOOST_NO_STDC_NAMESPACE - using std::log; -#endif - _log_p = log(p); - } - // compiler-generated copy ctor is fine - // uniform_01 cannot be assigned, neither can this class - - result_type operator()() - { -#ifndef BOOST_NO_STDC_NAMESPACE - using std::log; -#endif - return IntType (log(1-_rng()) / _log_p) + 1; - } - -#ifndef BOOST_NO_OPERATORS_IN_NAMESPACE - friend bool operator==(const geometric_distribution& x, - const geometric_distribution& y) - { return x._log_p == y._log_p && x._rng == y._rng; } -#else - // Use a member function - bool operator==(const geometric_distribution& rhs) const - { return _log_p == rhs._log_p && _rng == rhs._rng; } -#endif -private: - uniform_01 _rng; - typename uniform_01::result_type _log_p; -}; - -} // namespace boost - -#endif // BOOST_RANDOM_GEOMETRIC_DISTRIBUTION_HPP - diff --git a/include/boost/random/inversive_congruential.hpp b/include/boost/random/inversive_congruential.hpp deleted file mode 100644 index f6068a0..0000000 --- a/include/boost/random/inversive_congruential.hpp +++ /dev/null @@ -1,108 +0,0 @@ -/* boost random/inversive_congruential.hpp header file - * - * Copyright Jens Maurer 2000-2001 - * Permission to use, copy, modify, sell, and distribute this software - * is hereby granted without fee provided that the above copyright notice - * appears in all copies and that both that copyright notice and this - * permission notice appear in supporting documentation, - * - * Jens Maurer makes no representations about the suitability of this - * software for any purpose. It is provided "as is" without express or - * implied warranty. - * - * See http://www.boost.org for most recent version including documentation. - * - * $Id$ - * - * 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 - -namespace boost { -namespace random { - -// Eichenauer and Lehn 1986 -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() const { return b == 0 ? 1 : 0; } - result_type max() const { return p-1; } - - 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); - } - void seed(IntType y0) { value = y0; if(b == 0) assert(y0 > 0); } - IntType operator()() - { - typedef const_mod do_mod; - value = do_mod::mult_add(a, do_mod::invert(value), b); - return value; - } - bool validation(result_type x) const { return val == x; } - -#ifndef BOOST_NO_OPERATORS_IN_NAMESPACE - friend std::ostream& operator<<(std::ostream& os, inversive_congruential x) - { os << x.value; return os; } - friend std::istream& operator>>(std::istream& is, inversive_congruential& x) - { is >> x.value; return is; } - friend bool operator==(inversive_congruential x, inversive_congruential y) - { return x.value == y.value; } -#else - // Use a member function; Streamable concept not supported. - bool operator==(inversive_congruential rhs) const - { return value == rhs.value; } -#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 - -typedef random::inversive_congruential hellekalek1995; - -} // namespace boost - -#endif // BOOST_RANDOM_INVERSIVE_CONGRUENTIAL_HPP diff --git a/include/boost/random/lagged_fibonacci.hpp b/include/boost/random/lagged_fibonacci.hpp deleted file mode 100644 index c63e4cf..0000000 --- a/include/boost/random/lagged_fibonacci.hpp +++ /dev/null @@ -1,216 +0,0 @@ -/* boost random/lagged_fibonacci.hpp header file - * - * Copyright Jens Maurer 2000-2001 - * Permission to use, copy, modify, sell, and distribute this software - * is hereby granted without fee provided that the above copyright notice - * appears in all copies and that both that copyright notice and this - * permission notice appear in supporting documentation, - * - * Jens Maurer makes no representations about the suitability of this - * software for any purpose. It is provided "as is" without express or - * implied warranty. - * - * See http://www.boost.org for most recent version including documentation. - * - * $Id$ - * - * Revision history - * 2001-02-18 moved to individual header files - */ - -#ifndef BOOST_RANDOM_LAGGED_FIBONACCI_HPP -#define BOOST_RANDOM_LAGGED_FIBONACCI_HPP - -#include -#include // std::max -#include -#include -#include -#include -#include - -namespace boost { -namespace random { - -// 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 - -template -class lagged_fibonacci -{ -public: - typedef FloatType result_type; - BOOST_STATIC_CONSTANT(bool, has_fixed_range = false); - BOOST_STATIC_CONSTANT(unsigned int, long_lag = p); - BOOST_STATIC_CONSTANT(unsigned int, short_lag = q); - - result_type min() const { return 0.0; } - result_type max() const { return 1.0; } - - lagged_fibonacci() { seed(); } - explicit lagged_fibonacci(uint32_t value) { seed(value); } - template - explicit lagged_fibonacci(Generator & gen) { seed(gen); } - // compiler-generated copy ctor and assignment operator are fine - - void seed(uint32_t value = 331u) - { - minstd_rand0 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. - template - void seed(Generator & gen) - { - uniform_01 gen01(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; - } - - result_type operator()() - { - if(i >= long_lag) - fill(); - return x[i++]; - } - - bool validation(result_type x) const - { - 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 - friend std::ostream& operator<<(std::ostream& os, const lagged_fibonacci& f) - { - os << f.i << " "; - std::streamsize prec = - os.precision(std::numeric_limits::digits10); - for(unsigned int i = 0; i < long_lag; ++i) - os << f.x[i] << " "; - os.precision(prec); - return os; - } - friend std::istream& operator>>(std::istream& is, lagged_fibonacci& f) - { - is >> f.i >> std::ws; - for(unsigned int i = 0; i < long_lag; ++i) - is >> f.x[i] >> std::ws; - return is; - } - 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); } -#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); } -#endif - -private: - void fill(); - unsigned int i; - FloatType 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 - -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) { - FloatType t = x[j] + x[j+(long_lag-short_lag)]; - if(t >= 1.0) - t -= 1.0; - x[j] = t; - } - } - for(unsigned int j = short_lag; j < long_lag; ++j) { - FloatType t = x[j] + x[j-short_lag]; - if(t >= 1.0) - t -= 1.0; - x[j] = t; - } - i = 0; -} - -} // namespace random - -typedef random::lagged_fibonacci lagged_fibonacci607; -typedef random::lagged_fibonacci lagged_fibonacci1279; -typedef random::lagged_fibonacci lagged_fibonacci2281; -typedef random::lagged_fibonacci lagged_fibonacci3217; -typedef random::lagged_fibonacci lagged_fibonacci4423; -typedef random::lagged_fibonacci lagged_fibonacci9689; -typedef random::lagged_fibonacci lagged_fibonacci19937; -typedef random::lagged_fibonacci lagged_fibonacci23209; -typedef random::lagged_fibonacci lagged_fibonacci44497; - - -// It is possible to partially specialize uniform_01<> on lagged_fibonacci<> -// 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/include/boost/random/linear_congruential.hpp b/include/boost/random/linear_congruential.hpp deleted file mode 100644 index 92bda30..0000000 --- a/include/boost/random/linear_congruential.hpp +++ /dev/null @@ -1,153 +0,0 @@ -/* boost random/linear_congruential.hpp header file - * - * Copyright Jens Maurer 2000-2001 - * Permission to use, copy, modify, sell, and distribute this software - * is hereby granted without fee provided that the above copyright notice - * appears in all copies and that both that copyright notice and this - * permission notice appear in supporting documentation, - * - * Jens Maurer makes no representations about the suitability of this - * software for any purpose. It is provided "as is" without express or - * implied warranty. - * - * See http://www.boost.org for most recent version including documentation. - * - * $Id$ - * - * 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 - -namespace boost { -namespace random { - -// compile-time configurable linear congruential generator -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); - - result_type min() const { return c == 0 ? 1 : 0; } - result_type max() const { return m-1; } - explicit linear_congruential(IntType x0 = 1) - : _x(x0) - { - assert(c || x0); /* if c == 0 and x(0) == 0 then x(n) = 0 for all n */ - // overflow check - // disabled because it gives spurious "divide by zero" gcc warnings - // assert(m == 0 || (a*(m-1)+c) % m == (c < a ? c-a+m : c-a)); - } - // compiler-generated copy constructor and assignment operator are fine - void seed(IntType x0) { assert(c || x0); _x = x0; } - IntType operator()() - { - _x = const_mod::mult_add(a, _x, c); - return _x; - } - bool validation(IntType x) const { return val == x; } - -#ifndef BOOST_NO_OPERATORS_IN_NAMESPACE - friend std::ostream& operator<<(std::ostream& os, - const linear_congruential& lcg) - { os << lcg._x; return os; } - friend std::istream& operator>>(std::istream& is, linear_congruential& lcg) - { is >> lcg._x; return is; } - friend bool operator==(const linear_congruential& x, - const linear_congruential& y) - { return x._x == y._x; } -#else - // Use a member function; Streamable concept not supported. - bool operator==(const linear_congruential& rhs) const - { return _x == rhs._x; } -#endif -private: - IntType _x; -}; - -#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; -#endif - -} // namespace random - -// validation values from the publications -typedef random::linear_congruential minstd_rand0; -typedef random::linear_congruential minstd_rand; - - -#if !defined(BOOST_NO_INT64_T) && !defined(BOOST_NO_INTEGRAL_INT64_T) -// emulate the lrand48() C library function; requires support for uint64_t -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 - int32_t min() const { return 0; } - int32_t max() const { return std::numeric_limits::max(); } - - explicit rand48(int32_t x0 = 1) : lcf(cnv(x0)) { } - explicit rand48(uint64_t x0) : lcf(x0) { } - // compiler-generated copy ctor and assignment operator are fine - void seed(int32_t x0) { lcf.seed(cnv(x0)); } - void seed(uint64_t x0) { lcf.seed(x0); } - int32_t operator()() { return lcf() >> 17; } - // by experiment from lrand48() - bool validation(int32_t x) const { return x == 1993516219; } - -#ifndef BOOST_NO_OPERATORS_IN_NAMESPACE - friend std::ostream& operator<<(std::ostream& os, const rand48& r) - { os << r.lcf; return os; } - friend std::istream& operator>>(std::istream& is, rand48& r) - { is >> r.lcf; return is; } - friend bool operator==(const rand48& x, const rand48& y) - { return x.lcf == y.lcf; } -#else - // Use a member function; Streamable concept not supported. - bool operator==(const rand48& rhs) const - { return lcf == rhs.lcf; } -#endif -private: - random::linear_congruential lcf; - static uint64_t cnv(int32_t x) - { return (static_cast(x) << 16) | 0x330e; } -}; -#endif /* !BOOST_NO_INT64_T && !BOOST_NO_INTEGRAL_INT64_T */ - -} // namespace boost - -#endif // BOOST_RANDOM_LINEAR_CONGRUENTIAL_HPP diff --git a/include/boost/random/lognormal_distribution.hpp b/include/boost/random/lognormal_distribution.hpp deleted file mode 100644 index 4109cc8..0000000 --- a/include/boost/random/lognormal_distribution.hpp +++ /dev/null @@ -1,83 +0,0 @@ -/* boost random/lognormal_distribution.hpp header file - * - * Copyright Jens Maurer 2000-2001 - * Permission to use, copy, modify, sell, and distribute this software - * is hereby granted without fee provided that the above copyright notice - * appears in all copies and that both that copyright notice and this - * permission notice appear in supporting documentation, - * - * Jens Maurer makes no representations about the suitability of this - * software for any purpose. It is provided "as is" without express or - * implied warranty. - * - * See http://www.boost.org for most recent version including documentation. - * - * $Id$ - * - * 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 - -#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 - -template -class lognormal_distribution -{ -public: - typedef UniformRandomNumberGenerator base_type; - typedef RealType result_type; - lognormal_distribution(base_type & rng, result_type mean, - result_type sigma) - : _rng(rng, std::log(mean*mean/std::sqrt(sigma*sigma + mean*mean)), - std::sqrt(std::log(sigma*sigma/mean/mean+1))) - { - assert(mean > 0); - } - // compiler-generated copy constructor is fine - // normal_distribution cannot be assigned, neither can this class - result_type operator()() - { -#ifndef BOOST_NO_STDC_NAMESPACE - // allow for Koenig lookup - using std::exp; -#endif - return exp(_rng()); - } - -#ifndef BOOST_NO_OPERATORS_IN_NAMESPACE - friend bool operator==(const lognormal_distribution& x, - const lognormal_distribution& y) - { return x._rng == y._rng; } -#else - // Use a member function - bool operator==(const lognormal_distribution& rhs) const - { return _rng == rhs._rng; } -#endif -private: - normal_distribution _rng; -}; - -} // namespace boost - -#endif // BOOST_RANDOM_LOGNORMAL_DISTRIBUTION_HPP diff --git a/include/boost/random/mersenne_twister.hpp b/include/boost/random/mersenne_twister.hpp deleted file mode 100644 index 2ec9657..0000000 --- a/include/boost/random/mersenne_twister.hpp +++ /dev/null @@ -1,244 +0,0 @@ -/* boost random/mersenne_twister.hpp header file - * - * Copyright Jens Maurer 2000-2001 - * Permission to use, copy, modify, sell, and distribute this software - * is hereby granted without fee provided that the above copyright notice - * appears in all copies and that both that copyright notice and this - * permission notice appear in supporting documentation, - * - * Jens Maurer makes no representations about the suitability of this - * software for any purpose. It is provided "as is" without express or - * implied warranty. - * - * See http://www.boost.org for most recent version including documentation. - * - * $Id$ - * - * 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 - -namespace boost { -namespace random { - -// http://www.math.keio.ac.jp/matumoto/emt.html -template -class mersenne_twister -{ -public: - typedef DataType result_type; - BOOST_STATIC_CONSTANT(int, state_size = n); - BOOST_STATIC_CONSTANT(int, shift_size = m); - BOOST_STATIC_CONSTANT(int, mask_bits = r); - BOOST_STATIC_CONSTANT(DataType, parameter_a = a); - BOOST_STATIC_CONSTANT(int, output_u = u); - BOOST_STATIC_CONSTANT(int, output_s = s); - BOOST_STATIC_CONSTANT(DataType, output_b = b); - BOOST_STATIC_CONSTANT(int, output_t = t); - BOOST_STATIC_CONSTANT(DataType, output_c = c); - BOOST_STATIC_CONSTANT(int, output_l = l); -#ifndef BOOST_NO_INCLASS_MEMBER_INITIALIZATION - static const bool has_fixed_range = true; - static const result_type min_value = integer_traits::const_min; - static const result_type max_value = integer_traits::const_max; -#else - BOOST_STATIC_CONSTANT(bool, has_fixed_range = false); -#endif - result_type min() const { return std::numeric_limits::min(); } - result_type max() const { return std::numeric_limits::max(); } - - mersenne_twister() { seed(); } - -#if defined(__SUNPRO_CC) && (__SUNPRO_CC <= 0x520) - // Work around overload resolution problem (Gennadiy E. Rozental) - explicit mersenne_twister(const DataType& value) -#else - explicit mersenne_twister(DataType value) -#endif - { seed(value); } - - template - explicit mersenne_twister(Generator & gen) { seed(gen); } - - // compiler-generated copy ctor and assignment operator are fine - - void seed() { seed(DataType(4357)); } - -#if defined(__SUNPRO_CC) && (__SUNPRO_CC <= 0x520) - // Work around overload resolution problem (Gennadiy E. Rozental) - void seed(const DataType& value) -#else - void seed(DataType value) -#endif - { - random::linear_congruential - gen(value); - seed(gen); - } - - // 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 definitions of member function templates. - template - void seed(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; - } - - result_type operator()(); - bool validation(result_type v) const { return val == v; } - -#ifndef BOOST_NO_OPERATORS_IN_NAMESPACE - friend std::ostream& operator<<(std::ostream& os, const mersenne_twister& mt) - { - os << mt.i << " "; - std::copy(mt.x, mt.x+n, std::ostream_iterator(os, " ")); - return os; - } - friend std::istream& operator>>(std::istream& is, mersenne_twister& mt) - { - is >> mt.i >> std::ws; - for(int i = 0; i < mt.state_size; ++i) - is >> mt.x[i] >> std::ws; - return is; - } - friend bool operator==(const mersenne_twister& x, const mersenne_twister& y) - { return x.i == y.i && std::equal(x.x, x.x+n, y.x); } -#else - // Use a member function; Streamable concept not supported. - bool operator==(const mersenne_twister& rhs) const - { return i == rhs.i && std::equal(x, x+n, rhs.x); } -#endif - -private: - typedef DataType data_type; - void twist(); - int i; - data_type x[n]; -}; - -#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 typename mersenne_twister::result_type mersenne_twister::min_value; -template -const typename mersenne_twister::result_type mersenne_twister::max_value; -template -const int mersenne_twister::state_size; -template -const int mersenne_twister::shift_size; -template -const int mersenne_twister::mask_bits; -template -const DataType mersenne_twister::parameter_a; -template -const int mersenne_twister::output_u; -template -const int mersenne_twister::output_s; -template -const DataType mersenne_twister::output_b; -template -const int mersenne_twister::output_t; -template -const DataType mersenne_twister::output_c; -template -const int mersenne_twister::output_l; -#endif - -template -void mersenne_twister::twist() -{ - const data_type upper_mask = (~0u) << r; - const data_type lower_mask = ~upper_mask; - /* - for(int j = 0; j < n; j++) { - // Step 2 - data_type y = (x[j] & upper_mask) | (x[(j+1)%n] & lower_mask); - // Step 3 - x[j] = x[(j+m)%n] ^ (y >> 1) ^ (y&1 ? a : 0); - } - */ - // 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++) { - data_type y = (x[j] & upper_mask) | (x[j+1] & lower_mask); - x[j] = x[j+m] ^ (y >> 1) ^ (y&1 ? a : 0); - } - } - - for(int j = n-m; j < n-1; j++) { - data_type y = (x[j] & upper_mask) | (x[j+1] & lower_mask); - x[j] = x[j+m-n] ^ (y >> 1) ^ (y&1 ? a : 0); - } - // last iteration - data_type y = (x[n-1] & upper_mask) | (x[0] & lower_mask); - x[n-1] = x[n-1+m-n] ^ (y >> 1) ^ (y&1 ? a : 0); - - i = 0; -} - -template -inline typename mersenne_twister::result_type -mersenne_twister::operator()() -{ - if(i >= n) - twist(); - // Step 4 - data_type z = x[i]; - ++i; - z ^= (z >> u); - z ^= ((z << s) & b); - z ^= ((z << t) & c); - z ^= (z >> l); - return z; -} - -} // namespace random - - -typedef random::mersenne_twister mt11213b; - -// validation by experiment from mt19937.c -typedef random::mersenne_twister mt19937; - -} // namespace boost - -#endif // BOOST_RANDOM_MERSENNE_TWISTER_HPP diff --git a/include/boost/random/normal_distribution.hpp b/include/boost/random/normal_distribution.hpp deleted file mode 100644 index 9e14058..0000000 --- a/include/boost/random/normal_distribution.hpp +++ /dev/null @@ -1,96 +0,0 @@ -/* boost random/normal_distribution.hpp header file - * - * Copyright Jens Maurer 2000-2001 - * Permission to use, copy, modify, sell, and distribute this software - * is hereby granted without fee provided that the above copyright notice - * appears in all copies and that both that copyright notice and this - * permission notice appear in supporting documentation, - * - * Jens Maurer makes no representations about the suitability of this - * software for any purpose. It is provided "as is" without express or - * implied warranty. - * - * See http://www.boost.org for most recent version including documentation. - * - * $Id$ - * - * 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 - -namespace boost { - -// deterministic polar method, uses trigonometric functions -template -class normal_distribution -{ -public: - typedef UniformRandomNumberGenerator base_type; - typedef RealType result_type; - - explicit normal_distribution(base_type & rng, const result_type& mean = 0, - const result_type& sigma = 1) - : _rng(rng), _mean(mean), _sigma(sigma), _valid(false) - { - assert(sigma >= 0); - } - - // compiler-generated copy constructor is NOT fine, need to purge cache - normal_distribution(const normal_distribution& other) - : _rng(other._rng), _mean(other._mean), _sigma(other._sigma), _valid(false) - { - } - // uniform_01 cannot be assigned, neither can this class - - result_type operator()() - { -#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 = _rng(); - _r2 = _rng(); - _cached_rho = sqrt(-2 * log(1.0-_r2)); - _valid = true; - } else { - _valid = false; - } - // Can we have a boost::mathconst please? - const double pi = 3.14159265358979323846; - - return _cached_rho * (_valid ? cos(2*pi*_r1) : sin(2*pi*_r1)) * _sigma + - _mean; - } -#ifndef BOOST_NO_OPERATORS_IN_NAMESPACE - friend bool operator==(const normal_distribution& x, - const normal_distribution& y) - { - return x._mean == y._mean && x._sigma == y._sigma && - x._valid == y._valid && x._rng == y._rng; - } -#else - // Use a member function - bool operator==(const normal_distribution& rhs) const - { - return _mean == rhs._mean && _sigma == rhs._sigma && - _valid == rhs._valid && _rng == rhs._rng; - } -#endif -private: - uniform_01 _rng; - const result_type _mean, _sigma; - result_type _r1, _r2, _cached_rho; - bool _valid; -}; - -} // namespace boost - -#endif // BOOST_RANDOM_NORMAL_DISTRIBUTION_HPP diff --git a/include/boost/random/random_number_generator.hpp b/include/boost/random/random_number_generator.hpp deleted file mode 100644 index b9acee9..0000000 --- a/include/boost/random/random_number_generator.hpp +++ /dev/null @@ -1,62 +0,0 @@ -/* boost random/random_number_generator.hpp header file - * - * Copyright Jens Maurer 2000-2001 - * Permission to use, copy, modify, sell, and distribute this software - * is hereby granted without fee provided that the above copyright notice - * appears in all copies and that both that copyright notice and this - * permission notice appear in supporting documentation, - * - * Jens Maurer makes no representations about the suitability of this - * software for any purpose. It is provided "as is" without express or - * implied warranty. - * - * See http://www.boost.org for most recent version including documentation. - * - * $Id$ - * - * 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 -#include - -namespace boost { - -// a model for RandomNumberGenerator std:25.2.11 [lib.alg.random.shuffle] -template -class random_number_generator -{ -public: - typedef UniformRandomNumberGenerator base_type; - typedef IntType argument_type; - typedef IntType result_type; - random_number_generator(base_type & rng) : _rng(rng) { - // MSVC requires the typedef workaround - typedef typename base_type::result_type base_result_type; -#ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS - BOOST_STATIC_ASSERT(std::numeric_limits::is_integer); - BOOST_STATIC_ASSERT(std::numeric_limits::is_integer); -#endif - } - // compiler-generated copy ctor is fine - // assignment is disallowed because there is a reference member - - result_type operator()(argument_type n) { - return uniform_int(_rng, 0, n-1)(); - } - -private: - base_type & _rng; -}; - -} // namespace boost - -#endif // BOOST_RANDOM_RANDOM_NUMBER_GENERATOR_HPP diff --git a/include/boost/random/shuffle_output.hpp b/include/boost/random/shuffle_output.hpp deleted file mode 100644 index 6f0c1f9..0000000 --- a/include/boost/random/shuffle_output.hpp +++ /dev/null @@ -1,158 +0,0 @@ -/* boost random/shuffle_output.hpp header file - * - * Copyright Jens Maurer 2000-2001 - * Permission to use, copy, modify, sell, and distribute this software - * is hereby granted without fee provided that the above copyright notice - * appears in all copies and that both that copyright notice and this - * permission notice appear in supporting documentation, - * - * Jens Maurer makes no representations about the suitability of this - * software for any purpose. It is provided "as is" without express or - * implied warranty. - * - * See http://www.boost.org for most recent version including documentation. - * - * $Id$ - * - * 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 { - -// Carter Bays and S.D. Durham 1979 -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); - - shuffle_output() : _rng() { init(); } -#if defined(BOOST_MSVC) && _MSC_VER <= 1200 - // 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 - template - explicit shuffle_output(T seed) : _rng(seed) { init(); } - explicit shuffle_output(const base_type & rng) : _rng(rng) { init(); } - template - void seed(T s) { _rng.seed(s); init(); } - - 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*IntType(y-min())/range; - // assert(0 <= j && j < k); - y = v[j]; - v[j] = _rng(); - return y; - } - - result_type min() const { return _rng.min(); } - result_type max() const { return _rng.max(); } - bool validation(result_type x) const { return val == x; } - -#ifndef BOOST_NO_OPERATORS_IN_NAMESPACE - friend std::ostream& operator<<(std::ostream& os, const shuffle_output& s) - { - os << s._rng << " " << s.y << " "; - std::copy(s.v, s.v+k, std::ostream_iterator(os, " ")); - return os; - } - friend std::istream& operator>>(std::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; - } - 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); } -#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); } -#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(IntType(k * range) < IntType(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) -typedef random::shuffle_output< - random::linear_congruential, - 97, uint32_t, 139726> kreutzer1986; - - -} // namespace boost - -#endif // BOOST_RANDOM_SHUFFLE_OUTPUT_HPP diff --git a/include/boost/random/triangle_distribution.hpp b/include/boost/random/triangle_distribution.hpp deleted file mode 100644 index f84dfc6..0000000 --- a/include/boost/random/triangle_distribution.hpp +++ /dev/null @@ -1,80 +0,0 @@ -/* boost random/triangle_distribution.hpp header file - * - * Copyright Jens Maurer 2000-2001 - * Permission to use, copy, modify, sell, and distribute this software - * is hereby granted without fee provided that the above copyright notice - * appears in all copies and that both that copyright notice and this - * permission notice appear in supporting documentation, - * - * Jens Maurer makes no representations about the suitability of this - * software for any purpose. It is provided "as is" without express or - * implied warranty. - * - * See http://www.boost.org for most recent version including documentation. - * - * $Id$ - * - * 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 - -namespace boost { - -// triangle distribution, with a smallest, b most probable, and c largest -// value. -template -class triangle_distribution -{ -public: - typedef UniformRandomNumberGenerator base_type; - typedef RealType result_type; - triangle_distribution(base_type & rng, result_type a, result_type b, - result_type c) - : _rng(rng), _a(a), _b(b), _c(c), - d1(_b-_a), d2(_c-_a), d3(_c-_b), q1(d1/d2), p1(d1*d2) - { -#ifndef BOOST_NO_STDC_NAMESPACE - using std::sqrt; -#endif - d3 = sqrt(d3); - p1 = sqrt(p1); - assert(_a <= _b && _b <= _c); - } - // compiler-generated copy ctor is fine - // uniform_01 cannot be assigned, neither can this class - result_type operator()() - { -#ifndef BOOST_NO_STDC_NAMESPACE - using std::sqrt; -#endif - result_type u = _rng(); - if( u <= q1 ) - return _a + p1*sqrt(u); - else - return _c - d3*sqrt(d2*u-d1); - } -#ifndef BOOST_NO_OPERATORS_IN_NAMESPACE - friend bool operator==(const triangle_distribution& x, - const triangle_distribution& y) - { return x._a == y._a && x._b == y._b && x._c == y._c && x._rng == y._rng; } -#else - // Use a member function - bool operator==(const triangle_distribution& rhs) const - { return _a == rhs._a && _b == rhs._b && _c == rhs._c && _rng == rhs._rng; } -#endif -private: - uniform_01 _rng; - result_type _a, _b, _c; - result_type d1, d2, d3, q1, p1; -}; - -} // namespace boost - -#endif // BOOST_RANDOM_TRIANGLE_DISTRIBUTION_HPP diff --git a/include/boost/random/uniform_01.hpp b/include/boost/random/uniform_01.hpp deleted file mode 100644 index f94f68a..0000000 --- a/include/boost/random/uniform_01.hpp +++ /dev/null @@ -1,78 +0,0 @@ -/* boost random/uniform_01.hpp header file - * - * Copyright Jens Maurer 2000-2001 - * Permission to use, copy, modify, sell, and distribute this software - * is hereby granted without fee provided that the above copyright notice - * appears in all copies and that both that copyright notice and this - * permission notice appear in supporting documentation, - * - * Jens Maurer makes no representations about the suitability of this - * software for any purpose. It is provided "as is" without express or - * implied warranty. - * - * See http://www.boost.org for most recent version including documentation. - * - * $Id$ - * - * 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 - -namespace boost { - -// Because it is so commonly used: uniform distribution on the real [0..1) -// range. This allows for specializations to avoid a costly FP division -template -class uniform_01 -{ -public: - typedef UniformRandomNumberGenerator base_type; - typedef RealType result_type; - BOOST_STATIC_CONSTANT(bool, has_fixed_range = false); - - explicit uniform_01(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 - - result_type operator()() { - return static_cast(_rng() - _rng.min()) / - (static_cast(_rng.max()-_rng.min()) + - (std::numeric_limits::is_integer ? 1.0 : 0.0)); - } - result_type min() const { return 0.0; } - result_type max() const { return 1.0; } - -#ifndef BOOST_NO_OPERATORS_IN_NAMESPACE - friend bool operator==(const uniform_01& x, const uniform_01& y) - { return x._rng == y._rng; } -#else - // Use a member function - bool operator==(const uniform_01& rhs) const - { return _rng == rhs._rng; } -#endif -private: - typedef typename base_type::result_type base_result; - base_type & _rng; -}; - -#ifndef BOOST_NO_INCLASS_MEMBER_INITIALIZATION -// A definition is required even for integral static constants -template -const bool uniform_01::has_fixed_range; -#endif - -} // namespace boost - -#endif // BOOST_RANDOM_UNIFORM_01_HPP diff --git a/include/boost/random/uniform_int.hpp b/include/boost/random/uniform_int.hpp deleted file mode 100644 index 092c340..0000000 --- a/include/boost/random/uniform_int.hpp +++ /dev/null @@ -1,139 +0,0 @@ -/* boost random/uniform_int.hpp header file - * - * Copyright Jens Maurer 2000-2001 - * Permission to use, copy, modify, sell, and distribute this software - * is hereby granted without fee provided that the above copyright notice - * appears in all copies and that both that copyright notice and this - * permission notice appear in supporting documentation, - * - * Jens Maurer makes no representations about the suitability of this - * software for any purpose. It is provided "as is" without express or - * implied warranty. - * - * See http://www.boost.org for most recent version including documentation. - * - * $Id$ - * - * Revision history - * 2001-04-08 added min -#include -#include -#include -#include -#include - -namespace boost { - -// uniform integer distribution on [min, max] -template -class uniform_int -{ -public: - typedef UniformRandomNumberGenerator base_type; - typedef IntType result_type; - BOOST_STATIC_CONSTANT(bool, has_fixed_range = false); - - uniform_int(base_type & rng, IntType min, IntType max) - : _rng(rng), _min(min), _max(max), _range(_max - _min), - _bmin(_rng.min()), _brange(_rng.max() - _bmin) - { -#ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS - BOOST_STATIC_ASSERT(std::numeric_limits::is_integer); -#endif - assert(min < max); - if(random::equal_signed_unsigned(_brange, _range)) - _range_comparison = 0; - else if(random::lessthan_signed_unsigned(_brange, _range)) - _range_comparison = -1; - else - _range_comparison = 1; - } - result_type operator()(); - result_type min() const { return _min; } - result_type max() const { return _max; } -#ifndef BOOST_NO_OPERATORS_IN_NAMESPACE - friend bool operator==(const uniform_int& x, const uniform_int& y) - { return x._min == y._min && x._max == y._max && x._rng == y._rng; } -#else - // Use a member function - bool operator==(const uniform_int& rhs) const - { return _min == rhs._min && _max == rhs._max && _rng == rhs._rng; } -#endif -private: - typedef typename base_type::result_type base_result; - base_type & _rng; - result_type _min, _max, _range; - base_result _bmin, _brange; - int _range_comparison; -}; - -#ifndef BOOST_NO_INCLASS_MEMBER_INITIALIZATION -// A definition is required even for integral static constants -template -const bool uniform_int::has_fixed_range; -#endif - -template -inline IntType uniform_int::operator()() -{ - if(_range_comparison == 0) { - // this will probably never happen in real life - // basically nothing to do; just take care we don't overflow / underflow - return static_cast(_rng() - _bmin) + _min; - } else if(_range_comparison < 0) { - // 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 - result_type limit; - if(_range == std::numeric_limits::max()) { - limit = _range/(static_cast(_brange)+1); - if(_range % static_cast(_brange)+1 == static_cast(_brange)) - ++limit; - } else { - limit = (_range+1)/(static_cast(_brange)+1); - } - // we consider "result" as expressed to base (_brange+1) - // for every power of (_brange+1), we determine a random factor - result_type result = 0; - result_type mult = 1; - while(mult <= limit) { - result += (_rng() - _bmin) * mult; - mult *= static_cast(_brange)+1; - } - if(mult == limit) - // _range+1 is an integer power of _brange+1: no rejections required - return result; - // _range/mult < _brange+1 -> no endless loop - result += uniform_int(_rng, 0, _range/mult)() * mult; - if(result <= _range) - return result + _min; - } - } else { // brange > range - if(_brange / _range > 4 /* quantization_cutoff */ ) { - // the new range is vastly smaller than the source range, - // so quantization effects are not relevant - return uniform_smallint(_rng, _min, _max)(); - } else { - // use rejection method to handle things like 0..5 -> 0..4 - for(;;) { - base_result result = _rng() - _bmin; - // result and range are non-negative, and result is possibly larger - // than range, so the cast is safe - if(result <= static_cast(_range)) - return result + _min; - } - } - } -} - -} // namespace boost - -#endif // BOOST_RANDOM_UNIFORM_INT_HPP diff --git a/include/boost/random/uniform_on_sphere.hpp b/include/boost/random/uniform_on_sphere.hpp deleted file mode 100644 index ce12fba..0000000 --- a/include/boost/random/uniform_on_sphere.hpp +++ /dev/null @@ -1,79 +0,0 @@ -/* boost random/uniform_on_sphere.hpp header file - * - * Copyright Jens Maurer 2000-2001 - * Permission to use, copy, modify, sell, and distribute this software - * is hereby granted without fee provided that the above copyright notice - * appears in all copies and that both that copyright notice and this - * permission notice appear in supporting documentation, - * - * Jens Maurer makes no representations about the suitability of this - * software for any purpose. It is provided "as is" without express or - * implied warranty. - * - * See http://www.boost.org for most recent version including documentation. - * - * $Id$ - * - * 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 - -namespace boost { - -template > -class uniform_on_sphere -{ -public: - typedef UniformRandomNumberGenerator base_type; - typedef Cont result_type; - - explicit uniform_on_sphere(base_type & rng, int dim = 2) - : _rng(rng), _container(dim), _dim(dim) { } - // compiler-generated copy ctor is fine - // normal_distribution cannot be assigned, neither can this class - const result_type & operator()() - { - RealType sqsum = 0; - for(typename Cont::iterator it = _container.begin(); - it != _container.end(); - ++it) { - RealType val = _rng(); - *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_NO_OPERATORS_IN_NAMESPACE - friend bool operator==(const uniform_on_sphere& x, - const uniform_on_sphere& y) - { return x._dim == y._dim && x._rng == y._rng; } -#else - // Use a member function - bool operator==(const uniform_on_sphere& rhs) const - { return _dim == rhs._dim && _rng == rhs._rng; } -#endif -private: - normal_distribution _rng; - result_type _container; - const int _dim; -}; - -} // namespace boost - -#endif // BOOST_RANDOM_UNIFORM_ON_SPHERE_HPP diff --git a/include/boost/random/uniform_real.hpp b/include/boost/random/uniform_real.hpp deleted file mode 100644 index afb87d1..0000000 --- a/include/boost/random/uniform_real.hpp +++ /dev/null @@ -1,78 +0,0 @@ -/* boost random/uniform_real.hpp header file - * - * Copyright Jens Maurer 2000-2001 - * Permission to use, copy, modify, sell, and distribute this software - * is hereby granted without fee provided that the above copyright notice - * appears in all copies and that both that copyright notice and this - * permission notice appear in supporting documentation, - * - * Jens Maurer makes no representations about the suitability of this - * software for any purpose. It is provided "as is" without express or - * implied warranty. - * - * See http://www.boost.org for most recent version including documentation. - * - * $Id$ - * - * Revision history - * 2001-04-08 added min -#include -#include -#include -#include - -namespace boost { - -// uniform distribution on a real range -template -class uniform_real -{ -public: - typedef UniformRandomNumberGenerator base_type; - typedef RealType result_type; - BOOST_STATIC_CONSTANT(bool, has_fixed_range = false); - - uniform_real(base_type & rng, RealType min, RealType max) - : _rng(rng), _min(min), _max(max) - { -#ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS - BOOST_STATIC_ASSERT(!std::numeric_limits::is_integer); -#endif - assert(min < max); - } - // compiler-generated copy ctor is fine - // uniform_01 cannot be assigned, neither can this class - - result_type operator()() { return _rng() * (_max - _min) + _min; } - result_type min() const { return _min; } - result_type max() const { return _max; } - -#ifndef BOOST_NO_OPERATORS_IN_NAMESPACE - friend bool operator==(const uniform_real& x, const uniform_real& y) - { return x._min == y._min && x._max == y._max && x._rng == y._rng; } -#else - // Use a member function - bool operator==(const uniform_real& rhs) const - { return _min == rhs._min && _max == rhs._max && _rng == rhs._rng; } -#endif -private: - uniform_01 _rng; - RealType _min, _max; -}; - -#ifndef BOOST_NO_INCLASS_MEMBER_INITIALIZATION -// A definition is required even for integral static constants -template -const bool uniform_real::has_fixed_range; -#endif - -} // namespace boost - -#endif // BOOST_RANDOM_UNIFORM_REAL_HPP diff --git a/include/boost/random/uniform_smallint.hpp b/include/boost/random/uniform_smallint.hpp deleted file mode 100644 index 1bc6a5c..0000000 --- a/include/boost/random/uniform_smallint.hpp +++ /dev/null @@ -1,103 +0,0 @@ -/* boost random/uniform_smallint.hpp header file - * - * Copyright Jens Maurer 2000-2001 - * Permission to use, copy, modify, sell, and distribute this software - * is hereby granted without fee provided that the above copyright notice - * appears in all copies and that both that copyright notice and this - * permission notice appear in supporting documentation, - * - * Jens Maurer makes no representations about the suitability of this - * software for any purpose. It is provided "as is" without express or - * implied warranty. - * - * See http://www.boost.org for most recent version including documentation. - * - * $Id$ - * - * Revision history - * 2001-04-08 added min -#include -#include - -namespace boost { - -// uniform integer distribution on a small range [min, max] -template -class uniform_smallint -{ -public: - typedef UniformRandomNumberGenerator base_type; - typedef IntType result_type; - BOOST_STATIC_CONSTANT(bool, has_fixed_range = false); - - uniform_smallint(base_type & rng, IntType min, IntType max); - result_type operator()() - { - // we must not use the low bits here, because LCGs get very bad then - return ((_rng() - _rng.min()) / _factor) % _range + _min; - } - result_type min() const { return _min; } - result_type max() const { return _max; } -#ifndef BOOST_NO_OPERATORS_IN_NAMESPACE - friend bool operator==(const uniform_smallint& x, const uniform_smallint& y) - { return x._min == y._min && x._max == y._max && x._rng == y._rng; } -#else - // Use a member function - bool operator==(const uniform_smallint& rhs) const - { return _min == rhs._min && _max == rhs._max && _rng == rhs._rng; } -#endif -private: - typedef typename base_type::result_type base_result; - base_type & _rng; - IntType _min, _max; - base_result _range; - int _factor; -}; - -#ifndef BOOST_NO_INCLASS_MEMBER_INITIALIZATION -// A definition is required even for integral static constants -template -const bool uniform_smallint::has_fixed_range; -#endif - -template -uniform_smallint:: -uniform_smallint(base_type & rng, IntType min, IntType max) - : _rng(rng), _min(min), _max(max), - _range(static_cast(_max-_min)+1), _factor(1) -{ -#ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS - BOOST_STATIC_ASSERT(std::numeric_limits::is_integer); -#endif - assert(min < max); - - // 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 = _rng.max() - _rng.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 { - const base_result r = 32*_range*_range; - for(; r_base >= r; _factor *= 2) - r_base /= 2; - } -} - -} // namespace boost - -#endif // BOOST_RANDOM_UNIFORM_SMALLINT_HPP diff --git a/index.html b/index.html deleted file mode 100644 index 5dbc345..0000000 --- a/index.html +++ /dev/null @@ -1,143 +0,0 @@ - - - - - -Boost Random Number Library - - - - - - - - - - - - - -
c++boost.gif (8819 bytes)HomeLibrariesPeopleFAQMore
- -

Boost Random Number Library

- -Random numbers are useful in a variety of applications. The Boost -Random Number Library (Boost.Random for short) provides a vast variety -of generators and distributions to produce random numbers having -useful properties, such as uniform distribution. -

-You should read the -concepts documentation -for an introduction and the definition of the basic concepts. For a -quick start, it may be sufficient to have a look at random_demo.cpp. - -

Library Organization

- -The library is separated into several header files, all within the -boost/random/ directory. Additionally, a convenience -header file which includes all other headers in -boost/random/ is available as -boost/random.hpp. -

- -Several random number generators are available in the following -header files; please read the -documentation about these. - -

- - -Similarly, several random number distributions are available in the -following header files; please read the -documentation about these. - - - -Additionally, non-deterministic random number generators are available -in the header -<boost/nondet_random.hpp>. -Documentation is also available. - -

- -In order to map the interface of the generators and distribution functions -to other concepts, some decorators are available. - -

Tests

- -An extensive test suite for the pseudo-random number generators and -distributions is available as -random_test.cpp. -

-Some performance results obtained -using random_speed.cpp are also available. - -

Rationale

- -The methods for generating and evaluating deterministic and -non-deterministic random numbers differ radically. Furthermore, due -to the inherent deterministic design of present-day computers, it is -often difficult to implement non-deterministic random number -generation facilities. Thus, the random number library is split into -separate header files, mirroring the two different application -domains. - - -

History and Acknowledgements

- -In November 1999, Jeet Sukumaran proposed a framework based on virtual -functions, and later sketched a template-based approach. Ed Brey -pointed out that Microsoft Visual C++ does not support in-class member -initializations and suggested the enum workaround. Dave -Abrahams highlighted quantization issues. -

-The first public release of this random number library materialized in -March 2000 after extensive discussions on the boost mailing list. -Many thanks to Beman Dawes for his original min_rand -class, portability fixes, documentation suggestions, and general -guidance. Harry Erwin sent a header file which provided additional -insight into the requirements. Ed Brey and Beman Dawes wanted an -iterator-like interface. -

-Beman Dawes managed the formal review, during which Matthias Troyer, -Csaba Szepesvari, and Thomas Holenstein gave detailed comments. The -reviewed version became an official part of boost on 17 June 2000. -

-Gary Powell contributed suggestions for code cleanliness. Dave -Abrahams and Howard Hinnant suggested to move the basic generator -templates from namespace boost::detail to -boost::random. -

-Ed Brey asked to remove superfluous warnings and helped with -uint64_t handling. Andreas Scherer tested with MSVC. -Matthias Troyer contributed a lagged Fibonacci generator. Michael -Stevens found a bug in the copy semantics of normal_distribution and -suggested documentation improvements. -

-


-Jens Maurer, -2001-08-31 - - - diff --git a/integrate.hpp b/integrate.hpp deleted file mode 100644 index c637f35..0000000 --- a/integrate.hpp +++ /dev/null @@ -1,84 +0,0 @@ -/* integrate.hpp header file - * - * Copyright Jens Maurer 2000 - * Permission to use, copy, modify, sell, and distribute this software - * is hereby granted without fee provided that the above copyright notice - * appears in all copies and that both that copyright notice and this - * permission notice appear in supporting documentation, - * - * Jens Maurer makes no representations about the suitability of this - * software for any purpose. It is provided "as is" without express or - * implied warranty. - * - * $Id$ - * - * Revision history - * 01 April 2001: Modified to use new header. (JMaddock) - */ - -#ifndef INTEGRATE_HPP -#define INTEGRATE_HPP - -#include - -template -inline typename UnaryFunction::result_type -trapezoid(UnaryFunction f, typename UnaryFunction::argument_type a, - typename UnaryFunction::argument_type b, int n) -{ - typename UnaryFunction::result_type tmp = 0; - for(int i = 1; i <= n-1; ++i) - tmp += f(a+(b-a)/n*i); - return (b-a)/2/n * (f(a) + f(b) + 2*tmp); -} - -template -inline typename UnaryFunction::result_type -simpson(UnaryFunction f, typename UnaryFunction::argument_type a, - typename UnaryFunction::argument_type b, int n) -{ - typename UnaryFunction::result_type tmp1 = 0; - for(int i = 1; i <= n-1; ++i) - tmp1 += f(a+(b-a)/n*i); - typename UnaryFunction::result_type tmp2 = 0; - for(int i = 1; i <= n ; ++i) - tmp2 += f(a+(b-a)/2/n*(2*i-1)); - - return (b-a)/6/n * (f(a) + f(b) + 2*tmp1 + 4*tmp2); -} - -// compute b so that f(b) = y; assume f is monotone increasing -template -inline typename UnaryFunction::argument_type -invert_monotone_inc(UnaryFunction f, typename UnaryFunction::result_type y, - typename UnaryFunction::argument_type lower = -1, - typename UnaryFunction::argument_type upper = 1) -{ - while(upper-lower > 1e-6) { - double middle = (upper+lower)/2; - if(f(middle) > y) - upper = middle; - else - lower = middle; - } - return (upper+lower)/2; -} - -// compute b so that I(f(x), a, b) == y -template -inline typename UnaryFunction::argument_type -quantil(UnaryFunction f, typename UnaryFunction::argument_type a, - typename UnaryFunction::result_type y, - typename UnaryFunction::argument_type step) -{ - typedef typename UnaryFunction::result_type result_type; - if(y >= 1.0) - return std::numeric_limits::infinity(); - typename UnaryFunction::argument_type b = a; - for(result_type result = 0; result < y; b += step) - result += step*f(b); - return b; -} - - -#endif /* INTEGRATE_HPP */ diff --git a/nondet_random.html b/nondet_random.html deleted file mode 100644 index 8759296..0000000 --- a/nondet_random.html +++ /dev/null @@ -1,121 +0,0 @@ - - - - - -Boost RNG Library - Non-Deterministic Random Number Generators - - - - -

c++boost.gif (8819 bytes)Header -<boost/nondet_random.hpp>

- - - -

Header<boost/nondet_random.hpp> -Synopsis

- -
-namespace boost {
-  class random_device;
-} // namespace boost
-
- - -

Class random_device

- -

Synopsis

- -
-class random_device : noncopyable
-{
-public:
-  typedef unsigned int result_type;
-  static const bool has_fixed_range = true;
-  static const result_type min_value = /* implementation defined */;
-  static const result_type max_value = /* implementation defined */;
-  result_type min() const;
-  result_type max() const;
-  explicit random_device(const std::string& token = default_token);
-  ~random_device();
-  unsigned int operator()();
-};
-
- -

Description

- -Class random_device models a -non-deterministic random number -generator. -It uses one or more implementation-defined stochastic processes to -generate a sequence of uniformly distributed non-deterministic random -numbers. For those environments where a non-deterministic random -number generator is not available, class random_device -must not be implemented. See -
-"Randomness Recommendations for Security", D. Eastlake, S. -Crocker, J. Schiller, Network Working Group, RFC 1750, December 1994 -
-for further discussions. - -

-Note: Some operating systems abstract the computer hardware -enough to make it difficult to non-intrusively monitor stochastic -processes. However, several do provide a special device for exactly -this purpose. It seems to be impossible to emulate the functionality -using Standard C++ only, so users should be aware that this class may -not be available on all platforms. - -

Members

- -
explicit random_device(const std::string& token = default_token)
- -Effects: Constructs a random_device, -optionally using the given token as an access -specification (for example, a URL) to some implementation-defined -service for monitoring a stochastic process. - -

Implementation Note for Linux

- -On the Linux operating system, token is interpreted as a -filesystem path. It is assumed that this path denotes an operating -system pseudo-device which generates a stream of non-deterministic -random numbers. The pseudo-device should never signal an error or -end-of-file. Otherwise, std::ios_base::failure is -thrown. By default, random_device uses the -/dev/urandom pseudo-device to retrieve the random -numbers. Another option would be to specify the -/dev/random pseudo-device, which blocks on reads if the -entropy pool has no more random bits available. - - -

Performance

- -The test program nondet_random_speed.cpp -measures the execution times of the -nondet_random.hpp implementation of the above -algorithms in a tight loop. The performance has been evaluated on a -Pentium Pro 200 MHz with gcc 2.95.2, Linux 2.2.13, glibc 2.1.2. - -

- - - -
classtime per invocation [usec]
random_device92.0
- -

-The measurement error is estimated at +/- 1 usec. - -

-


-Jens Maurer, 2000-06-19 - - - - \ No newline at end of file diff --git a/nondet_random_speed.cpp b/nondet_random_speed.cpp deleted file mode 100644 index 2944401..0000000 --- a/nondet_random_speed.cpp +++ /dev/null @@ -1,69 +0,0 @@ -/* boost nondet_random_speed.cpp performance test - * - * Copyright Jens Maurer 2000 - * Permission to use, copy, modify, sell, and distribute this software - * is hereby granted without fee provided that the above copyright notice - * appears in all copies and that both that copyright notice and this - * permission notice appear in supporting documentation, - * - * Jens Maurer makes no representations about the suitability of this - * software for any purpose. It is provided "as is" without express or - * implied warranty. - * - * $Id$ - * - */ - -#include -#include -#include -#include - -// set to your CPU frequency in MHz -static const double cpu_frequency = 200 * 1e6; - -static void show_elapsed(double end, int iter, const std::string & name) -{ - double usec = end/iter*1e6; - double cycles = usec * cpu_frequency/1e6; - std::cout << name << ": " - << usec*1e3 << " nsec/loop = " - << cycles << " CPU cycles" - << std::endl; -} - -template -static void timing(RNG & rng, int iter, const std::string& name) -{ - volatile Result tmp; // make sure we're not optimizing too much - boost::timer t; - for(int i = 0; i < iter; i++) - tmp = rng(); - show_elapsed(t.elapsed(), iter, name); -} - -template -void run(int iter, const std::string & name) -{ - RNG rng; - timing(rng, iter, name); -} - -int main(int argc, char*argv[]) -{ - if(argc != 2) { - std::cerr << "usage: " << argv[0] << " iterations" << std::endl; - return 1; - } - - int iter = std::atoi(argv[1]); - -#ifdef __linux__ - boost::random_device dev; - timing(dev, iter, "random_device"); -#else -#error The non-deterministic random device is currently available on Linux only. -#endif - - return 0; -} diff --git a/random-concepts.html b/random-concepts.html deleted file mode 100644 index 1e8f550..0000000 --- a/random-concepts.html +++ /dev/null @@ -1,344 +0,0 @@ - - - - - -Boost Random Number Library Concepts - - - - -

Random Number Generator Library Concepts

- - -

Introduction

- -Random numbers are required in a number of different problem domains, -such as -
    -
  • numerics (simulation, Monte-Carlo integration) -
  • games (non-deterministic enemy behavior) -
  • security (key generation) -
  • testing (random coverage in white-box tests) -
- -The Boost Random Number Generator Library provides a framework -for random number generators with well-defined properties so that the -generators can be used in the demanding numerics and security domains. - -For a general introduction to random numbers in numerics, see -
-"Numerical Recipes in C: The art of scientific computing", William -H. Press, Saul A. Teukolsky, William A. Vetterling, Brian P. Flannery, -2nd ed., 1992, pp. 274-328 -
- -Depending on the requirements of the problem domain, different -variations of random number generators are appropriate: - -
    -
  • non-deterministic random number generator -
  • pseudo-random number generator -
  • quasi-random number generator -
- -All variations have some properties in common, these concepts (in the -STL sense) are called NumberGenerator and -UniformRandomNumberGenerator. Each concept will be defined in a -subsequent section. - -

- -The goals for this library are the following: -

    -
  • allow easy integration of third-party random-number generators -
  • define a validation interface for the generators -
  • provide easy-to-use front-end classes which model popular -distributions -
  • provide maximum efficiency -
  • allow control on quantization effects in front-end processing -(not yet done) -
- - -

Number Generator

- -A number generator is a function object (std:20.3 -[lib.function.objects]) that takes zero arguments. Each call to -operator() returns a number. - - -In the following table, X denotes a number generator -class returning objects of type T, and u is -a value of X. - -

- - - - - - - - -
NumberGenerator -requirements
expressionreturn typepre/post-condition
X::result_typeTstd::numeric_limits<T>::is_specialized is true, -T is LessThanComparable
u.operator()()T-
- -

- -Note: The NumberGenerator requirements do not impose any -restrictions on the characteristics of the returned numbers. - - -

Uniform Random Number Generator

- -A uniform random number generator is a NumberGenerator that provides a -sequence of random numbers uniformly distributed on a given range. -The range can be compile-time fixed or available (only) after run-time -construction of the object. - -

-The tight lower bound of some (finite) set S is the (unique) -member l in S, so that for all v in S, l <= v holds. Likewise, the -tight upper bound of some (finite) set S is the (unique) -member u in S, so that for all v in S, v <= u holds. - -

-In the following table, X denotes a number generator -class returning objects of type T, and v is -a const value of X. - -

- - - - - - - - - - - - - - - -
UniformRandomNumberGenerator -requirements
expressionreturn typepre/post-condition
X::has_fixed_rangeboolcompile-time constant; if true, the range on which -the random numbers are uniformly distributed is known at compile-time -and members min_value and max_value -exist. Note: This flag may also be false due to -compiler limitations.
X::min_valueTcompile-time constant; min_value is equal to -v.min()
X::max_valueTcompile-time constant; max_value is equal to -v.max()
v.min()Ttight lower bound on the set of all values returned by -operator(). The return value of this function shall not -change during the lifetime of the object.
v.max()Tif std::numeric_limits<T>::is_integer, tight -upper bound on the set of all values returned by -operator(), otherwise, the smallest representable number -larger than the tight upper bound on the set of all values returned by -operator(). In any case, the return value of this -function shall not change during the lifetime of the -object.
- -

-The member functions min, max, and -operator() shall have amortized constant time complexity. - -

-Note: For integer generators (i.e. integer T), -the generated values x fulfill min() <= x <= -max(), for non-integer generators (i.e. non-integer -T), the generated values x fulfill -min() <= x < max(). -
-Rationale: The range description with min and -max serves two purposes. First, it allows scaling of the -values to some canonical range, such as [0..1). Second, it describes -the significant bits of the values, which may be relevant for further -processing. -
-The range is a closed interval [min,max] for integers, because the -underlying type may not be able to represent the half-open interval -[min,max+1). It is a half-open interval [min, max) for non-integers, -because this is much more practical for borderline cases of continuous -distributions. -

- -Note: The UniformRandomNumberGenerator concept does not -require operator()(long) and thus it does not fulfill the -RandomNumberGenerator (std:25.2.11 [lib.alg.random.shuffle]) -requirements. Use the -random_number_generator -adapter for that. -
- -Rationale: operator()(long) is not provided, -because mapping the output of some generator with integer range to a -different integer range is not trivial. - - -

Non-deterministic Uniform Random Number -Generator

- -A non-deterministic uniform random number generator is a -UniformRandomNumberGenerator that is based on some stochastic process. -Thus, it provides a sequence of truly-random numbers. Examples for -such processes are nuclear decay, noise of a Zehner diode, tunneling -of quantum particles, rolling a die, drawing from an urn, and tossing -a coin. Depending on the environment, inter-arrival times of network -packets or keyboard events may be close approximations of stochastic -processes. -

- -The class -random_device -is a model for a non-deterministic random number generator. - -

- -Note: This type of random-number generator is useful for -security applications, where it is important to prevent that an -outside attacker guesses the numbers and thus obtains your -encryption or authentication key. Thus, models of this concept should -be cautious not to leak any information, to the extent possible by the -environment. For example, it might be advisable to explicitly clear -any temporary storage as soon as it is no longer needed. - - -

Pseudo-Random Number Generator

- -A pseudo-random number generator is a UniformRandomNumberGenerator -which provides a deterministic sequence of pseudo-random numbers, -based on some algorithm and internal state. Linear congruential and -inversive congruential generators are examples of such pseudo-random -number generators. Often, these generators are very sensitive to -their parameters. In order to prevent wrong implementations from -being used, an external testsuite should check that the generated -sequence and the validation value provided do indeed match. -

- -Donald E. Knuth gives an extensive overview on pseudo-random number -generation in his book "The Art of Computer Programming, Vol. 2, 3rd -edition, Addison-Wesley, 1997". The descriptions for the specific -generators contain additional references. -

- -Note: Because the state of a pseudo-random number generator -is necessarily finite, the sequence of numbers returned by the -generator will loop eventually. - -

-In addition to the UniformRandomNumberGenerator requirements, a -pseudo-random number generator has some additional requirements. In -the following table, X denotes a pseudo-random number -generator class returning objects of type T, -x is a value of T, u is a value -of X, and v is a const value of -X. - -

- - - - - - - - - - - -
PseudoRandomNumberGenerator -requirements
expressionreturn typepre/post-condition
X()-creates a generator in some implementation-defined -state. Note: Several generators thusly created may possibly -produce dependent or identical sequences of random numbers.
explicit X(...)-creates a generator with user-provided state; the implementation -shall specify the constructor argument(s)
u.seed(...)voidsets the current state according to the argument(s); at least -functions with the same signature as the non-default -constructor(s) shall be provided. -
v.validation(x)boolcompares the pre-computed and hardcoded 10001th element in the -generator's random number sequence with x. The generator -must have been constructed by its default constructor and -seed must not have been called for the validation to -be meaningful. -
- -

- -Note: The seed member function is similar to the -assign member function in STL containers. However, the -naming did not seem appropriate. - -

- -Classes which model a pseudo-random number generator shall also model -EqualityComparable, i.e. implement operator==. Two -pseudo-random number generators are defined to be equivalent -if they both return an identical sequence of numbers starting from a -given state. -

-Classes which model a pseudo-random number generator should also model -the Streamable concept, i.e. implement operator<< -and operator>>. If so, -operator<< writes all current state of the -pseudo-random number generator to the given ostream so -that operator>> can restore the state at a later -time. The state shall be written in a platform-independent manner, -but it is assumed that the locales used for writing and -reading be the same. - -The pseudo-random number generator with the restored state and the -original at the just-written state shall be equivalent. -

- -Classes which model a pseudo-random number generator may also model -the CopyConstructible and Assignable concepts. However, note that the -sequences of the original and the copy are strongly correlated (in -fact, they are identical), which may make them unsuitable for some -problem domains. Thus, copying pseudo-random number generators is -discouraged; they should always be passed by (non-const) -reference. - -

- -The classes -rand48, -minstd_rand, -and -mt19937 -are models for a pseudo-random number generator. - -

-Note: This type of random-number generator is useful for -numerics, games and testing. The non-zero arguments constructor(s) -and the seed() member function(s) allow for a -user-provided state to be installed in the generator. This is useful -for debugging Monte-Carlo algorithms and analyzing particular test -scenarios. The Streamable concept allows to save/restore the state of -the generator, for example to re-run a test suite at a later time. - - -

Quasi-Random Number Generators

- -A quasi-random number generator is a Number Generator which provides a -deterministic sequence of numbers, based on some algorithm and -internal state. The numbers do not have any statistical properties -(such as uniform distribution or independence of successive values). - -

- -Note: Quasi-random number generators are useful for -Monte-Carlo integrations where specially crafted sequences of random -numbers will make the approximation converge faster. - -

- -[Does anyone have a model?] - -

-


-Jens Maurer, 2000-02-23 - - - diff --git a/random-distributions.html b/random-distributions.html deleted file mode 100644 index b3c7d5a..0000000 --- a/random-distributions.html +++ /dev/null @@ -1,781 +0,0 @@ - - - - - - -Boost Random Number Library Distributions - - - - -

Random Number Library Distributions

- - - -

Introduction

- -In addition to the random number -generators, this library provides distribution functions which map -one distribution (often a uniform distribution provided by some -generator) to another. - -

-Usually, there are several possible implementations of any given -mapping. Often, there is a choice between using more space, more -invocations of the underlying source of random numbers, or more -time-consuming arithmetic such as trigonometric functions. This -interface description does not mandate any specific implementation. -However, implementations which cannot reach certain values of the -specified distribution or otherwise do not converge statistically to -it are not acceptable. - -

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
distributionexplanationexample
uniform_smallintdiscrete uniform distribution on a small set of integers (much -smaller than the range of the underlying generator)drawing from an urn
uniform_intdiscrete uniform distribution on a set of integers; the underlying -generator may be called several times to gather enough randomness for -the outputdrawing from an urn
uniform_01continuous uniform distribution on the range [0,1); important -basis for other distributions-
uniform_realcontinuous uniform distribution on some range [min, max) of real -numbersfor the range [0, 2pi): randomly dropping a stick and measuring -its angle in radiants (assuming the angle is uniformly -distributed)
bernoulli_distributionBernoulli experiment: discrete boolean valued distribution with -configurable probabilitytossing a coin (p=0.5)
geometric_distributionmeasures distance between outcomes of repeated Bernoulli experimentsthrowing a die several times and counting the number of tries -until a "6" appears for the first time
triangle_distribution??
exponential_distributionexponential distributionmeasuring the inter-arrival time of alpha particles emitted by -radioactive matter
normal_distributioncounts outcomes of (infinitely) repeated Bernoulli experimentstossing a coin 10000 times and counting how many front sides are shown
lognormal_distributionlognormal distribution (sometimes used in simulations)measuring the job completion time of an assembly line worker
uniform_on_sphereuniform distribution on a unit sphere of arbitrary dimensionchoosing a random point on Earth (assumed to be a sphere) where to -spend the next vacations
- -

- -The template parameters of the distribution functions are always in -the order -

    -
  • Underlying source of random numbers -
  • If applicable, return type, with a default to a reasonable type. -
- -

-The distribution functions no longer satisfy the input iterator -requirements (std:24.1.1 [lib.input.iterators]), because this is -redundant given the Generator interface and imposes a run-time -overhead on all users. Moreover, a Generator interface appeals to -random number generation as being more "natural". Use an -iterator adaptor -if you need to wrap any of the generators in an input iterator -interface. -

- -All of the distribution functions described below store a non-const -reference to the underlying source of random numbers. Therefore, the -distribution functions are not Assignable. However, they are -CopyConstructible. Copying a distribution function will copy the -parameter values. Furthermore, both the copy and the original will -refer to the same underlying source of random numbers. Therefore, -both the copy and the original will obtain their underlying random -numbers from a single sequence. - -

-In this description, I have refrained from documenting those members -in detail which are already defined in the -concept documentation. - - -

Synopsis of the distributions available from header -<boost/random.hpp>

- -
-namespace boost {
-  template<class UniformRandomNumberGenerator, class IntType = int>
-  class uniform_smallint;
-  template<class UniformRandomNumberGenerator, class IntType = int>
-  class uniform_int;
-  template<class UniformRandomNumberGenerator, class RealType = double>
-  class uniform_01;
-  template<class UniformRandomNumberGenerator, class RealType = double>
-  class uniform_real;
-
-  // discrete distributions
-  template<class UniformRandomNumberGenerator>
-  class bernoulli_distribution;
-  template<class UniformRandomNumberGenerator, class IntType = int>
-  class geometric_distribution;
-
-  // continuous distributions
-  template<class UniformRandomNumberGenerator, class RealType = double>
-  class triangle_distribution;
-  template<class UniformRandomNumberGenerator, class RealType = double>
-  class exponential_distribution;
-  template<class UniformRandomNumberGenerator, class RealType = double>
-  class normal_distribution;
-  template<class UniformRandomNumberGenerator, class RealType = double>
-  class lognormal_distribution;
-  template<class UniformRandomNumberGenerator, class RealType = double,
-    class Cont = std::vector<RealType> >
-  class uniform_on_sphere;
-}
-
- -

Class template -uniform_smallint

- -

Synopsis

- -
-#include <boost/random/uniform_smallint.hpp>
-
-template<class UniformRandomNumberGenerator, class IntType = int>
-class uniform_smallint
-{
-public:
-  typedef UniformRandomNumberGenerator base_type;
-  typedef IntType result_type;
-  static const bool has_fixed_range = false;
-  uniform_smallint(base_type & rng, IntType min, IntType max);
-  result_type operator()();
-  result_type min() const;
-  result_type max() const;
-};
-
- -

Description

- -The distribution function uniform_smallint models a -uniform random number -generator. 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 -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 UniformRandomNumberGenerator shall -denote a class which models a uniform random number generator. -Additionally, UniformRandomNumberGenerator::result_type -shall denote an integral type. 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. - - -

Members

- -
uniform_smallint(base_type & rng, IntType min, IntType max)
- -Effects: Constructs a uniform_smallint -functor with the uniform random number generator rng as -the underlying source of random numbers. min and -max are the lower and upper bounds of the output range, -respectively. - - -

Class template uniform_int

- -

Synopsis

- -
-#include <boost/random/uniform_int.hpp>
-
-template<class UniformRandomNumberGenerator, class IntType = int>
-class uniform_int
-{
-public:
-  typedef UniformRandomNumberGenerator base_type;
-  typedef IntType result_type;
-  static const bool has_fixed_range = false;
-  uniform_int(base_type & rng, IntType min, IntType max);
-  IntType operator()();
-  result_type min() const;
-  result_type max() const;
-};
-
- -

Description

- -The distribution function uniform_int models a -uniform random number -generator. 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. - -

Members

- -
uniform_int(base_type & rng, IntType min, IntType max)
- -Effects: Constructs a uniform_int functor -with the uniform random number generator rng as the -underlying source of random numbers. min and -max are the lower and upper bounds of the output range, -respectively. - -

-Note: Invocations of operator() may call the -underlying generator several times and concatenate the result to build -the required range. Thus, using this distribution with generators -such as linear congruential ones which tend to produce non-random bits -in some positions is strongly discouraged. - -

Class template uniform_01

- -

Synopsis

- -
-#include <boost/random/uniform_01.hpp>
-
-template<class UniformRandomNumberGenerator, class RealType = double>
-class uniform_01
-{
-public:
-  typedef UniformRandomNumberGenerator base_type;
-  typedef RealType result_type;
-  static const bool has_fixed_range = false;
-  explicit uniform_01(base_type & rng);
-  result_type operator()();
-  result_type min() const;
-  result_type max() const;
-};
-
- -

Description

- -The distribution function uniform_01 models a -uniform random number -generator. On each invocation, it returns a random floating-point -value uniformly distributed in the range [0..1). - -The value is computed using -std::numeric_limits<RealType>::digits random binary -digits, i.e. the mantissa of the floating-point value is completely -filled with random bits. [Note: Should this be configurable?] - -

-The template parameter RealType shall denote a float-like -value type with support for binary operators +, -, and /. It must be -large enough to hold floating-point numbers of value -rng.max()-rng.min()+1. -

-base_type::result_type must be a number-like value type, -it must support static_cast<> to -RealType and binary operator -. - -

- -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) boost::bigfloat class with random bits -efficiently. It's probably time for a traits class. - -

Members

- -
explicit uniform_01(base_type & rng)
- -Effects: Constructs a uniform_01 functor -with the given uniform random number generator as the underlying -source of random numbers. - - -

Class template uniform_real

- -

Synopsis

- -
-#include <boost/random/uniform_real.hpp>
-
-template<class UniformRandomNumberGenerator, class RealType = double>
-class uniform_real
-{
-public:
-  typedef UniformRandomNumberGenerator base_type;
-  typedef RealType result_type;
-  static const bool has_fixed_range = false;
-  uniform_real(base_type & rng, RealType min, RealType max);
-  result_type operator()();
-  result_type min() const;
-  result_type max() const;
-};
-
- -

Description

- -The distribution function uniform_real models a -uniform random number -generator. 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<RealType>::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. - - -

Members

- -
explicit uniform_real(base_type & rng, RealType min, RealType max)
- -Effects: Constructs a uniform_real -functor. rng specifies the uniform random number -generator to be used as the underlying source of random numbers, -min and max are the lower and upper bounds of -the output range. - - -

Class template -bernoulli_distribution

- -

Synopsis

- -
-#include <boost/random/bernoulli_distribution.hpp>
-
-template<class UniformRandomNumberGenerator>
-class bernoulli_distribution
-{
-public:
-  typedef UniformRandomNumberGenerator base_type;
-  typedef bool result_type;
-  bernoulli_distribution(base_type & rng, double q);
-  result_type operator()();
-};
-
- -

Description

- -Instantiations of class template bernoulli_distribution -model a number -generator. It transforms a uniform distribution into a Bernoulli -one. - -

Members

- -
bernoulli_distribution(base_type & rng, double q)
- -Effects: Constructs a -bernoulli_distribution functor with the uniform random -number generator rng as the underlying source of random -numbers. q is the parameter for the distribution. - -
result_type operator()()
-Returns: A random boolean value with p(true) = q and -p(false) = 1-q. For example, with q = 1/2 this can be interpreted as -tossing a coin. - - -

Class template -geometric_distribution

- -

Synopsis

-
-#include <boost/random/geometric_distribution.hpp>
-
-template<class UniformRandomNumberGenerator, class IntType = int>
-class geometric_distribution
-{
-public:
-  typedef UniformRandomNumberGenerator base_type;
-  typedef IntType result_type;
-  geometric_distribution(base_type& rng, double q);
-  result_type operator()();
-};
-
- - -

Description

- -Instantiations of class template geometric_distribution -model a number -generator. It transforms a uniform distribution into a geometric -one. - - -

Members

- -
geometric_distribution(base_type& rng, const result_type& q)
- -Effects: Constructs a -geometric_distribution functor with the uniform random -number generator rng as the underlying source of random -numbers. q is the parameter for the distribution. -

- -

result_type operator()()
- -Returns: A random integer value i >= 1 with -p(i) = (1-q) * qi-1. For example, with q = 5/6 this can be -interpreted as the number of times one has to roll a die until a given -number shows up. - - -

Class template -triangle_distribution

- -

Synopsis

-
-#include <boost/random/triangle_distribution.hpp>
-
-template<class UniformRandomNumberGenerator, class RealType = double>
-class triangle_distribution
-{
-public:
-  typedef UniformRandomNumberGenerator base_type;
-  typedef RealType result_type;
-  triangle_distribution(base_type& rng, result_type a, result_type b, result_type c);
-  result_type operator()();
-};
-
- - -

Description

- -Instantiations of class template triangle_distribution -model a number -generator. It transforms a uniform distribution into a triangle -one. - - -

Members

- -
triangle_distribution(base_type& rng, result_type a, result_type b, result_type c)
- -Effects: Constructs a -triangle_distribution functor with the uniform random -number generator rng as the underlying source of random -numbers. a, b, c are the parameters for the distribution. -

- -

result_type operator()()
- -Returns: A random floating-point value x -where a <= x <= c; x has a triangle -distribution, where b is the most probable value for -x. - - -

Class template -exponential_distribution

- -

Synopsis

-
-#include <boost/random/exponential_distribution.hpp>
-
-template<class UniformRandomNumberGenerator, class RealType = double>
-class exponential_distribution
-{
-public:
-  typedef UniformRandomNumberGenerator base_type;
-  typedef RealType result_type;
-  exponential_distribution(base_type& rng, const result_type& lambda);
-  result_type operator()();
-};
-
- -

Description

- -Instantiations of class template exponential_distribution -model a number -generator. It transforms a uniform distribution into an -exponential one. - -

Members

- -
exponential_distribution(base_type& rng, const result_type& lambda)
- -Effects: Constructs an -exponential_distribution functor with the uniform random -number generator rng as the underlying source of random -numbers. lambda is the parameter for the distribution. -

- -

result_type operator()()
- -Returns: A random floating-point value x -> 0 with p(x) = lambda * exp(-lambda * -x). - - -

Class template -normal_distribution

- -

Synopsis

- -
-#include <boost/random/normal_distribution.hpp>
-
-template<class UniformRandomNumberGenerator, class RealType = double>
-class normal_distribution
-{
-public:
-  typedef UniformRandomNumberGenerator base_type;
-  typedef RealType result_type;
-  explicit normal_distribution(base_type& rng, const result_type& mean = 0,
-			       const result_type& sigma = 1);
-  result_type operator()();
-};
-
- -

Description

- -Instantiations of class template normal_distribution -model a number -generator. It transforms a uniform distribution into a -normal (Gaussian) one. - -

Members

- -
normal_distribution(base_type& rng, const result_type& mean = 0,
-		     const result_type& sigma = 1)
- -Effects: Constructs a -normal_distribution functor with the uniform random -number generator rng as the underlying source of random -numbers. mean and sigma are the parameters for -the distribution. -

- -

result_type operator()()
- -Returns: A random floating-point value x -with p(x) = 1/sqrt(2*pi*sigma) * exp(- (x-mean)2 / -(2*sigma2) ). - - -

Class template -lognormal_distribution

- -

Synopsis

- -
-#include <boost/random/lognormal_distribution.hpp>
-
-template<class UniformRandomNumberGenerator, class RealType = double>
-class lognormal_distribution
-{
-public:
-  typedef UniformRandomNumberGenerator base_type;
-  typedef RealType result_type;
-  explicit lognormal_distribution(base_type& rng, const result_type& mean,
-			          const result_type& sigma);
-  result_type operator()();
-};
-
- -

Description

- -Instantiations of class template lognormal_distribution -model a number -generator. It transforms a uniform distribution into a -lognormal one. - -

Members

- -
lognormal_distribution(base_type& rng, const result_type& mean,
-	   	       const result_type& sigma)
- -Effects: Constructs a -lognormal_distribution functor with the uniform random -number generator rng as the underlying source of random -numbers. mean and sigma are the mean and -standard deviation of the lognormal distribution. -

- -

result_type operator()()
- - -Returns: A random floating-point value x -with p(x) = 1/(x * normal_sigma * sqrt(2*pi)) * exp( --(log(x)-normal_mean)2 / (2*normal_sigma2) ) -for x > 0, -where normal_mean = log(mean2/sqrt(sigma2 -+ mean2)) -and normal_sigma = sqrt(log(1 + sigma2/mean2)). - - -

Class template -uniform_on_sphere

- -

Synopsis

- -
-#include <boost/random/uniform_on_sphere.hpp>
-
-template<class UniformRandomNumberGenerator, class RealType = double,
-  class Cont = std::vector<RealType> >
-class uniform_on_sphere
-{
-public:
-  typedef UniformRandomNumberGenerator base_type;
-  typedef Cont result_type;
-  explicit uniform_on_sphere(base_type & rng, int dim = 2);
-  const result_type & operator()();
-};
-
- -

Description

- -Instantiations of class template uniform_on_sphere model a -Generator (std:25.2.6 [lib.alg.generate]). It transforms a uniform -distribution into a uniform distribution on the unit sphere of -arbitrary dimension. The Cont template parameter must be -a STL-like container type with begin and end -operations returning non-const ForwardIterators of type -Cont::iterator. - -

Members

- -
explicit uniform_on_sphere(base_type & rng, int dim = 2)
- -Effects: Constructs a uniform_on_sphere -functor with the uniform random number generator rng as -the underlying source of random numbers. dim is the -dimension of the sphere. -

- -

result_type operator()()
- -Returns: A position on the unit sphere of -dim dimensions in cartesian coordinates. The positions -are uniformly distributed on the unit sphere. -

-Complexity: Proportional to the number of dimensions. - -

-


-Jens Maurer, 2001-04-15 - - - diff --git a/random-generators.html b/random-generators.html deleted file mode 100644 index 353fb99..0000000 --- a/random-generators.html +++ /dev/null @@ -1,1042 +0,0 @@ - - - - - - -Boost Random Number Library Generators - - - - -

Random Number Library Generators

- - - -

Introduction

- -This library provides several pseudo-random number generators. The -quality of a pseudo-random number generator crucially depends on both -the algorithm and its parameters. This library implements the -algorithms as class templates with template value parameters, hidden -in namespace boost::random. Any particular choice of -parameters is represented as the appropriately specializing -typedef in namespace boost. -

- -Pseudo-random number generators should not be constructed -(initialized) frequently during program execution, for two reasons. -First, initialization requires full initialization of the internal -state of the generator. Thus, generators with a lot of internal state -(see below) are costly to initialize. Second, initialization always -requires some value used as a "seed" for the generated sequence. It -is usually difficult to obtain several good seed values. For example, -one method to obtain a seed is to determine the current time at the -highest resolution available, e.g. microseconds or nanoseconds. When -the pseudo-random number generator is initialized again with the -then-current time as the seed, it is likely that this is at a -near-constant (non-random) distance from the time given as the seed -for first initialization. The distance could even be zero if the -resolution of the clock is low, thus the generator re-iterates the -same sequence of random numbers. For some applications, this is -inappropriate. -

- -Note that all pseudo-random number generators described below are -CopyConstructible and Assignable. Copying or assigning a generator -will copy all its internal state, so the original and the copy will -generate the identical sequence of random numbers. Often, such -behavior is not wanted. In particular, beware of the algorithms from -the standard library such as std::generate. They take a functor -argument by value, thereby invoking the copy constructor when called. -

- -The following table gives an overview of some characteristics of the -generators. The cycle length is a rough estimate of the quality of -the generator; the approximate relative speed is a performance -measure, higher numbers mean faster random number generation. - -

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
generatorlength of cycleapprox. memory requirementsapprox. relative speedcomment
minstd_rand231-2sizeof(int32_t)40-
rand48248-1sizeof(uint64_t)80-
lrand48 (C library)248-1-20global state
ecuyer1988approx. 2612*sizeof(int32_t)20-
kreutzer1986?1368*sizeof(uint32_t)60-
hellekalek1995231-1sizeof(int32_t)3good uniform distribution in several dimensions
mt11213b211213-1352*sizeof(uint32_t)100good uniform distribution in up to 350 dimensions
mt19937219937-1625*sizeof(uint32_t)100good uniform distribution in up to 623 dimensions
lagged_fibonacci607approx. 232000607*sizeof(double)150-
lagged_fibonacci1279approx. 2670001279*sizeof(double)150-
lagged_fibonacci2281approx. 21200002281*sizeof(double)150-
lagged_fibonacci3217approx. 21700003217*sizeof(double)150-
lagged_fibonacci4423approx. 22300004423*sizeof(double)150-
lagged_fibonacci9689approx. 25100009689*sizeof(double)150-
lagged_fibonacci19937approx. 2105000019937*sizeof(double)150-
lagged_fibonacci23209approx. 2120000023209*sizeof(double)140-
lagged_fibonacci44497approx. 2230000044497*sizeof(double)60-
- -

-As observable from the table, there is generally a -quality/performance/memory trade-off to be decided upon when choosing -a random-number generator. The multitude of generators provided in -this library allows the application programmer to optimize the -trade-off with regard to his application domain. Additionally, -employing several fundamentally different random number generators for -a given application of Monte Carlo simulation will improve the -confidence in the results. -

- -If the names of the generators don't ring any bell and you have no -idea which generator to use, it is reasonable to employ -mt19937 for a start: It is fast and has acceptable -quality. - -

-Note: These random number generators are not intended for use -in applications where non-deterministic random numbers are required. -See nondet_random.html for a choice -of (hopefully) non-deterministic random number generators. - -

-In this description, I have refrained from documenting those members -in detail which are already defined in the -concept documentation. - - -

Synopsis of the generators available from header -<boost/random.hpp>

- -
-namespace boost {
-  namespace random {
-    template<class IntType, IntType m>
-    class const_mod;
-    template<class IntType, IntType a, IntType c, IntType m, IntType val>
-    class linear_congruential;
-  }
-  class rand48;
-  typedef random::linear_congruential< /* ... */ > minstd_rand0;
-  typedef random::linear_congruential< /* ... */ > minstd_rand;
-
-  namespace random {
-    template<class DataType, int n, int m, int r, DataType a, int u,
-        int s, DataType b, int t, DataType c, int l, IntType val>
-    class mersenne_twister;
-  }
-  typedef random::mersenne_twister< /* ... */ > mt11213b;
-  typedef random::mersenne_twister< /* ... */ > mt19937;
-
-  namespace random {
-    template<class FloatType, unsigned int  p, unsigned int q>
-    class lagged_fibonacci;
-  }
-  typedef random::lagged_fibonacci< /* ... */ > lagged_fibonacci607;
-  typedef random::lagged_fibonacci< /* ... */ > lagged_fibonacci1279;
-  typedef random::lagged_fibonacci< /* ... */ > lagged_fibonacci2281;
-  typedef random::lagged_fibonacci< /* ... */ > lagged_fibonacci3217;
-  typedef random::lagged_fibonacci< /* ... */ > lagged_fibonacci4423;
-  typedef random::lagged_fibonacci< /* ... */ > lagged_fibonacci9689;
-  typedef random::lagged_fibonacci< /* ... */ > lagged_fibonacci19937;
-  typedef random::lagged_fibonacci< /* ... */ > lagged_fibonacci23209;
-  typedef random::lagged_fibonacci< /* ... */ > lagged_fibonacci44497;  
-} // namespace boost
-
- - -

Class template -random::const_mod

- -

Synopsis

- -
-template<class IntType, IntType m>
-class random::const_mod
-{
-public:
-  template<IntType c>
-  static IntType add(IntType x);
-
-  template<IntType a>
-  static IntType mult(IntType x);
-
-  template<IntType a, IntType c>
-  static IntType mult_add(IntType x);
-
-  static IntType invert(IntType x);
-private:
-  const_mod();         // don't instantiate
-};
-
- -

Description

- -Class template const_mod provides functions performing -modular arithmetic, carefully avoiding overflows. All member -functions are static; there shall be no objects of type -const_mod<>. -

- -The template parameter IntType shall denote an integral -type, m is the modulus. -

- -Note: For modulo multiplications with large m, a trick allows -fast computation under certain conditions, see -

-"A more portable FORTRAN random number generator", Linus Schrage, ACM -Transactions on Mathematical Software, Vol. 5, No. 2, June 1979, pp. 132-138 -
- - -

Member functions

- -
template<IntType c> static IntType add(IntType x)
- -Returns: (x+c) mod m - -
template<IntType a> static IntType mult(IntType x)
- -Returns: (a*x) mod m - -
template<IntType a, IntType c> static IntType
-mult_add(IntType x)
- -Returns: (a*x+c) mod m - -
static IntType invert(IntType x)
- -Returns: i so that (a*i) mod m == 1 -
-Precondition: m is prime - - -

Class template -random::linear_congruential

- -

Synopsis

- -
-#include <boost/random/linear_congruential.hpp>
-
-template<class IntType, IntType a, IntType c, IntType m>
-class linear_congruential
-{
-public:
-  typedef IntType result_type;
-  static const IntType multiplier = a;
-  static const IntType increment = c;
-  static const IntType modulus = m;
-  static const bool has_fixed_range = true;
-  static const result_type min_value;
-  static const result_type max_value;
-  explicit linear_congruential_fixed(IntType x0 = 1);
-  // compiler-generated copy constructor and assignment operator are fine
-  void seed(IntType x0);
-  IntType operator()();
-};
-
-typedef random::linear_congruential<long, 16807L, 0, 2147483647L,
-     1043618065L> minstd_rand0;
-typedef random::linear_congruential<long, 48271L, 0, 2147483647L,
-     399268537L> minstd_rand;
-
- -

Description

- -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. -
-For each choice of the parameters a, c, m, some distinct type is -defined, so that the static members do not interfere with -regard to the one definition rule. - -

Members

- -
explicit linear_congruential(IntType x0 = 1)
- -Effects: Constructs a -linear_congruential generator with x(0) := -x0. - -
void seed(IntType x0)
- -Effects: Changes the current value x(n) of the -generator to x0. - -

Specializations

- -The specialization minstd_rand0 was originally suggested -in -
-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 -
- -It is examined more closely together with minstd_rand in -
-"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 -
- - -

Class rand48

- -

Synopsis

-
-#include <boost/random/linear_congruential.hpp>
-
-class rand48 
-{
-public:
-  typedef int32_t result_type;
-  static const bool has_fixed_range = true;
-  static const int32_t min_value = 0;
-  static const int32_t max_value = 0x7fffffff;
-  
-  explicit rand48(int32_t x0 = 1);
-  explicit rand48(uint64_t x0);
-  // compiler-generated copy ctor and assignment operator are fine
-  void seed(int32_t x0);
-  void seed(uint64_t x0);
-  int32_t operator()();
-};
-
- -

Description

- -Class 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 lrand48() function available on some -systems (assuming lcong48 has not been called). -

-It is only available on systems where uint64_t is -provided as an integral type, so that for example static in-class -constants and/or enum definitions with large uint64_t -numbers work. - -

Constructors

- -
rand48(int32_t x0)
- -Effects: Constructs a rand48 generator -with x(0) := (x0 << 16) | 0x330e. - -
rand48(uint64_t x0)
- -Effects: Constructs a rand48 generator -with x(0) := x0. - -

Seeding

-
void seed(int32_t x0)
- -Effects: Changes the current value x(n) of the -generator to (x0 << 16) | 0x330e. - -
void seed(uint64_t x0)
- -Effects: Changes the current value x(n) of the -generator to x0. - - -

Class template -random::additive_combine

- -

Synopsis

- -
-#include <boost/random/additive_combine.hpp>
-
-template<class MLCG1, class MLCG2, typename MLCG1::result_type val>
-class random::additive_combine
-{
-public:
-  typedef MLCG1 first_base;
-  typedef MLCG2 second_base;
-  typedef typename MLCG1::result_type result_type;
-  static const bool has_fixed_range = true;
-  static const result_type min_value = 1;
-  static const result_type max_value = MLCG1::max_value-1;
-  additive_combine();
-  additive_combine(typename MLCG1::result_type seed1, 
-		   typename MLCG2::result_type seed2);
-  result_type operator()();
-  bool validation(result_type x) const;
-};
-
-typedef random::additive_combine<
-    random::linear_congruential<int32_t, 40014, 0, 2147483563, 0>,
-    random::linear_congruential<int32_t, 40692, 0, 2147483399, 0>,
-  /* unknown */ 0> ecuyer1988;
-
-
- -

Description

- -Instatiations of class template additive_combine model a -pseudo-random number -generator. It combines two multiplicative linear congruential -number generators, i.e. those with c = 0. It is described in -
-"Efficient and Portable Combined Random Number Generators", Pierre -L'Ecuyer, Communications of the ACM, Vol. 31, No. 6, June 1988, -pp. 742-749, 774 -
- -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 val is the validation value -checked by validation. - - -

Members

- -
additive_combine()
- -Effects: Constructs an additive_combine -generator using the default constructors of the two base generators. - -
additive_combine(typename MLCG1::result_type seed1, 
- 		 typename MLCG2::result_type seed2)
- -Effects: Constructs an additive_combine -generator, using seed1 and seed2 as the -constructor argument to the first and second base generator, -respectively. - - -

Specialization

- -The specialization ecuyer1988 was suggested in the above -paper. - - -

Class template -random::shuffle_output

- -

Synopsis

- -
-#include <boost/random/shuffle_output.hpp>
-
-template<class UniformRandomNumberGenerator, int k, 
-  class IntType = typename UniformRandomNumberGenerator::result_type,
-  typename UniformRandomNumberGenerator::result_type val = 0>
-class random::shuffle_output
-{
-public:
-  typedef UniformRandomNumberGenerator base_type;
-  typedef typename base_type::result_type result_type;
-  static const bool has_fixed_range = false;
-
-  shuffle_output();
-  template<class T> explicit shuffle_output(T seed);
-  explicit shuffle_output(const base_type & rng);
-  template<class T> void seed(T s);
-
-  result_type operator()();
-  result_type min() const;
-  result_type max() const;
-  bool validation(result_type) const;
-};
-
- -

Description

- -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. According to Donald E. Knuth, "The Art of -Computer Programming, Vol. 2", the algorithm is described in -
-"Improving a poor random number generator", Carter Bays and -S.D. Durham, ACM Transactions on Mathematical Software, Vol. 2, 1979, -pp. 59-64. -
-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. As an implementation detail, the template -parameter IntType shall denote an integer-like type which -is large enough to hold integer numbers of value k * -base_type::max(). The template parameter -val is the validation value checked by -validation. - - -

Members

- -
shuffle_output()
- -Effects: Constructs a shuffle_output -generator by invoking the default constructor of the base generator. -

-Complexity: Exactly k+1 invocations of the base -generator. - -

template<class T> explicit shuffle_output(T seed)
- -Effects: 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. - -

explicit shuffle_output(const base_type & rng)
- -Precondition: The template argument -UniformRandomNumberGenerator shall denote a -CopyConstructible type. -

-Effects: Constructs a shuffle_output -generator by using a copy of the provided generator. -

-Complexity: Exactly k+1 invocations of the base -generator. - -

template<class T> void seed(T s)
- -Effects: 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. - - -

Specializations

- -According to Harry Erwin (private e-mail), the specialization -kreutzer1986 was suggested in: -
-"System Simulation: programming Styles and Languages (International -Computer Science Series)", Wolfgang Kreutzer, Addison-Wesley, December -1986. -
- - -

Class template -random::inversive_congruential

- -

Synopsis

- -
-#include <boost/random/inversive_congruential.hpp>
-
-template<class IntType, IntType a, IntType b, IntType p>
-class random::inversive_congruential
-{
-public:
-  typedef IntType result_type;
-  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;
-  static const result_type multiplier = a;
-  static const result_type increment = b;
-  static const result_type modulus = p;
-  explicit inversive_congruential(IntType y0 = 1);
-  void seed(IntType y0);
-  IntType operator()();
-};
-
-typedef random::inversive_congruential<int32_t, 9102, 2147483647-36884165, 2147483647> hellekalek1995;
-
- -

Description

- -Instantiations of class template inversive_congruential model a -pseudo-random number -generator. It uses the inversive congruential algorithm (ICG) -described in -
-"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 -
- -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. -

-Note: 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. - - -

Members

- -
inversive_congruential(IntType y0 = 1)
- -Effects: Constructs an -inversive_congruential generator with -y0 as the initial state. - -
void seed(IntType y0)
- -Effects: -Changes the current state to y0. - - -

Specialization

- -The specialization hellekalek1995 was suggested in the -above paper. - - -

Class template -random::mersenne_twister

- -

Synopsis

- -
-#include <boost/random/mersenne_twister.hpp>
-
-template<class DataType, int n, int m, int r, DataType a, int u,
-int s, DataType b, int t, DataType c, int l, IntType val>
-class random::mersenne_twister
-{
-public:
-  typedef DataType result_type;
-  static const bool has_fixed_range = true;
-  static const result_type min_value;
-  static const result_type max_value;
-  mersenne_twister();
-  explicit mersenne_twister(DataType value);
-  template<class Generator> explicit mersenne_twister(Generator & gen);
-  // compiler-generated copy ctor and assignment operator are fine
-  void seed();
-  void seed(DataType value);
-  template<class Generator> void seed(Generator & gen);
-  result_type operator()();
-  bool validation(result_type) const;
-};
-
-typedef mersenne_twister<uint32_t,351,175,19,0xccab8ee7,11,7,0x31b6ab00,15,0xffe50000,17, /* unknown */ 0> mt11213b;
-typedef mersenne_twister<uint32_t,624,397,31,0x9908b0df,11,7,0x9d2c5680,15,0xefc60000,18, 3346425566U> mt19937;
-
- -

Description

- -Instantiations of class template mersenne_twister model a -pseudo-random number -generator. It uses the algorithm described in - -
-"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. -http://www.math.keio.ac.jp/matumoto/emt.html -
- -Note: 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. -
-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. - -

Constructors

- -
mersenne_twister()
- -Effects: Constructs a mersenne_twister -and calls seed(). - -
explicit mersenne_twister(result_type value)
- -Effects: Constructs a mersenne_twister -and calls seed(value). - -
template<class Generator> explicit mersenne_twister(Generator & gen)
- -Effects: Constructs a mersenne_twister -and calls seed(gen). -

-Note: When using direct-initialization syntax with an lvalue -(e.g. in the variable definition Gen gen2(gen);), this -templated constructor will be preferred over the compiler-generated -copy constructor. For variable definitions which should copy the -state of another mersenne_twister, use e.g. Gen -gen2 = gen;, which is copy-initialization syntax and guaranteed -to invoke the copy constructor. - -

Seeding

- -
void seed()
- -Effects: Calls seed(result_type(4357)). - -
void seed(result_type value)
- -Effects: Constructs a -linear_congruential<uint32_t, 69069, 0, 0, 0> -generator with the constructor parameter -value and calls seed with it. - -
template<class Generator> void seed(Generator & gen)
- -Effects: Sets the state of this -mersenne_twister to the values returned by n -invocations of gen. - -

- -Complexity: Exactly n invocations of -gen. -

-Note: When invoking seed with an lvalue, -overload resolution chooses the function template unless the type of -the argument exactly matches result_type. For other -integer types, you should convert the argument to -result_type explicitly. - -

Specializations

- -The specializations mt11213b and mt19937 are -from the paper cited above. - -

Class template -random::lagged_fibonacci

- -

Synopsis

- -
-#include <boost/random/lagged_fibonacci.hpp>
-
-template<class FloatType, unsigned int p, unsigned int q>
-class lagged_fibonacci
-{
-public:
-  typedef FloatType result_type;
-  static const bool has_fixed_range = false;
-  static const unsigned int long_lag = p;
-  static const unsigned int short_lag = q;
-  result_type min() const { return 0.0; }
-  result_type max() const { return 1.0; }
-  lagged_fibonacci();
-  explicit lagged_fibonacci(uint32_t value);
-  template<class Generator>
-  explicit lagged_fibonacci(Generator & gen);
-  // compiler-generated copy ctor and assignment operator are fine
-  void seed(uint32_t value = 331u);
-  template<class Generator> void seed(Generator & gen);
-  result_type operator()();
-  bool validation(result_type x) const;
-};
-
-typedef random::lagged_fibonacci<double, 607, 273> lagged_fibonacci607;
-typedef random::lagged_fibonacci<double, 1279, 418> lagged_fibonacci1279;
-typedef random::lagged_fibonacci<double, 2281, 1252> lagged_fibonacci2281;
-typedef random::lagged_fibonacci<double, 3217, 576> lagged_fibonacci3217;
-typedef random::lagged_fibonacci<double, 4423, 2098> lagged_fibonacci4423;
-typedef random::lagged_fibonacci<double, 9689, 5502> lagged_fibonacci9689;
-typedef random::lagged_fibonacci<double, 19937, 9842> lagged_fibonacci19937;
-typedef random::lagged_fibonacci<double, 23209, 13470> lagged_fibonacci23209;
-typedef random::lagged_fibonacci<double, 44497, 21034> lagged_fibonacci44497;
-
- -

Description

- -Instantiations of class template lagged_fibonacci model a -pseudo-random number -generator. It uses a lagged Fibonacci algorithm with two lags p -and q, evaluated in floating-point arithmetic: x(i) = x(i-p) + x(i-q) -(mod 1) with p > q. See - -
-"Uniform random number generators for supercomputers", Richard Brent, -Proc. of Fifth Australian Supercomputer Conference, Melbourne, -Dec. 1992, pp. 704-706. -
- -

-Note: 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. -
-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. - -

Constructors

- -
lagged_fibonacci()
-Effects: Constructs a lagged_fibonacci -generator and calls seed(). - -
explicit lagged_fibonacci(uint32_t value)
-Effects: Constructs a lagged_fibonacci -generator and calls seed(value). - -
template<class Generator> explicit lagged_fibonacci(Generator & gen)
-Effects: Constructs a lagged_fibonacci -generator and calls seed(gen). - -

Seeding

- -
void seed()
-Effects: Calls seed(331u). - -
void seed(uint32_t value)
-Effects: Constructs a minstd_rand0 -generator with the constructor parameter value and calls -seed with it. - -
template<class Generator> void seed(Generator & gen)
-Effects: Sets the state of this -lagged_fibonacci to the values returned by p -invocations of uniform_01<gen, FloatType>. -
-Complexity: Exactly p invocations of -gen. - -

Specializations

-The specializations lagged_fibonacci607 -... lagged_fibonacci44497 (see above) use well tested -lags. (References will be added later.) - - -

Performance

- -The test program random_speed.cpp -measures the execution times of the -random.hpp implementation of the above -algorithms in a tight loop. The performance has been evaluated on a -Pentium Pro 200 MHz with gcc 2.95.2, Linux 2.2.13, glibc 2.1.2. - -

- - - - - - - - - - - - - - - - - - -
classtime per invocation [usec]
rand480.096
rand48 run-time configurable0.697
lrand48 glibc 2.1.20.844
minstd_rand0.174
ecuyer19880.445
kreutzer19860.249
hellekalek1995 (inversive)4.895
mt11213b0.165
mt199370.165
mt19937 original0.185
lagged_fibonacci6070.111
lagged_fibonacci44230.112
lagged_fibonacci199370.113
lagged_fibonacci232090.122
lagged_fibonacci444970.263
- -

-The measurement error is estimated at +/- 10 nsec. - -

-


-Jens Maurer, 2001-04-15 - - - diff --git a/random-misc.html b/random-misc.html deleted file mode 100644 index 86fefba..0000000 --- a/random-misc.html +++ /dev/null @@ -1,93 +0,0 @@ - - - - - - -Boost Random Number Generator Library (Miscellaneous) - - - - -

Random Number Generator Library --- Miscellaneous Decorators

- - - -

Introduction

- -These decorator class templates allow adaptation of the random number -generators and distribution functions to concepts found in the C++ -Standard Library, in particular the RandomNumberGenerator and the -InputIterator concepts. The latter adaptation is useful, because the -the basic random number generators do not implement the InputIterator -requirements per se, in contrast to the distribution functions. - - -

Synopsis of miscellaneous decorators in -header <boost/random.hpp>

- -
-namespace boost {
-  template<class UniformRandomNumberGenerator, class IntType = long>
-  class random_number_generator;
-  template<class Generator>
-  class generator_iterator;
-} // namespace boost
-
- - -

Class template -random_number_generator

- -

Synopsis

-
-template<class UniformRandomNumberGenerator, class IntType = long>
-class random_number_generator
-{
-public:
-  typedef UniformRandomNumberGenerator base_type;
-  typedef IntType argument_type;
-  typedef IntType result_type;
-  random_number_generator(base_type & rng);
-  result_type operator()(argument_type n);
-};
-
- -

Description

- -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. -

- -Note: I consider it unfortunate that the C++ Standard uses -the name RandomNumberGenerator for something rather specific. - -

Members

- -
random_number_generator(base_type & rng)
- -Effects: Constructs a -random_number_generator functor with the given uniform -random number generator as the underlying source of random numbers. - -
result_type operator()(argument_type n)
- -Returns: The value of -uniform_int<base_type>(rng, 0, n-1)(). - -

-


-Jens Maurer, 2001-11-19 - - - diff --git a/random-performance.html b/random-performance.html deleted file mode 100644 index 0ec52f3..0000000 --- a/random-performance.html +++ /dev/null @@ -1,241 +0,0 @@ - - - - -Boost Random Number Library Performance - - - - -

Random Number Library Performance

- -For some people, performance of random number generation is an -important consideration when choosing a random number generator or a -particular distribution function. This page provides numerous -performance tests with the wide variety of generators and -distributions available in the boost library. -

-The performance has been evaluated on a Pentium Pro 200 MHz with gcc -2.95.2, Linux 2.2.13, glibc 2.1.2. The speed is reported in million -random numbers per second (M rn/sec), generated in a tight loop. -

- - -

Basic Generators

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
generatorM rn/sectime per random number [usec]relative speed compared to fastest [percent]
rand485.380.18361%
rand48 run-time configurable1.480.67717%
lrand48 glibc 2.1.21.190.84313%
minstd_rand2.390.31835%
ecuyer19881.120.89213%
kreutzer19863.870.25843%
hellekalek1995 (inversive)0.205.122%
mt11213b6.070.16568%
mt199376.060.16568%
mt19937 original5.330.18860%
lagged_fibonacci6078.900.112100%
lagged_fibonacci44238.540.11796%
lagged_fibonacci199377.490.13384%
lagged_fibonacci232096.630.15174%
lagged_fibonacci444974.010.25045%
-

-Note that the lagged Fibonacci generators produce floating-point -numbers, whereas all others produce integers. - -

Distributions

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
[M rn/sec]minstd_randkreutzer1986mt19937lagged_fibonacci607
uniform_smallint1.261.551.93-
uniform_011.791.883.037.74
uniform_real1.741.562.346.62
geometric0.5930.6290.7530.916
triangle0.971.021.351.31
exponential0.8490.8280.8871.53
normal (polar method)0.6080.6260.7380.755
lognormal0.4170.4420.4700.481
uniform_on_sphere0.1540.1550.1740.218
-

-Note that the lagged Fibonacci generator is at least 2.5 times faster -than the Mersenne twister when generating uniformly distributed -floating-point numbers. For more sophisticated distributions, the -speed improvement is less. Note however that these distributions have -not been optimized for speed, yet. -

-


-Jens Maurer, 2001-04-15 - - - diff --git a/random_demo.cpp b/random_demo.cpp deleted file mode 100644 index db0be38..0000000 --- a/random_demo.cpp +++ /dev/null @@ -1,126 +0,0 @@ -/* boost random_demo.cpp profane demo - * - * Copyright Jens Maurer 2000 - * Permission to use, copy, modify, sell, and distribute this software - * is hereby granted without fee provided that the above copyright notice - * appears in all copies and that both that copyright notice and this - * permission notice appear in supporting documentation, - * - * Jens Maurer makes no representations about the suitability of this - * software for any purpose. It is provided "as is" without express or - * implied warranty. - * - * $Id$ - * - * A short demo program how to use the random number library. - */ - -#include -#include -#include // std::time - -#include -#include -#include - -// Sun CC doesn't handle boost::iterator_adaptor yet -#if !defined(__SUNPRO_CC) || (__SUNPRO_CC > 0x530) -#include -#endif - -#ifdef BOOST_NO_STDC_NAMESPACE -namespace std { - using ::time; -} -#endif - -// This is a typedef for a random number generator. -// Try boost::mt19937 or boost::ecuyer1988 instead of boost::minstd_rand -typedef boost::minstd_rand base_generator_type; - -// This is a reproducible simulation experiment. See main(). -void experiment(base_generator_type & generator) -{ - // Define a uniform random number distribution of integer values between - // 1 and 6 inclusive. The random numbers come from "generator". - typedef boost::uniform_smallint generator_type; - generator_type die_gen(generator, 1, 6); - -#if !defined(__SUNPRO_CC) || (__SUNPRO_CC > 0x530) - // If you want to use an STL iterator interface, use iterator_adaptors.hpp. - // Unfortunately, this doesn't work on SunCC yet. - boost::generator_iterator_generator::type - die = boost::make_generator_iterator(die_gen); - for(int i = 0; i < 10; i++) - std::cout << *die++ << " "; - std::cout << '\n'; -#endif -} - -int main() -{ - // Define a random number generator and initialize it with a reproducible - // seed. - // (The seed is unsigned, otherwise the wrong overload may be selected - // when using mt19937 as the base_generator_type.) - base_generator_type generator(42u); - - std::cout << "10 samples of a uniform distribution in [0..1):\n"; - - // Define a uniform random number distribution which produces "double" - // values between 0 and 1 (0 inclusive, 1 exclusive). - boost::uniform_01 uni(generator); - - std::cout.setf(std::ios::fixed); - // You can now retrieve random numbers from that distribution by means - // of a STL Generator interface, i.e. calling the generator as a zero- - // argument function. - for(int i = 0; i < 10; i++) - std::cout << uni() << '\n'; - - /* - * Change seed to something else. - * - * Caveat: std::time(0) is not a very good truly-random seed. When - * called in rapid succession, it could return the same values, and - * thus the same random number sequences could ensue. If not the same - * values are returned, the values differ only slightly in the - * lowest bits. A linear congruential generator with a small factor - * wrapped in a uniform_smallint (see experiment) will produce the same - * values for the first few iterations. This is because uniform_smallint - * takes only the highest bits of the generator, and the generator itself - * needs a few iterations to spread the initial entropy from the lowest bits - * to the whole state. - */ - generator.seed(static_cast(std::time(0))); - - std::cout << "\nexperiment: roll a die 10 times:\n"; - - // You can save a generator's state by copy construction. - base_generator_type saved_generator = generator; - - // When calling other functions which take a generator or distribution - // as a parameter, make sure to always call by reference (or pointer). - // Calling by value invokes the copy constructor, which means that the - // sequence of random numbers at the caller is disconnected from the - // sequence at the callee. - experiment(generator); - - std::cout << "redo the experiment to verify it:\n"; - experiment(saved_generator); - - // After that, both generators are equivalent - assert(generator == saved_generator); - -#ifndef BOOST_NO_OPERATORS_IN_NAMESPACE - { - // You can save the generator state for future use. You can read the - // state back in at any later time using operator>>. - std::ofstream file("rng.saved", std::ofstream::trunc); - file << generator; - } -#endif - // Some compilers don't pay attention to std:3.6.1/5 and issue a - // warning here if "return 0;" is omitted. - return 0; -} diff --git a/random_device.cpp b/random_device.cpp deleted file mode 100644 index 7eadf2c..0000000 --- a/random_device.cpp +++ /dev/null @@ -1,117 +0,0 @@ -/* boost random_device.cpp implementation - * - * Copyright Jens Maurer 2000 - * Permission to use, copy, modify, sell, and distribute this software - * is hereby granted without fee provided that the above copyright notice - * appears in all copies and that both that copyright notice and this - * permission notice appear in supporting documentation, - * - * Jens Maurer makes no representations about the suitability of this - * software for any purpose. It is provided "as is" without express or - * implied warranty. - * - * $Id$ - * - */ - -#include -#include -#include - - -#ifndef BOOST_NO_INCLASS_MEMBER_INITIALIZATION -// A definition is required even for integral static constants -const bool boost::random_device::has_fixed_range; -const boost::random_device::result_type boost::random_device::min_value; -const boost::random_device::result_type boost::random_device::max_value; -#endif - - -#ifdef __linux__ - -// the default is the unlimited capacity device, using some secure hash -// try "/dev/random" for blocking when the entropy pool has drained -const char * const boost::random_device::default_token = "/dev/urandom"; - -/* - * This uses the POSIX interface for unbuffered reading. - * Using buffered std::istream would consume entropy which may - * not actually be used. Entropy is a precious good we avoid - * wasting. - */ - -#if defined(__GNUC__) && defined(_CXXRT_STD_NAME) -// I have severe difficulty to get the POSIX includes to work with -// -fhonor-std and Dietmar Kühl's standard C++ library. Hack around that -// problem for now. -extern "C" { -static const int O_RDONLY = 0; -extern int open(const char *__file, int __oflag, ...); -extern int read(int __fd, __ptr_t __buf, size_t __nbytes); -extern int close(int __fd); -} -#else -#include -#include -#include // open -#include // read, close -#endif - -#include // errno -#include // strerror -#include // std::invalid_argument - - -class boost::random_device::impl -{ -public: - impl(const std::string & token) : path(token) { - fd = open(token.c_str(), O_RDONLY); - if(fd < 0) - error("cannot open"); - } - - ~impl() { if(close(fd) < 0) error("could not close"); } - - unsigned int next() { - unsigned int result; - long sz = read(fd, reinterpret_cast(&result), sizeof(result)); - if(sz == -1) - error("error while reading"); - else if(sz != sizeof(result)) { - errno = 0; - error("EOF while reading"); - } - return result; - } - -private: - void error(const std::string & msg) { - throw std::invalid_argument("boost::random_device: " + msg + - " random-number pseudo-device " + path + - ": " + strerror(errno)); - } - const std::string path; - int fd; -}; - -#endif // __linux__ - - -boost::random_device::random_device(const std::string& token) - : pimpl(new impl(token)) -{ - assert(std::numeric_limits::max() == max_value); -} - -boost::random_device::~random_device() -{ - // the complete class impl is now visible, so we're safe - // (see comment in random.hpp) - delete pimpl; -} - -unsigned int boost::random_device::operator()() -{ - return pimpl->next(); -} diff --git a/random_speed.cpp b/random_speed.cpp deleted file mode 100644 index 81eb82e..0000000 --- a/random_speed.cpp +++ /dev/null @@ -1,219 +0,0 @@ -/* boost random_speed.cpp performance measurements - * - * Copyright Jens Maurer 2000 - * Permission to use, copy, modify, sell, and distribute this software - * is hereby granted without fee provided that the above copyright notice - * appears in all copies and that both that copyright notice and this - * permission notice appear in supporting documentation, - * - * Jens Maurer makes no representations about the suitability of this - * software for any purpose. It is provided "as is" without express or - * implied warranty. - * - * $Id$ - */ - -#include -#include -#include -#include -#include - -/* - * Configuration Section - */ - -// define if your C library supports the non-standard drand48 family -#undef HAVE_DRAND48 - -// define if you have the original mt19937int.c (with commented out main()) -#undef HAVE_MT19937INT_C - -// set to your CPU frequency in MHz -static const double cpu_frequency = 200 * 1e6; - -/* - * End of Configuration Section - */ - -/* - * General portability note: - * MSVC mis-compiles explicit function template instantiations. - * For example, f() and f() are both compiled to call f(). - * BCC is unable to implicitly convert a "const char *" to a std::string - * when using explicit function template instantiations. - * - * Therefore, avoid explicit function template instantiations. - */ - -// provides a run-time configurable linear congruential generator, just -// for comparison -template -class linear_congruential -{ -public: - typedef IntType result_type; -#ifndef BOOST_NO_INCLASS_MEMBER_INITIALIZATION - static const bool has_fixed_range = false; -#else - enum { has_fixed_range = false }; -#endif - linear_congruential(IntType x0, IntType a, IntType c, IntType m) - : _x(x0), _a(a), _c(c), _m(m) { } - // compiler-generated copy ctor and assignment operator are fine - void seed(IntType x0, IntType a, IntType c, IntType m) - { _x = x0; _a = a; _c = c; _m = m; } - void seed(IntType x0) { _x = x0; } - result_type operator()() { _x = (_a*_x+_c) % _m; return _x; } - result_type min() const { return _c == 0 ? 1 : 0; } - result_type max() const { return _m -1; } - -private: - IntType _x, _a, _c, _m; -}; - -void show_elapsed(double end, int iter, const std::string & name) -{ - double usec = end/iter*1e6; - double cycles = usec * cpu_frequency/1e6; - std::cout << name << ": " - << usec*1e3 << " nsec/loop = " - << cycles << " CPU cycles" - << std::endl; -} - -template -void timing(RNG & rng, int iter, const std::string& name, const Result&) -{ - volatile Result tmp; // make sure we're not optimizing too much - boost::timer t; - for(int i = 0; i < iter; i++) - tmp = rng(); - show_elapsed(t.elapsed(), iter, name); -} - -template -void timing_sphere(RNG & rng, int iter, const std::string & name) -{ - boost::timer t; - for(int i = 0; i < iter; i++) { - // the special return value convention of uniform_on_sphere saves 20% CPU - const std::vector & tmp = rng(); - (void) tmp[0]; - } - show_elapsed(t.elapsed(), iter, name); -} - -template -void run(int iter, const std::string & name, const RNG &) -{ - RNG rng; - std::cout << (RNG::has_fixed_range ? "fixed-range " : ""); - // BCC has trouble with string autoconversion for explicit specializations - timing(rng, iter, std::string(name), 0l); -} - -#ifdef HAVE_DRAND48 -// requires non-standard C library support for srand48/lrand48 -void run(int iter, const std::string & name, int) -{ - std::srand48(1); - timing(std::lrand48, iter, name, 0l); -} -#endif - -#ifdef HAVE_MT19937INT_C // requires the original mt19937int.c -extern "C" void sgenrand(unsigned long); -extern "C" unsigned long genrand(); - -void run(int iter, const std::string & name, float) -{ - sgenrand(4357); - timing(genrand, iter, name, 0u); -} -#endif - -template -void distrib(int iter, const std::string & name, const Gen &) -{ - Gen gen; - - boost::uniform_smallint usmallint(gen, -2, 4); - timing(usmallint, iter, name + " uniform_smallint", 0); - - boost::uniform_int uint(gen, -2, 4); - timing(uint, iter, name + " uniform_int", 0); - - boost::uniform_01 uni(gen); - timing(uni, iter, name + " uniform_01", 0.0); - - boost::uniform_real ur(gen, -5.3, 4.8); - timing(ur, iter, name + " uniform_real", 0.0); - - boost::geometric_distribution geo(gen, 0.5); - timing(geo, iter, name + " geometric", 0); - - boost::triangle_distribution tria(gen, 1, 2, 7); - timing(tria, iter, name + " triangle", 0.0); - - boost::exponential_distribution ex(gen, 3); - timing(ex, iter, name + " exponential", 0.0); - - boost::normal_distribution no2(gen); - timing(no2, iter, name + " normal polar", 0.0); - - boost::lognormal_distribution lnorm(gen, 1, 1); - timing(lnorm, iter, name + " lognormal", 0.0); - - boost::uniform_on_sphere usph(gen, 3); - timing_sphere(usph, iter/10, name + " uniform_on_sphere"); -} - - -int main(int argc, char*argv[]) -{ - if(argc != 2) { - std::cerr << "usage: " << argv[0] << " iterations" << std::endl; - return 1; - } - - // okay, it's ugly, but it's only used here - int iter = -#ifndef BOOST_NO_STDC_NAMESPACE - std:: -#endif - atoi(argv[1]); - -#if !defined(BOOST_NO_INT64_T) && \ - !defined(BOOST_NO_INCLASS_MEMBER_INITIALIZATION) - run(iter, "rand48", boost::rand48()); - linear_congruential - lcg48(boost::uint64_t(1)<<16 | 0x330e, - boost::uint64_t(0xDEECE66DUL) | (boost::uint64_t(0x5) << 32), 0xB, - boost::uint64_t(1)<<48); - timing(lcg48, iter, "lrand48 run-time", 0l); -#endif - -#ifdef HAVE_DRAND48 - // requires non-standard C library support for srand48/lrand48 - run(iter, "lrand48", 0); // coded for lrand48() -#endif - - run(iter, "minstd_rand", boost::minstd_rand()); - run(iter, "ecuyer combined", boost::ecuyer1988()); - run(iter, "kreutzer1986", boost::kreutzer1986()); - - run(iter, "hellekalek1995 (inversive)", boost::hellekalek1995()); - - run(iter, "mt11213b", boost::mt11213b()); - run(iter, "mt19937", boost::mt19937()); - -#ifdef HAVE_MT19937INT_C - // requires the original mt19937int.c - run(iter, "mt19937 original"); // coded for sgenrand()/genrand() -#endif - - distrib(iter, "minstd_rand", boost::minstd_rand()); - distrib(iter, "kreutzer1986", boost::kreutzer1986()); - distrib(iter, "mt19937", boost::mt19937()); -} diff --git a/random_test.cpp b/random_test.cpp deleted file mode 100644 index c286dc1..0000000 --- a/random_test.cpp +++ /dev/null @@ -1,298 +0,0 @@ -/* boost random_test.cpp various tests - * - * Copyright Jens Maurer 2000 - * Permission to use, copy, modify, sell, and distribute this software - * is hereby granted without fee provided that the above copyright notice - * appears in all copies and that both that copyright notice and this - * permission notice appear in supporting documentation, - * - * Jens Maurer makes no representations about the suitability of this - * software for any purpose. It is provided "as is" without express or - * implied warranty. - * - * $Id$ - */ - -#include -#include -#include -#include -#include -#include -#include - -#define BOOST_INCLUDE_MAIN -#include - -#ifdef BOOST_NO_STDC_NAMESPACE - namespace std { using ::fabs; } -#endif - - -/* - * General portability note: - * MSVC mis-compiles explicit function template instantiations. - * For example, f() and f() are both compiled to call f(). - * BCC is unable to implicitly convert a "const char *" to a std::string - * when using explicit function template instantiations. - * - * Therefore, avoid explicit function template instantiations. - */ - -/* - * Validate correct implementation - */ - -template -void validate(const std::string & name, const PRNG &) -{ - std::cout << "validating " << name << ": "; - PRNG rng; - for(int i = 0; i < 9999; i++) - rng(); - typename PRNG::result_type val = rng(); - // make sure the validation function is a const member - bool result = const_cast(rng).validation(val); - - // allow for a simple eyeball check for MSVC instantiation brokenness - // (if the numbers for all generators are the same, it's obviously broken) - std::cout << val << std::endl; - BOOST_TEST(result); -} - -void validate_all() -{ - using namespace boost; -#if !defined(BOOST_NO_INT64_T) && !defined(BOOST_NO_INTEGRAL_INT64_T) - validate("rand48", rand48()); -#endif - validate("minstd_rand", minstd_rand()); - validate("minstd_rand0", minstd_rand0()); - validate("ecuyer combined", ecuyer1988()); - validate("mt19937", mt19937()); - validate("kreutzer1986", kreutzer1986()); -} - - -/* - * Check function signatures - */ - -template -void instantiate_urng(const std::string & s, const URNG &, const ResultType &) -{ - std::cout << "Basic tests for " << s << std::endl; - URNG urng; - int a[URNG::has_fixed_range ? 5 : 10]; // compile-time constant - (void) a; // avoid "unused" warning - typename URNG::result_type x1 = urng(); - ResultType x2 = x1; - (void) &x2; // avoid "unused" warning - -#ifndef BOOST_MSVC // MSVC brokenness - URNG urng2 = urng; // copy constructor - BOOST_TEST(urng == urng2); // operator== - urng(); - urng2 = urng; // assignment - BOOST_TEST(urng == urng2); -#endif // BOOST_MSVC - -#ifndef BOOST_NO_OPERATORS_IN_NAMESPACE - // Streamable concept not supported for broken compilers - { - std::ofstream file("rng.tmp", std::ofstream::trunc); - file << urng; - } - // move forward - urng(); - { - // restore old state - std::ifstream file("rng.tmp"); - file >> urng; - } -#ifndef BOOST_MSVC // MSVC brokenness - BOOST_TEST(urng == urng2); -#endif // BOOST_MSVC -#endif // BOOST_NO_OPERATORS_IN_NAMESPACE - - // instantiate various distributions with this URNG - boost::uniform_smallint unismall(urng, 0, 11); - unismall(); - boost::uniform_int uni_int(urng, -200, 20000); - uni_int(); - boost::uniform_real uni_real(urng, 0, 2.1); - uni_real(); - - boost::bernoulli_distribution ber(urng, 0.2); - ber(); - boost::geometric_distribution geo(urng, 0.8); - geo(); - boost::triangle_distribution tria(urng, 1, 1.5, 7); - tria(); - boost::exponential_distribution ex(urng, 5); - ex(); - boost::normal_distribution norm(urng); - norm(); - boost::lognormal_distribution lnorm(urng, 1, 1); - lnorm(); - boost::uniform_on_sphere usph(urng, 2); - usph(); -} - -void instantiate_all() -{ - using namespace boost; - -#if !defined(BOOST_NO_INT64_T) && !defined(BOOST_NO_INTEGRAL_INT64_T) - instantiate_urng("rand48", rand48(), 0); - rand48 rnd(boost::int32_t(5)); - rand48 rnd2(boost::uint64_t(0x80000000) * 42); - rnd.seed(boost::int32_t(17)); - rnd2.seed(boost::uint64_t(0x80000000) * 49); -#endif - - instantiate_urng("minstd_rand0", minstd_rand0(), 0); - instantiate_urng("minstd_rand", minstd_rand(), 0); - minstd_rand mstd(42); - mstd.seed(17); - - instantiate_urng("ecuyer1988", ecuyer1988(), 0); - instantiate_urng("kreutzer1986", kreutzer1986(), 0); - instantiate_urng("hellekalek1995", hellekalek1995(), 0); - - instantiate_urng("mt11213b", mt11213b(), 0u); - instantiate_urng("mt19937", mt19937(), 0u); - mt19937 mt(boost::uint32_t(17)); // needs to be an exact type match for MSVC - int i = 42; - mt.seed(boost::uint32_t(i)); - mt19937 mt2(mstd); - mt2.seed(mstd); - - - random_number_generator std_rng(mt2); - (void) std_rng(10); -} - -/* - * A few equidistribution tests - */ - -// yet to come... - -template -void check_uniform_int(Generator & gen, int iter) -{ - std::cout << "testing uniform_int(" << gen.min() << "," << gen.max() - << ")" << std::endl; - int range = gen.max()-gen.min()+1; - std::vector bucket(range); - for(int j = 0; j < iter; j++) { - int result = gen(); - if(result < gen.min() || result > gen.max()) - std::cerr << " ... delivers " << result << std::endl; - else - bucket[result-gen.min()]++; - } - int sum = 0; - // use a different variable name "k", because MSVC has broken "for" scoping - for(int k = 0; k < range; k++) - sum += bucket[k]; - double avg = static_cast(sum)/range; - double threshold = 2*avg/std::sqrt(static_cast(iter)); - for(int i = 0; i < range; i++) { - if(std::fabs(bucket[i] - avg) > threshold) { - // 95% confidence interval - std::cout << " ... has bucket[" << i << "] = " << bucket[i] - << " (distance " << (bucket[i] - avg) << ")" - << std::endl; - } - } -} - -template -void test_uniform_int(Generator & gen) -{ - typedef boost::uniform_int int_gen; - - // large range => small range (modulo case) - int_gen uint12(gen,1,2); - BOOST_TEST(uint12.min() == 1); - BOOST_TEST(uint12.max() == 2); - check_uniform_int(uint12, 100000); - int_gen uint16(gen,1,6); - check_uniform_int(uint16, 100000); - - // test chaining to get all cases in operator() - typedef boost::uniform_int intint_gen; - - // identity map - intint_gen uint01(uint12, 0, 1); - check_uniform_int(uint01, 100000); - - // small range => larger range - intint_gen uint05(uint12, -3, 2); - check_uniform_int(uint05, 100000); - - typedef boost::uniform_int intintint_gen; - -#if 0 - // This takes a lot of time to run and is of questionable net effect: - // avoid for now. - - // small => larger range, not power of two - // (for unknown reasons, this has noticeably uneven distribution) - intintint_gen uint1_49(uint05, 1, 49); - check_uniform_int(uint1_49, 500000); -#endif - - // larger => small range, rejection case - intintint_gen uint1_4(uint05, 1, 4); - check_uniform_int(uint1_4, 100000); -} - -#if defined(BOOST_MSVC) && _MSC_VER <= 1200 - -// These explicit instantiations are necessary, otherwise MSVC does -// find the inline friends. -// We ease the typing with a suitable preprocessor macro. -#define INSTANT(x) \ -template class boost::uniform_smallint; \ -template class boost::uniform_int; \ -template class boost::uniform_real; \ -template class boost::bernoulli_distribution; \ -template class boost::geometric_distribution; \ -template class boost::triangle_distribution; \ -template class boost::exponential_distribution; \ -template class boost::normal_distribution; \ -template class boost::uniform_on_sphere; \ -template class boost::lognormal_distribution; - -INSTANT(boost::minstd_rand0) -INSTANT(boost::minstd_rand) -INSTANT(boost::ecuyer1988) -INSTANT(boost::kreutzer1986) -INSTANT(boost::hellekalek1995) -INSTANT(boost::mt19937) -INSTANT(boost::mt11213b) - -#endif - -int test_main(int, char*[]) -{ - instantiate_all(); - validate_all(); - boost::mt19937 mt; - test_uniform_int(mt); - - // bug report from Ken Mahler: This lead to an endless loop. - boost::minstd_rand r1; - boost::uniform_int r2(r1, 0, 0xffffffff); - r2(); - r2(); - - // bug report from Fernando Cacciola - boost::minstd_rand rnd; - boost::uniform_int x(rnd,0,8361); // --> This CTOR loops forever. - - return 0; -} diff --git a/statistic_tests.cpp b/statistic_tests.cpp deleted file mode 100644 index 99ebd77..0000000 --- a/statistic_tests.cpp +++ /dev/null @@ -1,669 +0,0 @@ -/* statistic_tests.cpp file - * - * Copyright Jens Maurer 2000, 2002 - * Permission to use, copy, modify, sell, and distribute this software - * is hereby granted without fee provided that the above copyright notice - * appears in all copies and that both that copyright notice and this - * permission notice appear in supporting documentation, - * - * Jens Maurer makes no representations about the suitability of this - * software for any purpose. It is provided "as is" without express or - * implied warranty. - * - * $Id$ - * - * Revision history - */ - -/* - * NOTE: This is not part of the official boost submission. It exists - * only as a collection of ideas. - */ - -#include -#include -#include -#include -#include // lgamma is not in namespace std -#include -#include - -#include -#include - -#include "statistic_tests.hpp" -#include "integrate.hpp" - - -namespace boost { -namespace random { - -// Wikramaratna 1989 ACORN -template -class additive_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 = 0; - static const result_type max_value = m-1; -#else - enum { - has_fixed_range = true, - min_value = 0, - max_value = m-1 - }; -#endif - template - explicit additive_congruential(InputIterator start) { seed(start); } - template - void seed(InputIterator start) - { - for(int i = 0; i <= k; ++i, ++start) - values[i] = *start; - } - - result_type operator()() - { - for(int i = 1; i <= k; ++i) { - IntType tmp = values[i-1] + values[i]; - if(tmp >= m) - tmp -= m; - values[i] = tmp; - } - return values[k]; - } - result_type validation() const { return val; } -private: - IntType values[k+1]; -}; - - -template -class lagged_fibonacci_int -{ -public: - typedef IntType result_type; -#ifndef BOOST_NO_INCLASS_MEMBER_INITIALIZATION - static const bool has_fixed_range = true; - static const result_type min_value = 0; - static const result_type max_value = m-1; -#else - enum { - has_fixed_range = true, - min_value = 0, - max_value = m-1 - }; -#endif - explicit lagged_fibonacci_int(IntType start) { seed(start); } - template - explicit lagged_fibonacci_int(Generator & gen) { seed(gen); } - void seed(IntType start) - { - linear_congruential init; - seed(init); - } - template - void seed(Generator & gen) - { - assert(r > s); - for(int i = 0; i < 607; ++i) - values[i] = gen(); - current = 0; - lag = r-s; - } - - result_type operator()() - { - result_type tmp = values[current] + values[lag]; - if(tmp >= m) - tmp -= m; - values[current] = tmp; - ++current; - if(current >= r) - current = 0; - ++lag; - if(lag >= r) - lag = 0; - return tmp; - } - result_type validation() const { return val; } -private: - result_type values[r]; - int current, lag; -}; - -} // namespace random -} // namespace boost - -// distributions from Haertel's dissertation -// (additional parameterizations of the basic templates) -namespace Haertel { - typedef boost::random::linear_congruential LCG_Af2; - typedef boost::random::linear_congruential LCG_Die1; - typedef boost::random::linear_congruential LCG_Fis; - typedef boost::random::linear_congruential LCG_FM; - typedef boost::random::linear_congruential LCG_Hae; - typedef boost::random::linear_congruential LCG_VAX; - typedef boost::random::inversive_congruential NLG_Inv1; - typedef boost::random::inversive_congruential NLG_Inv2; - typedef boost::random::inversive_congruential NLG_Inv4; - typedef boost::random::inversive_congruential NLG_Inv5; - typedef boost::random::additive_congruential MRG_Acorn7; - typedef boost::random::lagged_fibonacci_int MRG_Fib2; - - template - inline void check_validation(Gen & gen, T value, const std::string & name) - { - for(int i = 0; i < 100000-1; ++i) - gen(); - if(value != gen()) - std::cout << name << ": validation failed" << std::endl; - } - - // we have validation after 100000 steps with Haertel's generators - template - void validate(T value, const std::string & name) - { - Gen gen(1234567); - check_validation(gen, value, name); - } - - void validate_all() - { - validate(183269031u, "LCG_Af2"); - validate(522319944u, "LCG_Die1"); - validate(-2065162233u, "LCG_Fis"); - validate(581815473u, "LCG_FM"); - validate(28931709, "LCG_Hae"); - validate(1508154087u, "LCG_VAX"); - validate(6666884, "NLG_Inv2"); - validate(1521640076, "NLG_Inv4"); - validate(641840839, "NLG_Inv5"); - static const int acorn7_init[] - = { 1234567, 7654321, 246810, 108642, 13579, 97531, 555555 }; - MRG_Acorn7 acorn7(acorn7_init); - check_validation(acorn7, 874294697, "MRG_Acorn7"); - validate(1234567u, "MRG_Fib2"); - } -} // namespace Haertel - - - - -double normal_density(double x) -{ - const double pi = 3.14159265358979323846; - return 1/std::sqrt(2*pi) * std::exp(-x*x/2); -} - -namespace std { -#ifdef _CXXRTCF_H__ - using _CS_swamp::lgamma; -#elif defined __SGI_STL_PORT - using ::lgamma; -#endif -} - - -class chi_square_density : public std::unary_function -{ -public: - chi_square_density(int freedom) - : _exponent( static_cast(freedom)/2-1 ), - _factor(1/(std::pow(2, _exponent+1) * std::exp(lgamma(_exponent+1)))) - { } - - double operator()(double x) - { - return _factor*std::pow(x, _exponent)*std::exp(-x/2); - } -private: - double _exponent, _factor; -}; - -// computes F(x) or F(y) - F(x) -class chi_square_probability : public distribution_function -{ -public: - chi_square_probability(int freedom) : dens(freedom) {} - double operator()(double x) { return operator()(0, x); } - double operator()(double x, double y) - { return trapezoid(dens, x, y, 1000); } -private: - chi_square_density dens; -}; - -class uniform_distribution : public distribution_function -{ -public: - uniform_distribution(double from, double to) : from(from), to(to) - { assert(from < to); } - double operator()(double x) - { - if(x < from) - return 0; - else if(x > to) - return 1; - else - return (x-from)/(to-from); - } - double operator()(double x, double delta) - { return operator()(x+delta) - operator()(x); } -private: - double from, to; -}; - -class test_environment; - -class test_base -{ -protected: - explicit test_base(test_environment & env) : environment(env) { } - void check(double val) const; -private: - test_environment & environment; -}; - -class equidistribution_test : test_base -{ -public: - equidistribution_test(test_environment & env, unsigned int classes, - unsigned int high_classes) - : test_base(env), classes(classes), - test_distrib_chi_square(chi_square_probability(classes-1), high_classes) - { } - - template - void run(RNG & rng, int n1, int n2) - { - using namespace boost; - std::cout << "equidistribution: " << std::flush; - equidistribution_experiment equi(classes); - uniform_smallint uint_linear(rng, 0, classes-1); - check(run_experiment(test_distrib_chi_square, - experiment_generator(equi, uint_linear, n1), n2)); - check(run_experiment(test_distrib_chi_square, - experiment_generator(equi, uint_linear, n1), 2*n2)); - - std::cout << " 2D: " << std::flush; - equidistribution_2d_experiment equi_2d(classes); - unsigned int root = static_cast(std::sqrt(double(classes))); - assert(root * root == classes); - uniform_smallint uint_square(rng, 0, root-1); - check(run_experiment(test_distrib_chi_square, - experiment_generator(equi_2d, uint_square, n1), n2)); - check(run_experiment(test_distrib_chi_square, - experiment_generator(equi_2d, uint_square, n1), 2*n2)); - std::cout << std::endl; - } -private: - unsigned int classes; - distribution_experiment test_distrib_chi_square; -}; - -class ks_equidistribution_test : test_base -{ -public: - ks_equidistribution_test(test_environment & env, unsigned int classes) - : test_base(env), - test_distrib_chi_square(kolmogorov_smirnov_probability(5000), - classes) - { } - - template - void run(RNG & rng, int n1, int n2) - { - using namespace boost; - std::cout << "KS: " << std::flush; - // generator_reference_t gen_ref(rng); - RNG& gen_ref(rng); - kolmogorov_experiment ks(n1); - uniform_distribution ud(rng.min_value, rng.max_value); - check(run_experiment(test_distrib_chi_square, - ks_experiment_generator(ks, gen_ref, ud), n2)); - check(run_experiment(test_distrib_chi_square, - ks_experiment_generator(ks, gen_ref, ud), 2*n2)); - } -private: - distribution_experiment test_distrib_chi_square; -}; - -class runs_test : test_base -{ -public: - runs_test(test_environment & env, unsigned int classes, - unsigned int high_classes) - : test_base(env), classes(classes), - test_distrib_chi_square(chi_square_probability(classes-1), high_classes) - { } - - template - void run(RNG & rng, int n1, int n2) - { - using namespace boost; - std::cout << "runs: up: " << std::flush; - runs_experiment r_up(classes); - // generator_reference_t gen_ref(rng); - RNG& gen_ref(rng); - check(run_experiment(test_distrib_chi_square, - experiment_generator(r_up, gen_ref, n1), n2)); - check(run_experiment(test_distrib_chi_square, - experiment_generator(r_up, gen_ref, n1), 2*n2)); - - std::cout << " down: " << std::flush; - runs_experiment r_down(classes); - check(run_experiment(test_distrib_chi_square, - experiment_generator(r_down, gen_ref, n1), n2)); - check(run_experiment(test_distrib_chi_square, - experiment_generator(r_down, gen_ref, n1), 2*n2)); - - std::cout << std::endl; - } -private: - unsigned int classes; - distribution_experiment test_distrib_chi_square; -}; - -class gap_test : test_base -{ -public: - gap_test(test_environment & env, unsigned int classes, - unsigned int high_classes) - : test_base(env), classes(classes), - test_distrib_chi_square(chi_square_probability(classes-1), high_classes) - { } - - template - void run(RNG & rng, int n1, int n2) - { - using namespace boost; - std::cout << "gaps: " << std::flush; - gap_experiment gap(classes, 0.2, 0.8); - // generator_reference_t gen_ref(rng); - RNG& gen_ref(rng); - check(run_experiment(test_distrib_chi_square, - experiment_generator(gap, gen_ref, n1), n2)); - check(run_experiment(test_distrib_chi_square, - experiment_generator(gap, gen_ref, n1), 2*n2)); - - std::cout << std::endl; - } -private: - unsigned int classes; - distribution_experiment test_distrib_chi_square; -}; - -class poker_test : test_base -{ -public: - poker_test(test_environment & env, unsigned int classes, - unsigned int high_classes) - : test_base(env), classes(classes), - test_distrib_chi_square(chi_square_probability(classes-1), high_classes) - { } - - template - void run(RNG & rng, int n1, int n2) - { - using namespace boost; - std::cout << "poker: " << std::flush; - poker_experiment poker(8, classes); - uniform_smallint usmall(rng, 0, 7); - check(run_experiment(test_distrib_chi_square, - experiment_generator(poker, usmall, n1), n2)); - check(run_experiment(test_distrib_chi_square, - experiment_generator(poker, usmall, n1), 2*n2)); - std::cout << std::endl; - } -private: - unsigned int classes; - distribution_experiment test_distrib_chi_square; -}; - -class coupon_collector_test : test_base -{ -public: - coupon_collector_test(test_environment & env, unsigned int classes, - unsigned int high_classes) - : test_base(env), classes(classes), - test_distrib_chi_square(chi_square_probability(classes-1), high_classes) - { } - - template - void run(RNG & rng, int n1, int n2) - { - using namespace boost; - std::cout << "coupon collector: " << std::flush; - coupon_collector_experiment coupon(5, classes); - - uniform_smallint usmall(rng, 0, 4); - check(run_experiment(test_distrib_chi_square, - experiment_generator(coupon, usmall, n1), n2)); - check(run_experiment(test_distrib_chi_square, - experiment_generator(coupon, usmall, n1), 2*n2)); - std::cout << std::endl; - } -private: - unsigned int classes; - distribution_experiment test_distrib_chi_square; -}; - -class permutation_test : test_base -{ -public: - permutation_test(test_environment & env, unsigned int classes, - unsigned int high_classes) - : test_base(env), classes(classes), - test_distrib_chi_square(chi_square_probability(fac(classes)-1), - high_classes) - { } - - template - void run(RNG & rng, int n1, int n2) - { - using namespace boost; - std::cout << "permutation: " << std::flush; - permutation_experiment perm(classes); - - // generator_reference_t gen_ref(rng); - RNG& gen_ref(rng); - check(run_experiment(test_distrib_chi_square, - experiment_generator(perm, gen_ref, n1), n2)); - check(run_experiment(test_distrib_chi_square, - experiment_generator(perm, gen_ref, n1), 2*n2)); - std::cout << std::endl; - } -private: - unsigned int classes; - distribution_experiment test_distrib_chi_square; -}; - -class maximum_test : test_base -{ -public: - maximum_test(test_environment & env, unsigned int high_classes) - : test_base(env), - test_distrib_chi_square(kolmogorov_smirnov_probability(1000), - high_classes) - { } - - template - void run(RNG & rng, int n1, int n2) - { - using namespace boost; - std::cout << "maximum-of-t: " << std::flush; - maximum_experiment mx(rng, n1, 5); - check(run_experiment(test_distrib_chi_square, mx, n2)); - check(run_experiment(test_distrib_chi_square, mx, 2*n2)); - std::cout << std::endl; - } -private: - distribution_experiment test_distrib_chi_square; -}; - -class birthday_test : test_base -{ -public: - birthday_test(test_environment & env) - : test_base(env) - { } - - template - void run(RNG & rng, int n1, int n2) - { - using namespace boost; - std::cout << "birthday spacing: " << std::flush; - uniform_int uni(rng, 0, (1<<25)); - birthday_spacing_experiment bsp(4, 512, (1<<25)); - std::cout << run_experiment(bsp, uni, n1); -#if 0 - check(run_experiment(test_distrib_chi_square, - experiment_generator(perm, gen_ref, n1), n2)); - check(run_experiment(test_distrib_chi_square, - experiment_generator(perm, gen_ref, n1), 2*n2)); -#endif - std::cout << std::endl; - } - - -}; - -class test_environment -{ -public: - static const int classes = 20; - explicit test_environment(double confid) - : confidence(confid), - confidence_chi_square_quantil(quantil(chi_square_density(classes-1), 0, confidence, 1e-4)), - test_distrib_chi_square6(chi_square_probability(7-1), classes), - ksequi_test(*this, classes), - equi_test(*this, 100, classes), - rns_test(*this, 7, classes), - gp_test(*this, 7, classes), - pk_test(*this, 5, classes), - cpn_test(*this, 15, classes), - perm_test(*this, 5, classes), - max_test(*this, classes), - bday_test(*this) - { - std::cout << "Confidence level: " << confid - << "; 1-alpha = " << (1-confid) - << "; chi_square(" << (classes-1) - << ", " << confidence_chi_square_quantil - << ") = " - << chi_square_probability(classes-1)(0, confidence_chi_square_quantil) - << std::endl; - } - - bool check_confidence(double val, double chi_square_conf) const - { - std::cout << val; - bool result = (val <= chi_square_conf); - if(!result) { - std::cout << "* ["; - double prob = (val > 10*chi_square_conf ? 1 : - chi_square_probability(classes-1)(0, val)); - std::cout << (1-prob) << "]"; - } - std::cout << " " << std::flush; - return result; - } - - bool check(double chi_square_value) const - { - return check_confidence(chi_square_value, confidence_chi_square_quantil); - } - - template - void run_test(const std::string & name) - { - using namespace boost; - - std::cout << "Running tests on " << name << std::endl; - - RNG rng(1234567); - typedef boost::uniform_01 UGen; - -#if 1 - ksequi_test.run(rng, 5000, 250); - equi_test.run(rng, 5000, 250); - rns_test.run(rng, 100000, 250); - gp_test.run(rng, 10000, 250); - pk_test.run(rng, 5000, 250); - cpn_test.run(rng, 500, 250); - perm_test.run(rng, 1200, 250); - max_test.run(rng, 1000, 250); -#endif - bday_test.run(rng, 1000, 150); - - std::cout << std::endl; - } - -private: - double confidence; - double confidence_chi_square_quantil; - distribution_experiment test_distrib_chi_square6; - ks_equidistribution_test ksequi_test; - equidistribution_test equi_test; - runs_test rns_test; - gap_test gp_test; - poker_test pk_test; - coupon_collector_test cpn_test; - permutation_test perm_test; - maximum_test max_test; - birthday_test bday_test; -}; - -void test_base::check(double val) const -{ - environment.check(val); -} - -void print_ks_table() -{ - std::cout.setf(std::ios::fixed); - std::cout.precision(5); - static const double all_p[] = { 0.01, 0.05, 0.25, 0.5, 0.75, 0.95, 0.99 }; - for(int n = 0; n <= 10000; (n < 55 ? ++n : n *= 10)) { - std::cout << std::setw(4) << n << " "; - for(unsigned int i = 0; i < sizeof(all_p)/sizeof(all_p[0]); ++i) { - std::cout << std::setw(8) - << (n == 0 ? all_p[i] : - invert_monotone_inc(kolmogorov_smirnov_probability(n), all_p[i], 0, 10)) - << " "; - } - std::cout << std::endl; - } -} - -int main() -{ - // Haertel::validate_all(); - test_environment env(0.99); - env.run_test("minstd_rand"); - env.run_test("mt19937"); - env.run_test("LCG_Af2"); - env.run_test("LCG_Die1"); - env.run_test("LCG_Fis"); - env.run_test("LCG_FM"); - env.run_test("LCG_Hae"); - env.run_test("LCG_VAX"); - env.run_test("NLG_Inv1"); - env.run_test("NLG_Inv2"); - env.run_test("NLG_Inv4"); - env.run_test("NLG_Inv5"); -} diff --git a/statistic_tests.hpp b/statistic_tests.hpp deleted file mode 100644 index ec3c04f..0000000 --- a/statistic_tests.hpp +++ /dev/null @@ -1,641 +0,0 @@ -/* statistic_tests.hpp header file - * - * Copyright Jens Maurer 2000 - * Permission to use, copy, modify, sell, and distribute this software - * is hereby granted without fee provided that the above copyright notice - * appears in all copies and that both that copyright notice and this - * permission notice appear in supporting documentation, - * - * Jens Maurer makes no representations about the suitability of this - * software for any purpose. It is provided "as is" without express or - * implied warranty. - * - * $Id$ - * - */ - -#ifndef STATISTIC_TESTS_HPP -#define STATISTIC_TESTS_HPP - -#include -#include -#include -#include -#include -#include - -#include -#include - - -#ifdef BOOST_MSVC -namespace std -{ - inline double pow(double a, double b) { return ::pow(a,b); } - inline double ceil(double x) { return ::ceil(x); } -} // namespace std -#endif - - -template -inline T fac(int k) -{ - T result = 1; - for(T i = 2; i <= k; ++i) - result *= i; - return result; -} - -template -T binomial(int n, int k) -{ - if(k < n/2) - k = n-k; - T result = 1; - for(int i = k+1; i<= n; ++i) - result *= i; - return result / fac(n-k); -} - -template -T stirling2(int n, int m) -{ - T sum = 0; - for(int k = 0; k <= m; ++k) - sum += binomial(m, k) * std::pow(double(k), n) * - ( (m-k)%2 == 0 ? 1 : -1); - return sum / fac(m); -} - -/* - * Experiments which create an empirical distribution in classes, - * suitable for the chi-square test. - */ -// std::floor(gen() * classes) - -class experiment_base -{ -public: - experiment_base(int cls) : _classes(cls) { } - unsigned int classes() const { return _classes; } -protected: - unsigned int _classes; -}; - -class equidistribution_experiment : public experiment_base -{ -public: - explicit equidistribution_experiment(unsigned int classes) - : experiment_base(classes) { } - - template - void run(NumberGenerator f, Counter & count, int n) const - { - assert(f.min() == 0 && - static_cast(f.max()) == classes()-1); - for(int i = 0; i < n; ++i) - count(f()); - } - double probability(int i) const { return 1.0/classes(); } -}; - -// two-dimensional equidistribution experiment -class equidistribution_2d_experiment : public equidistribution_experiment -{ -public: - explicit equidistribution_2d_experiment(unsigned int classes) - : equidistribution_experiment(classes) { } - - template - void run(NumberGenerator f, Counter & count, int n) const - { - unsigned int range = f.max()+1; - assert(f.min() == 0 && range*range == classes()); - for(int i = 0; i < n; ++i) { - int y1 = f(); - int y2 = f(); - count(y1 + range * y2); - } - } -}; - -// distribution experiment: assume a probability density and -// count events so that an equidistribution results. -class distribution_experiment : public equidistribution_experiment -{ -public: - template - distribution_experiment(UnaryFunction probability , unsigned int classes) - : equidistribution_experiment(classes), limit(classes) - { - for(unsigned int i = 0; i < classes-1; ++i) - limit[i] = invert_monotone_inc(probability, (i+1)*0.05, 0, 1000); - limit[classes-1] = std::numeric_limits::infinity(); -#if 0 - std::cout << __PRETTY_FUNCTION__ << ": "; - for(unsigned int i = 0; i < classes; ++i) - std::cout << limit[i] << " "; - std::cout << std::endl; -#endif - } - - template - void run(NumberGenerator f, Counter & count, int n) const - { - for(int i = 0; i < n; ++i) { - limits_type::const_iterator it = - std::lower_bound(limit.begin(), limit.end(), f()); - count(it-limit.begin()); - } - } -private: - typedef std::vector limits_type; - limits_type limit; -}; - -// runs-up/runs-down experiment -template -class runs_experiment : public experiment_base -{ -public: - explicit runs_experiment(unsigned int classes) : experiment_base(classes) { } - - template - void run(UniformRandomNumberGenerator f, Counter & count, int n) const - { - typedef typename UniformRandomNumberGenerator::result_type result_type; - result_type init = (up ? f.min() : f.max()); - result_type previous = init; - unsigned int length = 0; - for(int i = 0; i < n; ++i) { - result_type val = f(); - if(up ? previous <= val : previous >= val) { - previous = val; - ++length; - } else { - count(std::min(length, classes())-1); - length = 0; - previous = init; - // don't use this value, so that runs are independent - } - } - } - double probability(unsigned int r) const - { - if(r == classes()-1) - return 1.0/fac(classes()); - else - return static_cast(r+1)/fac(r+2); - } -}; - -// gap length experiment -class gap_experiment : public experiment_base -{ -public: - gap_experiment(unsigned int classes, double alpha, double beta) - : experiment_base(classes), alpha(alpha), beta(beta) { } - - template - void run(UniformRandomNumberGenerator f, Counter & count, int n) const - { - typedef typename UniformRandomNumberGenerator::result_type result_type; - double range = f.max() - f.min() + 1.0; - result_type low = static_cast(alpha * range); - result_type high = static_cast(beta * range); - unsigned int length = 0; - for(int i = 0; i < n; ) { - result_type value = f() - f.min(); - if(value < low || value > high) - ++length; - else { - count(std::min(length, classes()-1)); - length = 0; - ++i; - } - } - } - double probability(unsigned int r) const - { - double p = beta-alpha; - if(r == classes()-1) - return std::pow(1-p, static_cast(r)); - else - return p * std::pow(1-p, static_cast(r)); - } -private: - double alpha, beta; -}; - -// poker experiment -class poker_experiment : public experiment_base -{ -public: - poker_experiment(unsigned int d, unsigned int k) - : experiment_base(k), range(d) - { - assert(range > 1); - } - - template - void run(UniformRandomNumberGenerator f, Counter & count, int n) const - { - typedef typename UniformRandomNumberGenerator::result_type result_type; - assert(std::numeric_limits::is_integer); - assert(f.min() == 0); - assert(f.max() == static_cast(range-1)); - std::vector v(classes()); - for(int i = 0; i < n; ++i) { - for(unsigned int j = 0; j < classes(); ++j) - v[j] = f(); - std::sort(v.begin(), v.end()); - result_type prev = v[0]; - int r = 1; // count different values in v - for(unsigned int i = 1; i < classes(); ++i) { - if(prev != v[i]) { - prev = v[i]; - ++r; - } - } - count(r-1); - } - } - - double probability(unsigned int r) const - { - ++r; // transform to 1 <= r <= 5 - double result = range; - for(unsigned int i = 1; i < r; ++i) - result *= range-i; - return result / std::pow(range, static_cast(classes())) * - stirling2(classes(), r); - } -private: - unsigned int range; -}; - -// coupon collector experiment -class coupon_collector_experiment : public experiment_base -{ -public: - coupon_collector_experiment(unsigned int d, unsigned int cls) - : experiment_base(cls), d(d) - { - assert(d > 1); - } - - template - void run(UniformRandomNumberGenerator f, Counter & count, int n) const - { - typedef typename UniformRandomNumberGenerator::result_type result_type; - assert(std::numeric_limits::is_integer); - assert(f.min() == 0); - assert(f.max() == static_cast(d-1)); - std::vector occurs(d); - for(int i = 0; i < n; ++i) { - occurs.assign(d, false); - unsigned int r = 0; // length of current sequence - int q = 0; // number of non-duplicates in current set - for(;;) { - result_type val = f(); - ++r; - if(!occurs[val]) { // new set element - occurs[val] = true; - ++q; - if(q == d) - break; // one complete set - } - } - count(std::min(r-d, classes()-1)); - } - } - double probability(unsigned int r) const - { - if(r == classes()-1) - return 1-fac(d)/std::pow(d, static_cast(d+classes()-2))* - stirling2(d+classes()-2, d); - else - return fac(d)/std::pow(d, static_cast(d+r)) * - stirling2(d+r-1, d-1); - } -private: - int d; -}; - -// permutation test -class permutation_experiment : public equidistribution_experiment -{ -public: - permutation_experiment(unsigned int t) - : equidistribution_experiment(fac(t)), t(t) - { - assert(t > 1); - } - - template - void run(UniformRandomNumberGenerator f, Counter & count, int n) const - { - typedef typename UniformRandomNumberGenerator::result_type result_type; - std::vector v(t); - for(int i = 0; i < n; ++i) { - std::generate_n(v.begin(), t, f); - int x = 0; - for(int r = t-1; r > 0; r--) { - std::vector::iterator it = - std::max_element(v.begin(), v.begin()+r+1); - x = (r+1)*x + (it-v.begin()); - std::iter_swap(it, v.begin()+r); - } - count(x); - } - } -private: - int t; -}; - -// birthday spacing experiment test -class birthday_spacing_experiment : public experiment_base -{ -public: - birthday_spacing_experiment(unsigned int d, int n, int m) - : experiment_base(d), n(n), m(m) - { - } - - template - void run(UniformRandomNumberGenerator f, Counter & count, int n_total) const - { - typedef typename UniformRandomNumberGenerator::result_type result_type; - assert(std::numeric_limits::is_integer); - assert(f.min() == 0); - assert(f.max() == static_cast(m-1)); - - for(int j = 0; j < n_total; j++) { - std::vector v(n); - std::generate_n(v.begin(), n, f); - std::sort(v.begin(), v.end()); - std::vector spacing(n); - for(int i = 0; i < n-1; i++) - spacing[i] = v[i+1]-v[i]; - spacing[n-1] = v[0] + m - v[n-1]; - std::sort(spacing.begin(), spacing.end()); - unsigned int k = 0; - for(int i = 0; i < n-1; ++i) { - if(spacing[i] == spacing[i+1]) - ++k; - } - count(std::min(k, classes()-1)); - } - } - - double probability(unsigned int r) const - { - assert(classes() == 4); - assert(m == (1<<25)); - assert(n == 512); - static const double prob[] = { 0.368801577, 0.369035243, 0.183471182, - 0.078691997 }; - return prob[r]; - } -private: - int n, m; -}; -/* - * Misc. helper functions. - */ - -template -struct distribution_function -{ - typedef Float result_type; - typedef Float argument_type; - typedef Float first_argument_type; - typedef Float second_argument_type; -}; - -// computes P(K_n <= t) or P(t1 <= K_n <= t2). See Knuth, 3.3.1 -class kolmogorov_smirnov_probability : public distribution_function -{ -public: - kolmogorov_smirnov_probability(int n) - : approx(n > 50), n(n), sqrt_n(std::sqrt(double(n))) - { - if(!approx) - n_n = std::pow(static_cast(n), n); - } - - double operator()(double t) const - { - if(approx) { - return 1-std::exp(-2*t*t)*(1-2.0/3.0*t/sqrt_n); - } else { - t *= sqrt_n; - double sum = 0; - for(int k = static_cast(std::ceil(t)); k <= n; k++) - sum += binomial(n, k) * std::pow(k-t, k) * - std::pow(t+n-k, n-k-1); - return 1 - t/n_n * sum; - } - } - double operator()(double t1, double t2) const - { return operator()(t2) - operator()(t1); } - -private: - bool approx; - int n; - double sqrt_n; - double n_n; -}; - -/* - * Experiments for generators with continuous distribution functions - */ -class kolmogorov_experiment -{ -public: - kolmogorov_experiment(int n) : n(n), ksp(n) { } - template - double run(NumberGenerator gen, Distribution distrib) const - { - const int m = n; - typedef std::vector saved_temp; - saved_temp a(m,1.0), b(m,0); - std::vector c(m,0); - for(int i = 0; i < n; ++i) { - double val = gen(); - double y = distrib(val); - int k = static_cast(std::floor(m*y)); - if(k >= m) - --k; // should not happen - a[k] = std::min(a[k], y); - b[k] = std::max(b[k], y); - ++c[k]; - } - double kplus = 0, kminus = 0; - int j = 0; - for(int k = 0; k < m; ++k) { - if(c[k] > 0) { - kminus = std::max(kminus, a[k]-j/static_cast(n)); - j += c[k]; - kplus = std::max(kplus, j/static_cast(n) - b[k]); - } - } - kplus *= std::sqrt(double(n)); - kminus *= std::sqrt(double(n)); - // std::cout << "k+ " << kplus << " k- " << kminus << std::endl; - return kplus; - } - double probability(double x) const - { - return ksp(x); - } -private: - int n; - kolmogorov_smirnov_probability ksp; -}; - -// maximum-of-t test (KS-based) -template -class maximum_experiment -{ -public: - typedef UniformRandomNumberGenerator base_type; - maximum_experiment(base_type & f, int n, int t) : f(f), ke(n), t(t) - { } - - double operator()() const - { - double res = ke.run(generator(f, t), - std::bind2nd(std::ptr_fun(static_cast(&std::pow)), t)); - return res; - } - -private: - struct generator { - generator(base_type & f, int t) : f(f), t(t) { } - double operator()() - { - double mx = f(); - for(int i = 1; i < t; ++i) - mx = std::max(mx, f()); - return mx; - } - private: - boost::uniform_01 f; - int t; - }; - base_type & f; - kolmogorov_experiment ke; - int t; -}; - -// compute a chi-square value for the distribution approximation error -template -typename UnaryFunction::result_type -chi_square_value(ForwardIterator first, ForwardIterator last, - UnaryFunction probability) -{ - typedef std::iterator_traits iter_traits; - typedef typename iter_traits::value_type counter_type; - typedef typename UnaryFunction::result_type result_type; - unsigned int classes = std::distance(first, last); - result_type sum = 0; - counter_type n = 0; - for(unsigned int i = 0; i < classes; ++first, ++i) { - counter_type count = *first; - n += count; - sum += (count/probability(i)) * count; // avoid overflow - } -#if 0 - for(unsigned int i = 0; i < classes; ++i) { - // std::cout << (n*probability(i)) << " "; - if(n * probability(i) < 5) - std::cerr << "Not enough test runs for slot " << i - << " p=" << probability(i) << ", n=" << n - << std::endl; - } -#endif - // std::cout << std::endl; - // throw std::invalid_argument("not enough test runs"); - - return sum/n - n; -} -template -class generic_counter -{ -public: - explicit generic_counter(unsigned int classes) : container(classes, 0) { } - void operator()(int i) - { - assert(i >= 0); - assert(static_cast(i) < container.size()); - ++container[i]; - } - typename RandomAccessContainer::const_iterator begin() const - { return container.begin(); } - typename RandomAccessContainer::const_iterator end() const - { return container.end(); } - -private: - RandomAccessContainer container; -}; - -// chi_square test -template -double run_experiment(const Experiment & experiment, Generator gen, int n) -{ - generic_counter > v(experiment.classes()); - experiment.run(gen, v, n); - return chi_square_value(v.begin(), v.end(), - std::bind1st(std::mem_fun_ref(&Experiment::probability), - experiment)); -} - -// number generator with experiment results (for nesting) -template -class experiment_generator_t -{ -public: - experiment_generator_t(const Experiment & exper, Generator & gen, int n) - : experiment(exper), generator(gen), n(n) { } - double operator()() { return run_experiment(experiment, generator, n); } -private: - const Experiment & experiment; - Generator & generator; - int n; -}; - -template -experiment_generator_t -experiment_generator(const Experiment & e, Generator & gen, int n) -{ - return experiment_generator_t(e, gen, n); -} - - -template -class ks_experiment_generator_t -{ -public: - ks_experiment_generator_t(const Experiment & exper, Generator & gen, - const Distribution & distrib) - : experiment(exper), generator(gen), distribution(distrib) { } - double operator()() { return experiment.run(generator, distribution); } -private: - const Experiment & experiment; - Generator & generator; - Distribution distribution; -}; - -template -ks_experiment_generator_t -ks_experiment_generator(const Experiment & e, Generator & gen, - const Distribution & distrib) -{ - return ks_experiment_generator_t - (e, gen, distrib); -} - - -#endif /* STATISTIC_TESTS_HPP */ -