|
Boost-Commit : |
Subject: [Boost-commit] svn:boost r60755 - in branches/release: . boost boost/algorithm/string boost/archive boost/bimap boost/config boost/detail boost/filesystem boost/functional/hash boost/fusion boost/graph boost/integer boost/interprocess boost/intrusive boost/math boost/numeric/ublas boost/program_options boost/property_tree boost/python boost/random boost/random/detail boost/regex boost/serialization boost/signals boost/signals2 boost/spirit boost/spirit/home boost/spirit/home/karma boost/spirit/home/support boost/statechart boost/system boost/thread boost/tr1 boost/type_traits boost/utility boost/uuid boost/variant boost/wave doc doc/html doc/src libs libs/array/doc libs/bimap libs/config libs/filesystem libs/functional/hash libs/fusion libs/graph_parallel libs/integer libs/interprocess libs/intrusive libs/math libs/mpl/doc/refmanual libs/mpl/doc/src/refmanual libs/numeric/ublas libs/numeric/ublas/doc libs/program_options libs/property_tree libs/python libs/random libs/random/build libs/random/doc libs/random/example libs/random/extra libs/random/performance libs/random/src libs/random/test libs/regex libs/regex/doc libs/serialization libs/signals libs/signals2 libs/spirit libs/spirit/classic/example libs/spirit/doc libs/spirit/example libs/spirit/phoenix libs/spirit/test libs/spirit/test/qi libs/statechart libs/static_assert libs/system libs/thread libs/thread/doc libs/timer libs/tr1 libs/type_traits libs/utility libs/uuid libs/wave more people status tools tools/bcp tools/boostbook tools/build/v2 tools/inspect tools/regression tools/release tools/wave wiki
From: steven_at_[hidden]
Date: 2010-03-21 20:45:13
Author: steven_watanabe
Date: 2010-03-21 20:45:06 EDT (Sun, 21 Mar 2010)
New Revision: 60755
URL: http://svn.boost.org/trac/boost/changeset/60755
Log:
Merge Random from the trunk
Added:
branches/release/boost/random/detail/auto_link.hpp
- copied, changed from r60199, /trunk/boost/random/detail/auto_link.hpp
branches/release/doc/html/boost_random.html
- copied unchanged from r60172, /trunk/doc/html/boost_random.html
branches/release/libs/random/build/
- copied from r60199, /trunk/libs/random/build/
branches/release/libs/random/build/Jamfile.v2
- copied unchanged from r60199, /trunk/libs/random/build/Jamfile.v2
branches/release/libs/random/doc/
- copied from r59910, /trunk/libs/random/doc/
branches/release/libs/random/doc/Jamfile.v2
- copied, changed from r59910, /trunk/libs/random/doc/Jamfile.v2
branches/release/libs/random/doc/concepts.qbk
- copied, changed from r59910, /trunk/libs/random/doc/concepts.qbk
branches/release/libs/random/doc/distribution_performance_linux.qbk
- copied, changed from r59910, /trunk/libs/random/doc/distribution_performance_linux.qbk
branches/release/libs/random/doc/distribution_performance_windows.qbk
- copied, changed from r59910, /trunk/libs/random/doc/distribution_performance_windows.qbk
branches/release/libs/random/doc/distributions.qbk
- copied, changed from r59910, /trunk/libs/random/doc/distributions.qbk
branches/release/libs/random/doc/generator_defs.qbk
- copied, changed from r59910, /trunk/libs/random/doc/generator_defs.qbk
branches/release/libs/random/doc/generator_performance_linux.qbk
- copied, changed from r59910, /trunk/libs/random/doc/generator_performance_linux.qbk
branches/release/libs/random/doc/generator_performance_windows.qbk
- copied, changed from r59910, /trunk/libs/random/doc/generator_performance_windows.qbk
branches/release/libs/random/doc/generators.qbk
- copied, changed from r59910, /trunk/libs/random/doc/generators.qbk
branches/release/libs/random/doc/nondet_random.qbk
- copied, changed from r59910, /trunk/libs/random/doc/nondet_random.qbk
branches/release/libs/random/doc/performance.qbk
- copied, changed from r59910, /trunk/libs/random/doc/performance.qbk
branches/release/libs/random/doc/performance_data.qbk
- copied, changed from r59910, /trunk/libs/random/doc/performance_data.qbk
branches/release/libs/random/doc/random.qbk
- copied, changed from r59910, /trunk/libs/random/doc/random.qbk
branches/release/libs/random/doc/random_number_generator.qbk
- copied, changed from r59910, /trunk/libs/random/doc/random_number_generator.qbk
branches/release/libs/random/doc/tutorial.qbk
- copied, changed from r59910, /trunk/libs/random/doc/tutorial.qbk
branches/release/libs/random/example/
- copied from r59910, /trunk/libs/random/example/
branches/release/libs/random/example/Jamfile.v2
- copied unchanged from r59910, /trunk/libs/random/example/Jamfile.v2
branches/release/libs/random/example/die.cpp
- copied, changed from r59910, /trunk/libs/random/example/die.cpp
branches/release/libs/random/example/random_demo.cpp
- copied unchanged from r60199, /trunk/libs/random/example/random_demo.cpp
branches/release/libs/random/example/weighted_die.cpp
- copied, changed from r59910, /trunk/libs/random/example/weighted_die.cpp
branches/release/libs/random/extra/
- copied from r60279, /trunk/libs/random/extra/
branches/release/libs/random/extra/Jamfile.v2
- copied unchanged from r60279, /trunk/libs/random/extra/Jamfile.v2
branches/release/libs/random/extra/haertel.hpp
- copied unchanged from r60279, /trunk/libs/random/extra/haertel.hpp
branches/release/libs/random/extra/test_haertel.cpp
- copied unchanged from r60279, /trunk/libs/random/extra/test_haertel.cpp
branches/release/libs/random/index.html
- copied unchanged from r60172, /trunk/libs/random/index.html
branches/release/libs/random/nondet_random.html
- copied unchanged from r60526, /trunk/libs/random/nondet_random.html
branches/release/libs/random/performance/
- copied from r60199, /trunk/libs/random/performance/
branches/release/libs/random/performance/generate_table.cpp
- copied unchanged from r60199, /trunk/libs/random/performance/generate_table.cpp
branches/release/libs/random/performance/nondet_random_speed.cpp
- copied unchanged from r60199, /trunk/libs/random/performance/nondet_random_speed.cpp
branches/release/libs/random/performance/random_speed.cpp
- copied unchanged from r60199, /trunk/libs/random/performance/random_speed.cpp
branches/release/libs/random/random-concepts.html
- copied unchanged from r60526, /trunk/libs/random/random-concepts.html
branches/release/libs/random/random-distributions.html
- copied unchanged from r60526, /trunk/libs/random/random-distributions.html
branches/release/libs/random/random-generators.html
- copied unchanged from r60526, /trunk/libs/random/random-generators.html
branches/release/libs/random/random-misc.html
- copied unchanged from r60526, /trunk/libs/random/random-misc.html
branches/release/libs/random/random-performance.html
- copied unchanged from r60526, /trunk/libs/random/random-performance.html
branches/release/libs/random/random-variate.html
- copied unchanged from r60526, /trunk/libs/random/random-variate.html
branches/release/libs/random/src/
- copied from r60199, /trunk/libs/random/src/
branches/release/libs/random/src/random_device.cpp
- copied, changed from r60199, /trunk/libs/random/src/random_device.cpp
branches/release/libs/random/test/histogram.cpp
- copied unchanged from r60199, /trunk/libs/random/test/histogram.cpp
branches/release/libs/random/test/instantiate.cpp
- copied, changed from r60199, /trunk/libs/random/test/instantiate.cpp
branches/release/libs/random/test/integrate.hpp
- copied, changed from r60199, /trunk/libs/random/test/integrate.hpp
branches/release/libs/random/test/random_test.cpp
- copied, changed from r60199, /trunk/libs/random/test/random_test.cpp
branches/release/libs/random/test/statistic_tests.cpp
- copied, changed from r60199, /trunk/libs/random/test/statistic_tests.cpp
branches/release/libs/random/test/statistic_tests.hpp
- copied, changed from r60199, /trunk/libs/random/test/statistic_tests.hpp
branches/release/libs/random/test/validate.cpp
- copied, changed from r60199, /trunk/libs/random/test/validate.cpp
Removed:
branches/release/libs/random/histogram.cpp
branches/release/libs/random/instantiate.cpp
branches/release/libs/random/integrate.hpp
branches/release/libs/random/nondet_random_speed.cpp
branches/release/libs/random/random_demo.cpp
branches/release/libs/random/random_device.cpp
branches/release/libs/random/random_speed.cpp
branches/release/libs/random/random_test.cpp
branches/release/libs/random/statistic_tests.cpp
branches/release/libs/random/statistic_tests.hpp
branches/release/libs/random/validate.cpp
branches/release/libs/random/wg21-proposal.html
Properties modified:
branches/release/ (props changed)
branches/release/CMakeLists.txt (props changed)
branches/release/INSTALL (props changed)
branches/release/Jamroot (props changed)
branches/release/LICENSE_1_0.txt (props changed)
branches/release/boost/ (props changed)
branches/release/boost-build.jam (props changed)
branches/release/boost.css (props changed)
branches/release/boost.png (props changed)
branches/release/boost/algorithm/string/ (props changed)
branches/release/boost/archive/ (props changed)
branches/release/boost/array.hpp (props changed)
branches/release/boost/bimap/ (props changed)
branches/release/boost/config/ (props changed)
branches/release/boost/detail/ (props changed)
branches/release/boost/filesystem/ (props changed)
branches/release/boost/functional/hash/ (props changed)
branches/release/boost/fusion/ (props changed)
branches/release/boost/graph/ (props changed)
branches/release/boost/integer/ (props changed)
branches/release/boost/interprocess/ (props changed)
branches/release/boost/intrusive/ (props changed)
branches/release/boost/math/ (props changed)
branches/release/boost/numeric/ublas/ (props changed)
branches/release/boost/program_options/ (props changed)
branches/release/boost/property_tree/ (props changed)
branches/release/boost/python/ (props changed)
branches/release/boost/regex/ (props changed)
branches/release/boost/serialization/ (props changed)
branches/release/boost/signals/ (props changed)
branches/release/boost/signals2/ (props changed)
branches/release/boost/spirit/ (props changed)
branches/release/boost/spirit/home/ (props changed)
branches/release/boost/spirit/home/karma/ (props changed)
branches/release/boost/spirit/home/support/attributes.hpp (props changed)
branches/release/boost/statechart/ (props changed)
branches/release/boost/system/ (props changed)
branches/release/boost/thread/ (props changed)
branches/release/boost/thread.hpp (props changed)
branches/release/boost/tr1/ (props changed)
branches/release/boost/type_traits/ (props changed)
branches/release/boost/utility/ (props changed)
branches/release/boost/utility/value_init.hpp (props changed)
branches/release/boost/uuid/ (props changed)
branches/release/boost/variant/ (props changed)
branches/release/boost/version.hpp (props changed)
branches/release/boost/wave/ (props changed)
branches/release/bootstrap.bat (props changed)
branches/release/bootstrap.sh (props changed)
branches/release/doc/ (props changed)
branches/release/index.htm (props changed)
branches/release/index.html (props changed)
branches/release/libs/ (props changed)
branches/release/libs/array/doc/array.xml (props changed)
branches/release/libs/bimap/ (props changed)
branches/release/libs/config/ (props changed)
branches/release/libs/filesystem/ (props changed)
branches/release/libs/functional/hash/ (props changed)
branches/release/libs/fusion/ (props changed)
branches/release/libs/graph_parallel/ (props changed)
branches/release/libs/integer/ (props changed)
branches/release/libs/interprocess/ (props changed)
branches/release/libs/intrusive/ (props changed)
branches/release/libs/libraries.htm (props changed)
branches/release/libs/maintainers.txt (props changed)
branches/release/libs/math/ (props changed)
branches/release/libs/mpl/doc/refmanual/broken-compiler-workarounds.html (props changed)
branches/release/libs/mpl/doc/refmanual/categorized-index-concepts.html (props changed)
branches/release/libs/mpl/doc/refmanual/cfg-no-preprocessed-headers.html (props changed)
branches/release/libs/mpl/doc/refmanual/composition-and-argument-binding.html (props changed)
branches/release/libs/mpl/doc/refmanual/data-types-concepts.html (props changed)
branches/release/libs/mpl/doc/refmanual/data-types-miscellaneous.html (props changed)
branches/release/libs/mpl/doc/refmanual/extensible-associative-sequence.html (props changed)
branches/release/libs/mpl/doc/refmanual/inserter-class.html (props changed)
branches/release/libs/mpl/doc/refmanual/tag-dispatched-metafunction.html (props changed)
branches/release/libs/mpl/doc/refmanual/trivial-metafunctions-summary.html (props changed)
branches/release/libs/mpl/doc/src/refmanual/Iterators-Iterator.rst (props changed)
branches/release/libs/numeric/ublas/ (props changed)
branches/release/libs/numeric/ublas/doc/ (props changed)
branches/release/libs/program_options/ (props changed)
branches/release/libs/property_tree/ (props changed)
branches/release/libs/python/ (props changed)
branches/release/libs/regex/ (props changed)
branches/release/libs/regex/doc/ (props changed)
branches/release/libs/serialization/ (props changed)
branches/release/libs/signals/ (props changed)
branches/release/libs/signals2/ (props changed)
branches/release/libs/spirit/ (props changed)
branches/release/libs/spirit/classic/example/ (props changed)
branches/release/libs/spirit/doc/ (props changed)
branches/release/libs/spirit/example/ (props changed)
branches/release/libs/spirit/phoenix/ (props changed)
branches/release/libs/spirit/test/ (props changed)
branches/release/libs/spirit/test/qi/optional.cpp (props changed)
branches/release/libs/statechart/ (props changed)
branches/release/libs/static_assert/ (props changed)
branches/release/libs/system/ (props changed)
branches/release/libs/thread/ (props changed)
branches/release/libs/thread/doc/ (props changed)
branches/release/libs/timer/ (props changed)
branches/release/libs/tr1/ (props changed)
branches/release/libs/type_traits/ (props changed)
branches/release/libs/utility/ (props changed)
branches/release/libs/utility/swap.html (props changed)
branches/release/libs/utility/value_init.htm (props changed)
branches/release/libs/utility/value_init_test.cpp (props changed)
branches/release/libs/uuid/ (props changed)
branches/release/libs/wave/ (props changed)
branches/release/more/ (props changed)
branches/release/people/ (props changed)
branches/release/rst.css (props changed)
branches/release/status/ (props changed)
branches/release/status/Jamfile.v2 (props changed)
branches/release/tools/ (props changed)
branches/release/tools/bcp/ (props changed)
branches/release/tools/boostbook/ (props changed)
branches/release/tools/build/v2/ (props changed)
branches/release/tools/inspect/ (props changed)
branches/release/tools/regression/ (props changed)
branches/release/tools/release/ (props changed)
branches/release/tools/wave/ (props changed)
branches/release/wiki/ (props changed)
Text files modified:
branches/release/boost/nondet_random.hpp | 90 ++++++
branches/release/boost/random.hpp | 9
branches/release/boost/random/additive_combine.hpp | 106 +++++++
branches/release/boost/random/bernoulli_distribution.hpp | 30 ++
branches/release/boost/random/binomial_distribution.hpp | 39 ++
branches/release/boost/random/cauchy_distribution.hpp | 33 ++
branches/release/boost/random/detail/auto_link.hpp | 2
branches/release/boost/random/detail/disable_warnings.hpp | 1
branches/release/boost/random/detail/seed.hpp | 7
branches/release/boost/random/discard_block.hpp | 9
branches/release/boost/random/exponential_distribution.hpp | 6
branches/release/boost/random/gamma_distribution.hpp | 11
branches/release/boost/random/geometric_distribution.hpp | 26 +
branches/release/boost/random/inversive_congruential.hpp | 44 +++
branches/release/boost/random/lagged_fibonacci.hpp | 142 ++++++++++
branches/release/boost/random/linear_congruential.hpp | 123 +++++++++
branches/release/boost/random/linear_feedback_shift.hpp | 11
branches/release/boost/random/lognormal_distribution.hpp | 14 +
branches/release/boost/random/mersenne_twister.hpp | 86 ++++++
branches/release/boost/random/normal_distribution.hpp | 19 +
branches/release/boost/random/poisson_distribution.hpp | 16 +
branches/release/boost/random/random_number_generator.hpp | 17 +
branches/release/boost/random/ranlux.hpp | 31 ++
branches/release/boost/random/shuffle_output.hpp | 61 ++++
branches/release/boost/random/subtract_with_carry.hpp | 25 +
branches/release/boost/random/triangle_distribution.hpp | 20 +
branches/release/boost/random/uniform_01.hpp | 49 +++
branches/release/boost/random/uniform_int.hpp | 38 ++
branches/release/boost/random/uniform_on_sphere.hpp | 14 +
branches/release/boost/random/uniform_real.hpp | 24 +
branches/release/boost/random/uniform_smallint.hpp | 52 +++
branches/release/boost/random/variate_generator.hpp | 87 ++++++
branches/release/boost/random/xor_combine.hpp | 52 +++
branches/release/doc/Jamfile.v2 | 2
branches/release/doc/src/boost.xml | 11
branches/release/libs/random/doc/Jamfile.v2 | 23 +
branches/release/libs/random/doc/concepts.qbk | 8
branches/release/libs/random/doc/distribution_performance_linux.qbk | 8
branches/release/libs/random/doc/distribution_performance_windows.qbk | 8
branches/release/libs/random/doc/distributions.qbk | 8
branches/release/libs/random/doc/generator_defs.qbk | 8
branches/release/libs/random/doc/generator_performance_linux.qbk | 8
branches/release/libs/random/doc/generator_performance_windows.qbk | 8
branches/release/libs/random/doc/generators.qbk | 8
branches/release/libs/random/doc/nondet_random.qbk | 8
branches/release/libs/random/doc/performance.qbk | 8
branches/release/libs/random/doc/performance_data.qbk | 8
branches/release/libs/random/doc/random.qbk | 2
branches/release/libs/random/doc/random_number_generator.qbk | 8
branches/release/libs/random/doc/tutorial.qbk | 8
branches/release/libs/random/example/die.cpp | 9
branches/release/libs/random/example/weighted_die.cpp | 9
branches/release/libs/random/src/random_device.cpp | 41 +-
branches/release/libs/random/test/Jamfile.v2 | 12
branches/release/libs/random/test/instantiate.cpp | 4
branches/release/libs/random/test/integrate.hpp | 8
branches/release/libs/random/test/random_test.cpp | 2
branches/release/libs/random/test/statistic_tests.cpp | 521 +++++++++++++--------------------------
branches/release/libs/random/test/statistic_tests.hpp | 146 ++++++++--
branches/release/libs/random/test/validate.cpp | 32 +-
branches/release/status/explicit-failures-markup.xml | 21 +
61 files changed, 1745 insertions(+), 496 deletions(-)
Modified: branches/release/boost/nondet_random.hpp
==============================================================================
--- branches/release/boost/nondet_random.hpp (original)
+++ branches/release/boost/nondet_random.hpp 2010-03-21 20:45:06 EDT (Sun, 21 Mar 2010)
@@ -23,10 +23,66 @@
#include <boost/config.hpp>
#include <boost/utility.hpp> // noncopyable
#include <boost/integer_traits.hpp> // compile-time integral limits
+#include <boost/random/detail/auto_link.hpp>
namespace boost {
-// use some OS service to generate non-deterministic random numbers
+/**
+ * Class \random_device models a \nondeterministic_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
+ *
+ * @blockquote
+ * "Randomness Recommendations for Security", D. Eastlake, S. Crocker,
+ * J. Schiller, Network Working Group, RFC 1750, December 1994
+ * @endblockquote
+ *
+ * for further discussions.
+ *
+ * @xmlnote
+ * 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.
+ * @endxmlnote
+ *
+ * <b>Implementation Note for Linux</b>
+ *
+ * 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, @c 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.
+ *
+ * <b>Inplementation Note for Windows</b>
+ *
+ * On the Windows operating system, token is interpreted as the name
+ * of a cryptographic service provider. By default \random_device uses
+ * MS_DEF_PROV.
+ *
+ * <b>Performance</b>
+ *
+ * The test program <a href="\boost/libs/random/performance/nondet_random_speed.cpp">
+ * nondet_random_speed.cpp</a> 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.
+ *
+ * <table cols="2">
+ * <tr><th>class</th><th>time per invocation [usec]</th></tr>
+ * <tr><td> @xmlonly <classname alt="boost::random_device">random_device</classname> @endxmlonly </td><td>92.0</td></tr>
+ * </table>
+ *
+ * The measurement error is estimated at +/- 1 usec.
+ */
class random_device : private noncopyable
{
public:
@@ -35,15 +91,37 @@
BOOST_STATIC_CONSTANT(result_type, min_value = integer_traits<result_type>::const_min);
BOOST_STATIC_CONSTANT(result_type, max_value = integer_traits<result_type>::const_max);
+ /**
+ * Returns: The smallest value that the \random_device can produce.
+ */
result_type min BOOST_PREVENT_MACRO_SUBSTITUTION () const { return min_value; }
+ /**
+ * Returns: The largest value that the \random_device can produce.
+ */
result_type max BOOST_PREVENT_MACRO_SUBSTITUTION () const { return max_value; }
- explicit random_device(const std::string& token = default_token);
- ~random_device();
- double entropy() const;
- unsigned int operator()();
+ /**
+ * Constructs a @c 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.
+ */
+ BOOST_RANDOM_DECL explicit random_device(const std::string& token = default_token);
+ BOOST_RANDOM_DECL ~random_device();
+ /**
+ * Returns: An entropy estimate for the random numbers returned by
+ * operator(), in the range min() to log2( max()+1). A deterministic
+ * random number generator (e.g. a pseudo-random number engine)
+ * has entropy 0.
+ *
+ * Throws: Nothing.
+ */
+ BOOST_RANDOM_DECL double entropy() const;
+ /**
+ * Returns: A random value in the range [min, max]
+ */
+ BOOST_RANDOM_DECL unsigned int operator()();
private:
- static const char * const default_token;
+ BOOST_RANDOM_DECL static const char * const default_token;
/*
* std:5.3.5/5 [expr.delete]: "If the object being deleted has incomplete
Modified: branches/release/boost/random.hpp
==============================================================================
--- branches/release/boost/random.hpp (original)
+++ branches/release/boost/random.hpp 2010-03-21 20:45:06 EDT (Sun, 21 Mar 2010)
@@ -47,6 +47,15 @@
#include <boost/random/variate_generator.hpp>
namespace boost {
+ /**
+ * The specialization taus88 was suggested in
+ *
+ * @blockquote
+ * "Maximally Equidistributed Combined Tausworthe Generators",
+ * Pierre L'Ecuyer, Mathematics of Computation, Volume 65,
+ * Number 213, January 1996, Pages 203-213
+ * @endblockquote
+ */
typedef random::xor_combine<random::xor_combine<random::linear_feedback_shift<uint32_t, 32, 31, 13, 12, 0>, 0,
random::linear_feedback_shift<uint32_t, 32, 29, 2, 4, 0>, 0, 0>, 0,
random::linear_feedback_shift<uint32_t, 32, 28, 3, 17, 0>, 0, 0> taus88;
Modified: branches/release/boost/random/additive_combine.hpp
==============================================================================
--- branches/release/boost/random/additive_combine.hpp (original)
+++ branches/release/boost/random/additive_combine.hpp 2010-03-21 20:45:06 EDT (Sun, 21 Mar 2010)
@@ -26,7 +26,24 @@
namespace boost {
namespace random {
-// L'Ecuyer 1988
+/**
+ * An instantiation of class template \additive_combine model a
+ * \pseudo_random_number_generator. It combines two multiplicative
+ * \linear_congruential number generators, i.e. those with @c c = 0.
+ * It is described in
+ *
+ * @blockquote
+ * "Efficient and Portable Combined Random Number Generators", Pierre L'Ecuyer,
+ * Communications of the ACM, Vol. 31, No. 6, June 1988, pp. 742-749, 774
+ * @endblockquote
+ *
+ * The template parameters MLCG1 and MLCG2 shall denote two different
+ * \linear_congruential number generators, each with c = 0. Each invocation
+ * returns a random number X(n) := (MLCG1(n) - MLCG2(n)) mod (m1 - 1), where
+ * m1 denotes the modulus of MLCG1.
+ *
+ * The template parameter @c val is the validation value checked by validation.
+ */
template<class MLCG1, class MLCG2,
#ifndef BOOST_NO_DEPENDENT_TYPES_IN_TEMPLATE_VALUE_PARAMETERS
typename MLCG1::result_type
@@ -47,30 +64,71 @@
#else
enum { has_fixed_range = false };
#endif
+ /**
+ * Returns: The smallest value that the generator can produce
+ */
result_type min BOOST_PREVENT_MACRO_SUBSTITUTION () const { return 1; }
+ /**
+ * Returns: The largest value that the generator can produce
+ */
result_type max BOOST_PREVENT_MACRO_SUBSTITUTION () const { return (_mlcg1.max)()-1; }
+ /**
+ * Constructs an \additive_combine generator using the
+ * default constructors of the two base generators.
+ */
additive_combine() : _mlcg1(), _mlcg2() { }
+ /**
+ * Constructs an \additive_combine generator, using aseed as
+ * the constructor argument for both base generators.
+ */
+ explicit additive_combine(result_type aseed)
+ : _mlcg1(aseed), _mlcg2(aseed) { }
+ /**
+ * Constructs an \additive_combine generator, using
+ * @c seed1 and @c seed2 as the constructor argument to
+ * the first and second base generators, respectively.
+ */
additive_combine(typename MLCG1::result_type seed1,
typename MLCG2::result_type seed2)
: _mlcg1(seed1), _mlcg2(seed2) { }
- additive_combine(result_type aseed)
- : _mlcg1(aseed), _mlcg2(aseed) { }
+ /**
+ * Contructs an \additive_combine generator with
+ * values from the range defined by the input iterators first
+ * and last. first will be modified to point to the element
+ * after the last one used.
+ *
+ * Throws: @c std::invalid_argument if the input range is too small.
+ *
+ * Exception Safety: Basic
+ */
template<class It> additive_combine(It& first, It last)
: _mlcg1(first, last), _mlcg2(first, last) { }
+ /**
+ * Seeds an \additive_combine generator using the default
+ * seeds of the two base generators.
+ */
void seed()
{
_mlcg1.seed();
_mlcg2.seed();
}
+ /**
+ * Seeds an \additive_combine generator, using @c aseed as the
+ * seed for both base generators.
+ */
void seed(result_type aseed)
{
_mlcg1.seed(aseed);
_mlcg2.seed(aseed);
}
+ /**
+ * Seeds an \additive_combine generator, using @c seed1 and @c seed2 as
+ * the seeds to the first and second base generators, respectively.
+ */
void seed(typename MLCG1::result_type seed1,
typename MLCG2::result_type seed2)
{
@@ -78,36 +136,69 @@
_mlcg2.seed(seed2);
}
+ /**
+ * Seeds an \additive_combine generator with
+ * values from the range defined by the input iterators first
+ * and last. first will be modified to point to the element
+ * after the last one used.
+ *
+ * Throws: @c std::invalid_argument if the input range is too small.
+ *
+ * Exception Safety: Basic
+ */
template<class It> void seed(It& first, It last)
{
_mlcg1.seed(first, last);
_mlcg2.seed(first, last);
}
+ /**
+ * Returns: the next value of the generator
+ */
result_type operator()() {
result_type z = _mlcg1() - _mlcg2();
if(z < 1)
z += MLCG1::modulus-1;
return z;
}
+
static bool validation(result_type x) { return val == x; }
#ifndef BOOST_NO_OPERATORS_IN_NAMESPACE
#ifndef BOOST_RANDOM_NO_STREAM_OPERATORS
+ /**
+ * Writes the state of an \additive_combine generator to a @c
+ * std::ostream. The textual representation of an \additive_combine
+ * generator is the textual representation of the first base
+ * generator followed by the textual representation of the
+ * second base generator.
+ */
template<class CharT, class Traits>
friend std::basic_ostream<CharT,Traits>&
operator<<(std::basic_ostream<CharT,Traits>& os, const additive_combine& r)
{ os << r._mlcg1 << " " << r._mlcg2; return os; }
+ /**
+ * Reads the state of an \additive_combine generator from a
+ * @c std::istream.
+ */
template<class CharT, class Traits>
friend std::basic_istream<CharT,Traits>&
operator>>(std::basic_istream<CharT,Traits>& is, additive_combine& r)
{ is >> r._mlcg1 >> std::ws >> r._mlcg2; return is; }
#endif
+ /**
+ * Returns: true iff the two \additive_combine generators will
+ * produce the same sequence of values.
+ */
friend bool operator==(const additive_combine& x, const additive_combine& y)
{ return x._mlcg1 == y._mlcg1 && x._mlcg2 == y._mlcg2; }
+ /**
+ * Returns: true iff the two \additive_combine generators will
+ * produce different sequences of values.
+ */
friend bool operator!=(const additive_combine& x, const additive_combine& y)
{ return !(x == y); }
#else
@@ -117,6 +208,7 @@
bool operator!=(const additive_combine& rhs) const
{ return !(*this == rhs); }
#endif
+
private:
MLCG1 _mlcg1;
MLCG2 _mlcg2;
@@ -124,6 +216,14 @@
} // namespace random
+/**
+ * The specialization \ecuyer1988 was suggested in
+ *
+ * @blockquote
+ * "Efficient and Portable Combined Random Number Generators", Pierre L'Ecuyer,
+ * Communications of the ACM, Vol. 31, No. 6, June 1988, pp. 742-749, 774
+ * @endblockquote
+ */
typedef random::additive_combine<
random::linear_congruential<int32_t, 40014, 0, 2147483563, 0>,
random::linear_congruential<int32_t, 40692, 0, 2147483399, 0>,
Modified: branches/release/boost/random/bernoulli_distribution.hpp
==============================================================================
--- branches/release/boost/random/bernoulli_distribution.hpp (original)
+++ branches/release/boost/random/bernoulli_distribution.hpp 2010-03-21 20:45:06 EDT (Sun, 21 Mar 2010)
@@ -22,7 +22,12 @@
namespace boost {
-// Bernoulli distribution: p(true) = p, p(false) = 1-p (boolean)
+/**
+ * Instantiations of class template \bernoulli_distribution model a
+ * \random_distribution. Such a random distribution produces bool values
+ * distributed with probabilities P(true) = p and P(false) = 1-p. p is
+ * the parameter of the distribution.
+ */
template<class RealType = double>
class bernoulli_distribution
{
@@ -33,6 +38,12 @@
typedef int input_type;
typedef bool result_type;
+ /**
+ * Constructs a \bernoulli_distribution object.
+ * p is the parameter of the distribution.
+ *
+ * Requires: 0 <= p <= 1
+ */
explicit bernoulli_distribution(const RealType& p_arg = RealType(0.5))
: _p(p_arg)
{
@@ -42,9 +53,20 @@
// compiler-generated copy ctor and assignment operator are fine
+ /**
+ * Returns: The "p" parameter of the distribution.
+ */
RealType p() const { return _p; }
+ /**
+ * Effects: Subsequent uses of the distribution do not depend
+ * on values produced by any engine prior to invoking reset.
+ */
void reset() { }
+ /**
+ * Returns: a random variate distributed according to the
+ * \bernoulli_distribution.
+ */
template<class Engine>
result_type operator()(Engine& eng)
{
@@ -55,6 +77,9 @@
}
#ifndef BOOST_RANDOM_NO_STREAM_OPERATORS
+ /**
+ * Writes the parameters of the distribution to a @c std::ostream.
+ */
template<class CharT, class Traits>
friend std::basic_ostream<CharT,Traits>&
operator<<(std::basic_ostream<CharT,Traits>& os, const bernoulli_distribution& bd)
@@ -63,6 +88,9 @@
return os;
}
+ /**
+ * Reads the parameters of the distribution from a @c std::istream.
+ */
template<class CharT, class Traits>
friend std::basic_istream<CharT,Traits>&
operator>>(std::basic_istream<CharT,Traits>& is, bernoulli_distribution& bd)
Modified: branches/release/boost/random/binomial_distribution.hpp
==============================================================================
--- branches/release/boost/random/binomial_distribution.hpp (original)
+++ branches/release/boost/random/binomial_distribution.hpp 2010-03-21 20:45:06 EDT (Sun, 21 Mar 2010)
@@ -21,7 +21,14 @@
namespace boost {
-// Knuth
+/**
+ * The binomial distribution is an integer valued distribution with
+ * two parameters, @c t and @c p. The values of the distribution
+ * are within the range [0,t].
+ *
+ * The probability that the distribution produces a value k is
+ * \f${t \choose k}p^k(1-p)^{t-k}\f$.
+ */
template<class IntType = int, class RealType = double>
class binomial_distribution
{
@@ -29,20 +36,36 @@
typedef typename bernoulli_distribution<RealType>::input_type input_type;
typedef IntType result_type;
- explicit binomial_distribution(IntType t_arg = 1,
- const RealType& p_arg = RealType(0.5))
- : _bernoulli(p_arg), _t(t_arg)
+ /**
+ * Construct an @c binomial_distribution object. @c t and @c p
+ * are the parameters of the distribution.
+ *
+ * Requires: t >=0 && 0 <= p <= 1
+ */
+ explicit binomial_distribution(IntType t = 1,
+ const RealType& p = RealType(0.5))
+ : _bernoulli(p), _t(t)
{
assert(_t >= 0);
- assert(RealType(0) <= p_arg && p_arg <= RealType(1));
+ assert(RealType(0) <= p && p <= RealType(1));
}
// compiler-generated copy ctor and assignment operator are fine
+ /** Returns: the @c t parameter of the distribution */
IntType t() const { return _t; }
+ /** Returns: the @c p parameter of the distribution */
RealType p() const { return _bernoulli.p(); }
+ /**
+ * Effects: Subsequent uses of the distribution do not depend
+ * on values produced by any engine prior to invoking reset.
+ */
void reset() { }
+ /**
+ * Returns: a random variate distributed according to the
+ * binomial distribution.
+ */
template<class Engine>
result_type operator()(Engine& eng)
{
@@ -55,6 +78,9 @@
}
#ifndef BOOST_RANDOM_NO_STREAM_OPERATORS
+ /**
+ * Writes the parameters of the distribution to a @c std::ostream.
+ */
template<class CharT, class Traits>
friend std::basic_ostream<CharT,Traits>&
operator<<(std::basic_ostream<CharT,Traits>& os, const binomial_distribution& bd)
@@ -63,6 +89,9 @@
return os;
}
+ /**
+ * Reads the parameters of the distribution from a @c std::istream.
+ */
template<class CharT, class Traits>
friend std::basic_istream<CharT,Traits>&
operator>>(std::basic_istream<CharT,Traits>& is, binomial_distribution& bd)
Modified: branches/release/boost/random/cauchy_distribution.hpp
==============================================================================
--- branches/release/boost/random/cauchy_distribution.hpp (original)
+++ branches/release/boost/random/cauchy_distribution.hpp 2010-03-21 20:45:06 EDT (Sun, 21 Mar 2010)
@@ -30,7 +30,14 @@
using std::tan;
#endif
-// Cauchy distribution: p(x) = sigma/(pi*(sigma**2 + (x-median)**2))
+// Cauchy distribution:
+
+/**
+ * The cauchy distribution is a continuous distribution with two
+ * parameters, sigma and median.
+ *
+ * It has \f$p(x) = \frac{\sigma}{\pi(\sigma^2 + (x-m)^2)}\f$
+ */
template<class RealType = double>
class cauchy_distribution
{
@@ -42,16 +49,34 @@
BOOST_STATIC_ASSERT(!std::numeric_limits<RealType>::is_integer);
#endif
+ /**
+ * Constructs a \cauchy_distribution with the paramters @c median
+ * and @c sigma.
+ */
explicit cauchy_distribution(result_type median_arg = result_type(0),
result_type sigma_arg = result_type(1))
: _median(median_arg), _sigma(sigma_arg) { }
// compiler-generated copy ctor and assignment operator are fine
+ /**
+ * Returns: the "median" parameter of the distribution
+ */
result_type median() const { return _median; }
+ /**
+ * Returns: the "sigma" parameter of the distribution
+ */
result_type sigma() const { return _sigma; }
+ /**
+ * Effects: Subsequent uses of the distribution do not depend
+ * on values produced by any engine prior to invoking reset.
+ */
void reset() { }
+ /**
+ * Returns: A random variate distributed according to the
+ * cauchy distribution.
+ */
template<class Engine>
result_type operator()(Engine& eng)
{
@@ -64,6 +89,9 @@
}
#ifndef BOOST_RANDOM_NO_STREAM_OPERATORS
+ /**
+ * Writes the parameters of the distribution to a @c std::ostream.
+ */
template<class CharT, class Traits>
friend std::basic_ostream<CharT,Traits>&
operator<<(std::basic_ostream<CharT,Traits>& os, const cauchy_distribution& cd)
@@ -72,6 +100,9 @@
return os;
}
+ /**
+ * Reads the parameters of the distribution from a @c std::istream.
+ */
template<class CharT, class Traits>
friend std::basic_istream<CharT,Traits>&
operator>>(std::basic_istream<CharT,Traits>& is, cauchy_distribution& cd)
Copied: branches/release/boost/random/detail/auto_link.hpp (from r60199, /trunk/boost/random/detail/auto_link.hpp)
==============================================================================
--- /trunk/boost/random/detail/auto_link.hpp (original)
+++ branches/release/boost/random/detail/auto_link.hpp 2010-03-21 20:45:06 EDT (Sun, 21 Mar 2010)
@@ -14,7 +14,7 @@
#include <boost/config.hpp>
#ifdef BOOST_HAS_DECLSPEC
- #if defined(BOOST_ALL_DYN_LINK) || defined(BOOST_FILESYSTEM_DYN_LINK)
+ #if defined(BOOST_ALL_DYN_LINK) || defined(BOOST_RANDOM_DYN_LINK)
#if defined(BOOST_RANDOM_SOURCE)
#define BOOST_RANDOM_DECL __declspec(dllexport)
#else
Modified: branches/release/boost/random/detail/disable_warnings.hpp
==============================================================================
--- branches/release/boost/random/detail/disable_warnings.hpp (original)
+++ branches/release/boost/random/detail/disable_warnings.hpp 2010-03-21 20:45:06 EDT (Sun, 21 Mar 2010)
@@ -19,4 +19,5 @@
#pragma warning(push)
#pragma warning(disable:4512)
#pragma warning(disable:4127)
+#pragma warning(disable:4724)
#endif
Modified: branches/release/boost/random/detail/seed.hpp
==============================================================================
--- branches/release/boost/random/detail/seed.hpp (original)
+++ branches/release/boost/random/detail/seed.hpp 2010-03-21 20:45:06 EDT (Sun, 21 Mar 2010)
@@ -15,7 +15,9 @@
#include <boost/config.hpp>
-#if !defined(BOOST_NO_SFINAE)
+// Sun seems to have trouble with the use of SFINAE for the
+// templated constructor. So does Borland.
+#if !defined(BOOST_NO_SFINAE) && !defined(__SUNPRO_CC) && !defined(__BORLANDC__)
#include <boost/utility/enable_if.hpp>
#include <boost/type_traits/is_arithmetic.hpp>
@@ -31,8 +33,7 @@
struct disable_constructor : disable_seed<T> {};
template<class Engine>
-struct disable_constructor<Engine, Engine> {
-};
+struct disable_constructor<Engine, Engine> {};
#define BOOST_RANDOM_DETAIL_GENERATOR_CONSTRUCTOR(Self, Generator, gen) \
template<class Generator> \
Modified: branches/release/boost/random/discard_block.hpp
==============================================================================
--- branches/release/boost/random/discard_block.hpp (original)
+++ branches/release/boost/random/discard_block.hpp 2010-03-21 20:45:06 EDT (Sun, 21 Mar 2010)
@@ -26,6 +26,15 @@
namespace boost {
namespace random {
+/**
+ * The class template \discard_block is a model of
+ * \pseudo_random_number_generator. It modifies
+ * another generator by discarding parts of its output.
+ * Out of every block of @c r results, the first @c p
+ * will be returned and the rest discarded.
+ *
+ * Requires: 0 < p <= r
+ */
template<class UniformRandomNumberGenerator, unsigned int p, unsigned int r>
class discard_block
{
Modified: branches/release/boost/random/exponential_distribution.hpp
==============================================================================
--- branches/release/boost/random/exponential_distribution.hpp (original)
+++ branches/release/boost/random/exponential_distribution.hpp 2010-03-21 20:45:06 EDT (Sun, 21 Mar 2010)
@@ -25,7 +25,11 @@
namespace boost {
-// exponential distribution: p(x) = lambda * exp(-lambda * x)
+/**
+ * The exponential distribution has a single parameter lambda.
+ *
+ * It has \f$p(x) = \lambda e^{-\lambda x}\f$
+ */
template<class RealType = double>
class exponential_distribution
{
Modified: branches/release/boost/random/gamma_distribution.hpp
==============================================================================
--- branches/release/boost/random/gamma_distribution.hpp (original)
+++ branches/release/boost/random/gamma_distribution.hpp 2010-03-21 20:45:06 EDT (Sun, 21 Mar 2010)
@@ -23,7 +23,14 @@
namespace boost {
-// Knuth
+// The algorithm is taken from Knuth
+
+/**
+ * The gamma distribution is a continuous distribution with a single
+ * parameter alpha.
+ *
+ * It has \f$p(x) = x^{\alpha-1}\frac{e^{-x}}{\Gamma(\alpha)}\f$.
+ */
template<class RealType = double>
class gamma_distribution
{
@@ -114,6 +121,7 @@
#endif
private:
+ /// \cond hide_private_members
void init()
{
#ifndef BOOST_NO_STDC_NAMESPACE
@@ -122,6 +130,7 @@
#endif
_p = exp(result_type(1)) / (_alpha + exp(result_type(1)));
}
+ /// \endcond
exponential_distribution<RealType> _exp;
result_type _alpha;
Modified: branches/release/boost/random/geometric_distribution.hpp
==============================================================================
--- branches/release/boost/random/geometric_distribution.hpp (original)
+++ branches/release/boost/random/geometric_distribution.hpp 2010-03-21 20:45:06 EDT (Sun, 21 Mar 2010)
@@ -30,7 +30,14 @@
using std::log;
#endif
-// geometric distribution: p(i) = (1-p) * pow(p, i-1) (integer)
+/**
+ * An instantiation of the class template @c geometric_distribution models
+ * a \random_distribution. The distribution produces positive
+ * integers which are the number of bernoulli trials
+ * with probability @c p required to get one that fails.
+ *
+ * For the geometric distribution, \f$p(i) = (1-p) p^{i-1}\f$.
+ */
template<class IntType = int, class RealType = double>
class geometric_distribution
{
@@ -38,8 +45,13 @@
typedef RealType input_type;
typedef IntType result_type;
- explicit geometric_distribution(const RealType& p_arg = RealType(0.5))
- : _p(p_arg)
+ /**
+ * Contructs a new geometric_distribution with the paramter @c p.
+ *
+ * Requires: 0 < p < 1
+ */
+ explicit geometric_distribution(const RealType& p = RealType(0.5))
+ : _p(p)
{
assert(RealType(0) < _p && _p < RealType(1));
init();
@@ -47,6 +59,9 @@
// compiler-generated copy ctor and assignment operator are fine
+ /**
+ * Returns: the distribution parameter @c p
+ */
RealType p() const { return _p; }
void reset() { }
@@ -80,6 +95,9 @@
#endif
private:
+
+ /// \cond hide_private_functions
+
void init()
{
#ifndef BOOST_NO_STDC_NAMESPACE
@@ -88,6 +106,8 @@
_log_p = log(_p);
}
+ /// \endcond
+
RealType _p;
RealType _log_p;
};
Modified: branches/release/boost/random/inversive_congruential.hpp
==============================================================================
--- branches/release/boost/random/inversive_congruential.hpp (original)
+++ branches/release/boost/random/inversive_congruential.hpp 2010-03-21 20:45:06 EDT (Sun, 21 Mar 2010)
@@ -28,6 +28,35 @@
namespace random {
// Eichenauer and Lehn 1986
+/**
+ * Instantiations of class template @c inversive_congruential model a
+ * \pseudo_random_number_generator. It uses the inversive congruential
+ * algorithm (ICG) described in
+ *
+ * @blockquote
+ * "Inversive pseudorandom number generators: concepts, results and links",
+ * Peter Hellekalek, In: "Proceedings of the 1995 Winter Simulation
+ * Conference", C. Alexopoulos, K. Kang, W.R. Lilegdon, and D. Goldsman
+ * (editors), 1995, pp. 255-262. ftp://random.mat.sbg.ac.at/pub/data/wsc95.ps
+ * @endblockquote
+ *
+ * The output sequence is defined by x(n+1) = (a*inv(x(n)) - b) (mod p),
+ * where x(0), a, b, and the prime number p are parameters of the generator.
+ * The expression inv(k) denotes the multiplicative inverse of k in the
+ * field of integer numbers modulo p, with inv(0) := 0.
+ *
+ * The template parameter IntType shall denote a signed integral type large
+ * enough to hold p; a, b, and p are the parameters of the generators. The
+ * template parameter val is the validation value checked by validation.
+ *
+ * @xmlnote
+ * The implementation currently uses the Euclidian Algorithm to compute
+ * the multiplicative inverse. Therefore, the inversive generators are about
+ * 10-20 times slower than the others (see section"performance"). However,
+ * the paper talks of only 3x slowdown, so the Euclidian Algorithm is probably
+ * not optimal for calculating the multiplicative inverse.
+ * @endxmlnote
+ */
template<class IntType, IntType a, IntType b, IntType p, IntType val>
class inversive_congruential
{
@@ -47,6 +76,10 @@
result_type min BOOST_PREVENT_MACRO_SUBSTITUTION () const { return b == 0 ? 1 : 0; }
result_type max BOOST_PREVENT_MACRO_SUBSTITUTION () const { return p-1; }
+ /**
+ * Constructs an inversive_congruential generator with
+ * @c y0 as the initial state.
+ */
explicit inversive_congruential(IntType y0 = 1) : value(y0)
{
BOOST_STATIC_ASSERT(b >= 0);
@@ -58,6 +91,7 @@
template<class It> inversive_congruential(It& first, It last)
{ seed(first, last); }
+ /** Changes the current state to y0. */
void seed(IntType y0 = 1) { value = y0; if(b == 0) assert(y0 > 0); }
template<class It> void seed(It& first, It last)
{
@@ -121,6 +155,16 @@
} // namespace random
+/**
+ * The specialization hellekalek1995 was suggested in
+ *
+ * @blockquote
+ * "Inversive pseudorandom number generators: concepts, results and links",
+ * Peter Hellekalek, In: "Proceedings of the 1995 Winter Simulation
+ * Conference", C. Alexopoulos, K. Kang, W.R. Lilegdon, and D. Goldsman
+ * (editors), 1995, pp. 255-262. ftp://random.mat.sbg.ac.at/pub/data/wsc95.ps
+ * @endblockquote
+ */
typedef random::inversive_congruential<int32_t, 9102, 2147483647-36884165,
2147483647, 0> hellekalek1995;
Modified: branches/release/boost/random/lagged_fibonacci.hpp
==============================================================================
--- branches/release/boost/random/lagged_fibonacci.hpp (original)
+++ branches/release/boost/random/lagged_fibonacci.hpp 2010-03-21 20:45:06 EDT (Sun, 21 Mar 2010)
@@ -80,6 +80,12 @@
}
# endif
+/**
+ * Instantiations of class template \lagged_fibonacci model a
+ * \pseudo_random_number_generator. It uses a lagged Fibonacci
+ * algorithm with two lags @c p and @c q:
+ * x(i) = x(i-p) + x(i-q) (mod 2<sup>w</sup>) with p > q.
+ */
template<class UIntType, int w, unsigned int p, unsigned int q,
UIntType val = 0>
class lagged_fibonacci
@@ -91,24 +97,45 @@
BOOST_STATIC_CONSTANT(unsigned int, long_lag = p);
BOOST_STATIC_CONSTANT(unsigned int, short_lag = q);
+ /**
+ * Returns: the smallest value that the generator can produce
+ */
result_type min BOOST_PREVENT_MACRO_SUBSTITUTION () const { return 0; }
+ /**
+ * Returns: the largest value that the generator can produce
+ */
result_type max BOOST_PREVENT_MACRO_SUBSTITUTION () const { return wordmask; }
+ /**
+ * Creates a new @c lagged_fibonacci generator and calls @c seed()
+ */
lagged_fibonacci() { init_wordmask(); seed(); }
+ /**
+ * Creates a new @c lagged_fibonacci generator and calls @c seed(value)
+ */
explicit lagged_fibonacci(uint32_t value) { init_wordmask(); seed(value); }
+ /**
+ * Creates a new @c lagged_fibonacci generator and calls @c seed(first, last)
+ */
template<class It> lagged_fibonacci(It& first, It last)
{ init_wordmask(); seed(first, last); }
// compiler-generated copy ctor and assignment operator are fine
private:
+ /// \cond hide_private_members
void init_wordmask()
{
wordmask = 0;
for(int j = 0; j < w; ++j)
wordmask |= (1u << j);
}
+ /// \endcond
public:
+ /**
+ * Sets the state of the generator to values produced by
+ * a \minstd_rand generator.
+ */
void seed(uint32_t value = 331u)
{
minstd_rand0 gen(value);
@@ -117,6 +144,11 @@
i = long_lag;
}
+ /**
+ * Sets the state of the generator to values from the iterator
+ * range [first, last). If there are not enough elements in the
+ * range [first, last) throws @c std::invalid_argument.
+ */
template<class It>
void seed(It& first, It last)
{
@@ -129,6 +161,9 @@
throw std::invalid_argument("lagged_fibonacci::seed");
}
+ /**
+ * Returns: the next value of the generator
+ */
result_type operator()()
{
if(i >= long_lag)
@@ -183,7 +218,10 @@
#endif
private:
+ /// \cond hide_private_members
void fill();
+ /// \endcond
+
UIntType wordmask;
unsigned int i;
UIntType x[long_lag];
@@ -199,6 +237,8 @@
const unsigned int lagged_fibonacci<UIntType, w, p, q, val>::short_lag;
#endif
+/// \cond hide_private_members
+
template<class UIntType, int w, unsigned int p, unsigned int q, UIntType val>
void lagged_fibonacci<UIntType, w, p, q, val>::fill()
{
@@ -257,6 +297,30 @@
#undef BOOST_RANDOM_FIBONACCI_VAL
+/// \endcond
+
+/**
+ * Instantiations of class template @c lagged_fibonacci_01 model a
+ * \pseudo_random_number_generator. It uses a lagged Fibonacci
+ * algorithm with two lags @c p and @c q, evaluated in floating-point
+ * arithmetic: x(i) = x(i-p) + x(i-q) (mod 1) with p > q. See
+ *
+ * @blockquote
+ * "Uniform random number generators for supercomputers", Richard Brent,
+ * Proc. of Fifth Australian Supercomputer Conference, Melbourne,
+ * Dec. 1992, pp. 704-706.
+ * @endblockquote
+ *
+ * @xmlnote
+ * The quality of the generator crucially depends on the choice
+ * of the parameters. User code should employ one of the sensibly
+ * parameterized generators such as \lagged_fibonacci607 instead.
+ * @endxmlnote
+ *
+ * The generator requires considerable amounts of memory for the storage
+ * of its state array. For example, \lagged_fibonacci607 requires about
+ * 4856 bytes and \lagged_fibonacci44497 requires about 350 KBytes.
+ */
template<class RealType, int w, unsigned int p, unsigned int q>
class lagged_fibonacci_01
{
@@ -267,9 +331,12 @@
BOOST_STATIC_CONSTANT(unsigned int, long_lag = p);
BOOST_STATIC_CONSTANT(unsigned int, short_lag = q);
+ /** Constructs a @c lagged_fibonacci_01 generator and calls @c seed(). */
lagged_fibonacci_01() { init_modulus(); seed(); }
+ /** Constructs a @c lagged_fibonacci_01 generator and calls @c seed(value). */
BOOST_RANDOM_DETAIL_ARITHMETIC_CONSTRUCTOR(lagged_fibonacci_01, uint32_t, value)
{ init_modulus(); seed(value); }
+ /** Constructs a @c lagged_fibonacci_01 generator and calls @c seed(gen). */
BOOST_RANDOM_DETAIL_GENERATOR_CONSTRUCTOR(lagged_fibonacci_01, Generator, gen)
{ init_modulus(); seed(gen); }
template<class It> lagged_fibonacci_01(It& first, It last)
@@ -277,6 +344,7 @@
// compiler-generated copy ctor and assignment operator are fine
private:
+ /// \cond hide_private_members
void init_modulus()
{
#ifndef BOOST_NO_STDC_NAMESPACE
@@ -285,18 +353,30 @@
#endif
_modulus = pow(RealType(2), word_size);
}
+ /// \endcond
public:
+ /** Calls seed(331u). */
void seed() { seed(331u); }
+ /**
+ * Constructs a \minstd_rand0 generator with the constructor parameter
+ * value and calls seed with it. Distinct seeds in the range
+ * [1, 2147483647) will produce generators with different states. Other
+ * seeds will be equivalent to some seed within this range. See
+ * \linear_congruential for details.
+ */
BOOST_RANDOM_DETAIL_ARITHMETIC_SEED(lagged_fibonacci_01, uint32_t, value)
{
minstd_rand0 intgen(value);
seed(intgen);
}
- // 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.
+ /**
+ * Sets the state of this @c lagged_fibonacci_01 to the values returned
+ * by p invocations of \uniform_01<code>\<RealType\>()(gen)</code>.
+ *
+ * Complexity: Exactly p invocations of gen.
+ */
BOOST_RANDOM_DETAIL_GENERATOR_SEED(lagged_fibonacci, Generator, gen)
{
// use pass-by-reference, but wrap argument in pass_through_engine
@@ -407,7 +487,9 @@
#endif
private:
+ /// \cond hide_private_members
void fill();
+ /// \endcond
unsigned int i;
RealType x[long_lag];
RealType _modulus;
@@ -426,6 +508,7 @@
#endif
+/// \cond hide_private_members
template<class RealType, int w, unsigned int p, unsigned int q>
void lagged_fibonacci_01<RealType, w, p, q>::fill()
{
@@ -446,17 +529,70 @@
}
i = 0;
}
+/// \endcond
} // namespace random
+#ifdef BOOST_RANDOM_DOXYGEN
+namespace detail {
+/**
+ * The specializations lagged_fibonacci607 ... lagged_fibonacci44497
+ * use well tested lags.
+ *
+ * See
+ *
+ * @blockquote
+ * "On the Periods of Generalized Fibonacci Recurrences", Richard P. Brent
+ * Computer Sciences Laboratory Australian National University, December 1992
+ * @endblockquote
+ *
+ * The lags used here can be found in
+ *
+ * @blockquote
+ * "Uniform random number generators for supercomputers", Richard Brent,
+ * Proc. of Fifth Australian Supercomputer Conference, Melbourne,
+ * Dec. 1992, pp. 704-706.
+ * @endblockquote
+ */
+struct lagged_fibonacci_doc {};
+}
+#endif
+
+/**
+ * @copydoc boost::detail::lagged_fibonacci_doc
+ */
typedef random::lagged_fibonacci_01<double, 48, 607, 273> lagged_fibonacci607;
+/**
+ * @copydoc boost::detail::lagged_fibonacci_doc
+ */
typedef random::lagged_fibonacci_01<double, 48, 1279, 418> lagged_fibonacci1279;
+/**
+ * @copydoc boost::detail::lagged_fibonacci_doc
+ */
typedef random::lagged_fibonacci_01<double, 48, 2281, 1252> lagged_fibonacci2281;
+/**
+ * @copydoc boost::detail::lagged_fibonacci_doc
+ */
typedef random::lagged_fibonacci_01<double, 48, 3217, 576> lagged_fibonacci3217;
+/**
+ * @copydoc boost::detail::lagged_fibonacci_doc
+ */
typedef random::lagged_fibonacci_01<double, 48, 4423, 2098> lagged_fibonacci4423;
+/**
+ * @copydoc boost::detail::lagged_fibonacci_doc
+ */
typedef random::lagged_fibonacci_01<double, 48, 9689, 5502> lagged_fibonacci9689;
+/**
+ * @copydoc boost::detail::lagged_fibonacci_doc
+ */
typedef random::lagged_fibonacci_01<double, 48, 19937, 9842> lagged_fibonacci19937;
+/**
+ * @copydoc boost::detail::lagged_fibonacci_doc
+ */
typedef random::lagged_fibonacci_01<double, 48, 23209, 13470> lagged_fibonacci23209;
+/**
+ * @copydoc boost::detail::lagged_fibonacci_doc
+ */
typedef random::lagged_fibonacci_01<double, 48, 44497, 21034> lagged_fibonacci44497;
Modified: branches/release/boost/random/linear_congruential.hpp
==============================================================================
--- branches/release/boost/random/linear_congruential.hpp (original)
+++ branches/release/boost/random/linear_congruential.hpp 2010-03-21 20:45:06 EDT (Sun, 21 Mar 2010)
@@ -31,7 +31,26 @@
namespace boost {
namespace random {
-// compile-time configurable linear congruential generator
+/**
+ * Instantiations of class template linear_congruential model a
+ * \pseudo_random_number_generator. Linear congruential pseudo-random
+ * number generators are described in:
+ *
+ * "Mathematical methods in large-scale computing units", D. H. Lehmer,
+ * Proc. 2nd Symposium on Large-Scale Digital Calculating Machines,
+ * Harvard University Press, 1951, pp. 141-146
+ *
+ * Let x(n) denote the sequence of numbers returned by some pseudo-random
+ * number generator. Then for the linear congruential generator,
+ * x(n+1) := (a * x(n) + c) mod m. Parameters for the generator are
+ * x(0), a, c, m. The template parameter IntType shall denote an integral
+ * type. It must be large enough to hold values a, c, and m. The template
+ * parameters a and c must be smaller than m.
+ *
+ * Note: The quality of the generator crucially depends on the choice of
+ * the parameters. User code should use one of the sensibly parameterized
+ * generators such as minstd_rand instead.
+ */
template<class IntType, IntType a, IntType c, IntType m, IntType val>
class linear_congruential
{
@@ -53,6 +72,9 @@
// BOOST_STATIC_ASSERT(m == 0 || a < m);
// BOOST_STATIC_ASSERT(m == 0 || c < m);
+ /**
+ * Constructs a linear_congruential generator, seeding it with @c x0.
+ */
explicit linear_congruential(IntType x0 = 1)
{
seed(x0);
@@ -63,6 +85,14 @@
#endif
}
+ /**
+ * Constructs a @c linear_congruential generator and seeds it
+ * with values taken from the itrator range [first, last)
+ * and adjusts first to point to the element after the last one
+ * used. If there are not enough elements, throws @c std::invalid_argument.
+ *
+ * first and last must be input iterators.
+ */
template<class It>
linear_congruential(It& first, It last)
{
@@ -70,6 +100,13 @@
}
// compiler-generated copy constructor and assignment operator are fine
+
+ /**
+ * If c mod m is zero and x0 mod m is zero, changes the current value of
+ * the generator to 1. Otherwise, changes it to x0 mod m. If c is zero,
+ * distinct seeds in the range [1,m) will leave the generator in distinct
+ * states. If c is not zero, the range is [0,m).
+ */
void seed(IntType x0 = 1)
{
// wrap _x if it doesn't fit in the destination
@@ -90,6 +127,14 @@
assert(_x <= (max)());
}
+ /**
+ * seeds a @c linear_congruential generator with values taken
+ * from the itrator range [first, last) and adjusts @c first to
+ * point to the element after the last one used. If there are
+ * not enough elements, throws @c std::invalid_argument.
+ *
+ * @c first and @c last must be input iterators.
+ */
template<class It>
void seed(It& first, It last)
{
@@ -98,9 +143,18 @@
seed(*first++);
}
+ /**
+ * Returns the smallest value that the @c linear_congruential generator
+ * can produce.
+ */
result_type min BOOST_PREVENT_MACRO_SUBSTITUTION () const { return c == 0 ? 1 : 0; }
+ /**
+ * Returns the largest value that the @c linear_congruential generator
+ * can produce.
+ */
result_type max BOOST_PREVENT_MACRO_SUBSTITUTION () const { return modulus-1; }
+ /** Returns the next value of the @c linear_congruential generator. */
IntType operator()()
{
_x = const_mod<IntType, m>::mult_add(a, _x, c);
@@ -199,14 +253,48 @@
} // namespace random
// validation values from the publications
+/**
+ * The specialization \minstd_rand0 was originally suggested in
+ *
+ * @blockquote
+ * A pseudo-random number generator for the System/360, P.A. Lewis,
+ * A.S. Goodman, J.M. Miller, IBM Systems Journal, Vol. 8, No. 2,
+ * 1969, pp. 136-146
+ * @endblockquote
+ *
+ * It is examined more closely together with \minstd_rand in
+ *
+ * @blockquote
+ * "Random Number Generators: Good ones are hard to find",
+ * Stephen K. Park and Keith W. Miller, Communications of
+ * the ACM, Vol. 31, No. 10, October 1988, pp. 1192-1201
+ * @endblockquote
+ */
typedef random::linear_congruential<int32_t, 16807, 0, 2147483647,
1043618065> minstd_rand0;
+
+/** The specialization \minstd_rand was suggested in
+ *
+ * @blockquote
+ * "Random Number Generators: Good ones are hard to find",
+ * Stephen K. Park and Keith W. Miller, Communications of
+ * the ACM, Vol. 31, No. 10, October 1988, pp. 1192-1201
+ * @endblockquote
+ */
typedef random::linear_congruential<int32_t, 48271, 0, 2147483647,
399268537> 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 @c rand48 models a \pseudo_random_number_generator. It uses
+ * the linear congruential algorithm with the parameters a = 0x5DEECE66D,
+ * c = 0xB, m = 2**48. It delivers identical results to the @c lrand48()
+ * function available on some systems (assuming lcong48 has not been called).
+ *
+ * It is only available on systems where @c uint64_t is provided as an
+ * integral type, so that for example static in-class constants and/or
+ * enum definitions with large @c uint64_t numbers work.
+ */
class rand48
{
public:
@@ -218,17 +306,46 @@
#else
enum { has_fixed_range = false };
#endif
+ /**
+ * Returns the smallest value that the generator can produce
+ */
int32_t min BOOST_PREVENT_MACRO_SUBSTITUTION () const { return 0; }
+ /**
+ * Returns the largest value that the generator can produce
+ */
int32_t max BOOST_PREVENT_MACRO_SUBSTITUTION () const { return std::numeric_limits<int32_t>::max BOOST_PREVENT_MACRO_SUBSTITUTION (); }
+#ifdef BOOST_RANDOM_DOXYGEN
+ /**
+ * If T is an integral type smaller than int46_t, constructs
+ * a \rand48 generator with x(0) := (x0 << 16) | 0x330e. Otherwise
+ * constructs a \rand48 generator with x(0) = x0.
+ */
+ template<class T> explicit rand48(T x0 = 1);
+#else
rand48() : lcf(cnv(static_cast<int32_t>(1))) {}
template<class T> explicit rand48(T x0) : lcf(cnv(x0)) { }
+#endif
template<class It> rand48(It& first, It last) : lcf(first, last) { }
+
// compiler-generated copy ctor and assignment operator are fine
+
+#ifdef BOOST_RANDOM_DOXYGEN
+ /**
+ * If T is an integral type smaller than int46_t, changes
+ * the current value x(n) of the generator to (x0 << 16) | 0x330e.
+ * Otherwise changes the current value x(n) to x0.
+ */
+ template<class T> void seed(T x0 = 1);
+#else
void seed() { seed(static_cast<int32_t>(1)); }
template<class T> void seed(T x0) { lcf.seed(cnv(x0)); }
+#endif
template<class It> void seed(It& first, It last) { lcf.seed(first,last); }
+ /**
+ * Returns the next value of the generator.
+ */
int32_t operator()() { return static_cast<int32_t>(lcf() >> 17); }
// by experiment from lrand48()
static bool validation(int32_t x) { return x == 1993516219; }
@@ -259,6 +376,7 @@
{ return !(*this == rhs); }
#endif
private:
+ /// \cond hide_private_members
random::linear_congruential<uint64_t,
uint64_t(0xDEECE66DUL) | (uint64_t(0x5) << 32), // xxxxULL is not portable
0xB, uint64_t(1)<<48, /* unknown */ 0> lcf;
@@ -274,6 +392,7 @@
static uint64_t cnv(float x) { return(static_cast<uint64_t>(x)); }
static uint64_t cnv(double x) { return(static_cast<uint64_t>(x)); }
static uint64_t cnv(long double x) { return(static_cast<uint64_t>(x)); }
+ /// \endcond
};
#endif /* !BOOST_NO_INT64_T && !BOOST_NO_INTEGRAL_INT64_T */
Modified: branches/release/boost/random/linear_feedback_shift.hpp
==============================================================================
--- branches/release/boost/random/linear_feedback_shift.hpp (original)
+++ branches/release/boost/random/linear_feedback_shift.hpp 2010-03-21 20:45:06 EDT (Sun, 21 Mar 2010)
@@ -25,7 +25,16 @@
namespace boost {
namespace random {
-// Tausworte 1965
+/**
+ * Instatiation of @c linear_feedback_shift model a
+ * \pseudo_random_number_generator. It was originally
+ * proposed in
+ *
+ * @blockquote
+ * "Random numbers generated by linear recurrence modulo two.",
+ * Tausworthe, R. C.(1965), Mathematics of Computation 19, 201-209.
+ * @endblockquote
+ */
template<class UIntType, int w, int k, int q, int s, UIntType val>
class linear_feedback_shift
{
Modified: branches/release/boost/random/lognormal_distribution.hpp
==============================================================================
--- branches/release/boost/random/lognormal_distribution.hpp (original)
+++ branches/release/boost/random/lognormal_distribution.hpp 2010-03-21 20:45:06 EDT (Sun, 21 Mar 2010)
@@ -40,6 +40,13 @@
using std::exp;
#endif
+/**
+ * Instantiations of class template lognormal_distribution model a
+ * \random_distribution. Such a distribution produces random numbers
+ * with \f$p(x) = \frac{1}{x \sigma_N \sqrt{2\pi}} e^{\frac{-\left(\log(x)-\mu_N\right)^2}{2\sigma_N^2}}\f$
+ * for x > 0, where \f$\mu_N = \log\left(\frac{\mu^2}{\sqrt{\sigma^2 + \mu^2}}\right)\f$ and
+ * \f$\sigma_N = \sqrt{\log\left(1 + \frac{\sigma^2}{\mu^2}\right)}\f$.
+ */
template<class RealType = double>
class lognormal_distribution
{
@@ -51,6 +58,10 @@
BOOST_STATIC_ASSERT(!std::numeric_limits<RealType>::is_integer);
#endif
+ /**
+ * Constructs a lognormal_distribution. @c mean and @c sigma are the
+ * mean and standard deviation of the lognormal distribution.
+ */
explicit lognormal_distribution(result_type mean_arg = result_type(1),
result_type sigma_arg = result_type(1))
: _mean(mean_arg), _sigma(sigma_arg)
@@ -95,6 +106,8 @@
#endif
private:
+
+ /// \cond hide_private_members
void init()
{
#ifndef BOOST_NO_STDC_NAMESPACE
@@ -104,6 +117,7 @@
_nmean = log(_mean*_mean/sqrt(_sigma*_sigma + _mean*_mean));
_nsigma = sqrt(log(_sigma*_sigma/_mean/_mean+result_type(1)));
}
+ /// \endcond
RealType _mean, _sigma;
RealType _nmean, _nsigma;
Modified: branches/release/boost/random/mersenne_twister.hpp
==============================================================================
--- branches/release/boost/random/mersenne_twister.hpp (original)
+++ branches/release/boost/random/mersenne_twister.hpp 2010-03-21 20:45:06 EDT (Sun, 21 Mar 2010)
@@ -33,7 +33,34 @@
namespace boost {
namespace random {
-// http://www.math.keio.ac.jp/matumoto/emt.html
+/**
+ * Instantiations of class template mersenne_twister model a
+ * \pseudo_random_number_generator. It uses the algorithm described in
+ *
+ * @blockquote
+ * "Mersenne Twister: A 623-dimensionally equidistributed uniform
+ * pseudo-random number generator", Makoto Matsumoto and Takuji Nishimura,
+ * ACM Transactions on Modeling and Computer Simulation: Special Issue on
+ * Uniform Random Number Generation, Vol. 8, No. 1, January 1998, pp. 3-30.
+ * @endblockquote
+ *
+ * @xmlnote
+ * The boost variant has been implemented from scratch and does not
+ * derive from or use mt19937.c provided on the above WWW site. However, it
+ * was verified that both produce identical output.
+ * @endxmlnote
+ *
+ * The seeding from an integer was changed in April 2005 to address a
+ * weakness.
+ *
+ * The quality of the generator crucially depends on the choice of the
+ * parameters. User code should employ one of the sensibly parameterized
+ * generators such as \mt19937 instead.
+ *
+ * The generator requires considerable amounts of memory for the storage of
+ * its state array. For example, \mt11213b requires about 1408 bytes and
+ * \mt19937 requires about 2496 bytes.
+ */
template<class UIntType, int w, int n, int m, int r, UIntType a, int u,
int s, UIntType b, int t, UIntType c, int l, UIntType val>
class mersenne_twister
@@ -54,19 +81,39 @@
BOOST_STATIC_CONSTANT(bool, has_fixed_range = false);
+ /**
+ * Constructs a @c mersenne_twister and calls @c seed().
+ */
mersenne_twister() { seed(); }
+ /**
+ * Constructs a @c mersenne_twister and calls @c seed(value).
+ */
BOOST_RANDOM_DETAIL_ARITHMETIC_CONSTRUCTOR(mersenne_twister, UIntType, value)
{ seed(value); }
template<class It> mersenne_twister(It& first, It last) { seed(first,last); }
+ /**
+ * Constructs a mersenne_twister and calls @c seed(gen).
+ *
+ * @xmlnote
+ * The copy constructor will always be preferred over
+ * the templated constructor.
+ * @endxmlnote
+ */
BOOST_RANDOM_DETAIL_GENERATOR_CONSTRUCTOR(mersenne_twister, Generator, gen)
{ seed(gen); }
// compiler-generated copy ctor and assignment operator are fine
+ /** Calls @c seed(result_type(5489)). */
void seed() { seed(UIntType(5489)); }
+ /**
+ * Sets the state x(0) to v mod 2w. Then, iteratively,
+ * sets x(i) to (i + 1812433253 * (x(i-1) xor (x(i-1) rshift w-2))) mod 2<sup>w</sup>
+ * for i = 1 .. n-1. x(n) is the first value to be returned by operator().
+ */
BOOST_RANDOM_DETAIL_ARITHMETIC_SEED(mersenne_twister, UIntType, value)
{
// New seeding algorithm from
@@ -81,9 +128,12 @@
}
}
- // 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.
+ /**
+ * Sets the state of this mersenne_twister to the values
+ * returned by n invocations of gen.
+ *
+ * Complexity: Exactly n invocations of gen.
+ */
BOOST_RANDOM_DETAIL_GENERATOR_SEED(mersenne_twister, Generator, gen)
{
#ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
@@ -170,6 +220,7 @@
#endif
private:
+ /// \cond hide_private_members
// returns x(i-n+index), where index is in 0..n-1
UIntType compute(unsigned int index) const
{
@@ -177,6 +228,7 @@
return x[ (i + n + index) % (2*n) ];
}
void twist(int block);
+ /// \endcond
// state representation: next output is o(x(i))
// x[0] ... x[k] x[k+1] ... x[n-1] x[n] ... x[2*n-1] represents
@@ -225,6 +277,7 @@
const int mersenne_twister<UIntType,w,n,m,r,a,u,s,b,t,c,l,val>::output_l;
#endif
+/// \cond hide_private_members
template<class UIntType, int w, int n, int m, int r, UIntType a, int u,
int s, UIntType b, int t, UIntType c, int l, UIntType val>
void mersenne_twister<UIntType,w,n,m,r,a,u,s,b,t,c,l,val>::twist(int block)
@@ -256,6 +309,7 @@
i = 0;
}
}
+/// \endcond
template<class UIntType, int w, int n, int m, int r, UIntType a, int u,
int s, UIntType b, int t, UIntType c, int l, UIntType val>
@@ -278,11 +332,31 @@
} // namespace random
-
+/**
+ * The specializations \mt11213b and \mt19937 are from
+ *
+ * @blockquote
+ * "Mersenne Twister: A 623-dimensionally equidistributed
+ * uniform pseudo-random number generator", Makoto Matsumoto
+ * and Takuji Nishimura, ACM Transactions on Modeling and
+ * Computer Simulation: Special Issue on Uniform Random Number
+ * Generation, Vol. 8, No. 1, January 1998, pp. 3-30.
+ * @endblockquote
+ */
typedef random::mersenne_twister<uint32_t,32,351,175,19,0xccab8ee7,11,
7,0x31b6ab00,15,0xffe50000,17, 0xa37d3c92> mt11213b;
-// validation by experiment from mt19937.c
+/**
+ * The specializations \mt11213b and \mt19937 are from
+ *
+ * @blockquote
+ * "Mersenne Twister: A 623-dimensionally equidistributed
+ * uniform pseudo-random number generator", Makoto Matsumoto
+ * and Takuji Nishimura, ACM Transactions on Modeling and
+ * Computer Simulation: Special Issue on Uniform Random Number
+ * Generation, Vol. 8, No. 1, January 1998, pp. 3-30.
+ * @endblockquote
+ */
typedef random::mersenne_twister<uint32_t,32,624,397,31,0x9908b0df,11,
7,0x9d2c5680,15,0xefc60000,18, 3346425566U> mt19937;
Modified: branches/release/boost/random/normal_distribution.hpp
==============================================================================
--- branches/release/boost/random/normal_distribution.hpp (original)
+++ branches/release/boost/random/normal_distribution.hpp 2010-03-21 20:45:06 EDT (Sun, 21 Mar 2010)
@@ -25,6 +25,13 @@
namespace boost {
+/**
+ * Instantiations of class template normal_distribution model a
+ * \random_distribution. Such a distribution produces random numbers
+ * @c x distributed with probability density function
+ * \f$p(x) = \frac{1}{\sqrt{2\pi\sigma}} e^{-\frac{(x-\mu)^2}{2\sigma^2}}\f$,
+ * where mean and sigma are the parameters of the distribution.
+ */
// deterministic Box-Muller method, uses trigonometric functions
template<class RealType = double>
class normal_distribution
@@ -37,6 +44,12 @@
BOOST_STATIC_ASSERT(!std::numeric_limits<RealType>::is_integer);
#endif
+ /**
+ * Constructs a normal_distribution object. @c mean and @c sigma are
+ * the parameters for the distribution.
+ *
+ * Requires: sigma > 0
+ */
explicit normal_distribution(const result_type& mean_arg = result_type(0),
const result_type& sigma_arg = result_type(1))
: _mean(mean_arg), _sigma(sigma_arg), _valid(false)
@@ -52,7 +65,13 @@
// compiler-generated copy ctor and assignment operator are fine
+ /**
+ * Returns: The "mean" parameter of the distribution.
+ */
RealType mean() const { return _mean; }
+ /**
+ * Returns: The "sigma" parameter of the distribution.
+ */
RealType sigma() const { return _sigma; }
void reset() { _valid = false; }
Modified: branches/release/boost/random/poisson_distribution.hpp
==============================================================================
--- branches/release/boost/random/poisson_distribution.hpp (original)
+++ branches/release/boost/random/poisson_distribution.hpp 2010-03-21 20:45:06 EDT (Sun, 21 Mar 2010)
@@ -24,6 +24,12 @@
namespace boost {
// Knuth
+
+/**
+ * An instantiation of the class template @c poisson_distribution is a
+ * model of \random_distribution. The poisson distribution has
+ * \f$p(i) = \frac{e^{-\lambda}\lambda^i}{i!}\f$
+ */
template<class IntType = int, class RealType = double>
class poisson_distribution
{
@@ -31,6 +37,11 @@
typedef RealType input_type;
typedef IntType result_type;
+ /**
+ * Constructs a @c poisson_distribution with the parameter @c mean.
+ *
+ * Requires: mean > 0
+ */
explicit poisson_distribution(const RealType& mean_arg = RealType(1))
: _mean(mean_arg)
{
@@ -46,6 +57,9 @@
// compiler-generated copy ctor and assignment operator are fine
+ /**
+ * Returns: the "mean" parameter of the distribution.
+ */
RealType mean() const { return _mean; }
void reset() { }
@@ -81,6 +95,7 @@
#endif
private:
+ /// \cond hide_private_members
void init()
{
#ifndef BOOST_NO_STDC_NAMESPACE
@@ -89,6 +104,7 @@
#endif
_exp_mean = exp(-_mean);
}
+ /// \endcond
RealType _mean;
// some precomputed data from the parameters
Modified: branches/release/boost/random/random_number_generator.hpp
==============================================================================
--- branches/release/boost/random/random_number_generator.hpp (original)
+++ branches/release/boost/random/random_number_generator.hpp 2010-03-21 20:45:06 EDT (Sun, 21 Mar 2010)
@@ -24,7 +24,14 @@
namespace boost {
-// a model for RandomNumberGenerator std:25.2.11 [lib.alg.random.shuffle]
+/**
+ * Instantiations of class template random_number_generator model a
+ * RandomNumberGenerator (std:25.2.11 [lib.alg.random.shuffle]). On
+ * each invocation, it returns a uniformly distributed integer in
+ * the range [0..n).
+ *
+ * The template parameter IntType shall denote some integer-like value type.
+ */
template<class UniformRandomNumberGenerator, class IntType = long>
class random_number_generator
{
@@ -32,6 +39,11 @@
typedef UniformRandomNumberGenerator base_type;
typedef IntType argument_type;
typedef IntType result_type;
+ /**
+ * Constructs a random_number_generator functor with the given
+ * \uniform_random_number_generator as the underlying source of
+ * random numbers.
+ */
random_number_generator(base_type& rng) : _rng(rng)
{
#ifndef BOOST_NO_LIMITS_COMPILE_TIME_CONSTANTS
@@ -41,6 +53,9 @@
// compiler-generated copy ctor is fine
// assignment is disallowed because there is a reference member
+ /**
+ * Returns a value in the range [0, n)
+ */
result_type operator()(argument_type n)
{
typedef uniform_int<IntType> dist_type;
Modified: branches/release/boost/random/ranlux.hpp
==============================================================================
--- branches/release/boost/random/ranlux.hpp (original)
+++ branches/release/boost/random/ranlux.hpp 2010-03-21 20:45:06 EDT (Sun, 21 Mar 2010)
@@ -28,20 +28,51 @@
typedef subtract_with_carry_01<double, 48, 10, 24> ranlux64_base_01;
}
+namespace random {
+namespace detail {
+/**
+ * The ranlux family of generators are described in
+ *
+ * @blockquote
+ * "A portable high-quality random number generator for lattice field theory
+ * calculations", M. Luescher, Computer Physics Communications, 79 (1994)
+ * pp 100-110.
+ * @endblockquote
+ *
+ * The levels are given in
+ *
+ * @blockquote
+ * "RANLUX: A Fortran implementation ofthe high-quality
+ * pseudorandom number generator of Luescher", F. James,
+ * Computer Physics Communications 79 (1994) 111-114
+ * @endblockquote
+ */
+class ranlux_documentation {};
+}
+}
+
+/** @copydoc boost::random::detail::ranlux_documentation */
typedef random::discard_block<random::ranlux_base, 223, 24> ranlux3;
+/** @copydoc boost::random::detail::ranlux_documentation */
typedef random::discard_block<random::ranlux_base, 389, 24> ranlux4;
+/** @copydoc boost::random::detail::ranlux_documentation */
typedef random::discard_block<random::ranlux_base_01, 223, 24> ranlux3_01;
+/** @copydoc boost::random::detail::ranlux_documentation */
typedef random::discard_block<random::ranlux_base_01, 389, 24> ranlux4_01;
+/** @copydoc boost::random::detail::ranlux_documentation */
typedef random::discard_block<random::ranlux64_base_01, 223, 24> ranlux64_3_01;
+/** @copydoc boost::random::detail::ranlux_documentation */
typedef random::discard_block<random::ranlux64_base_01, 389, 24> ranlux64_4_01;
#if !defined(BOOST_NO_INT64_T) && !defined(BOOST_NO_INTEGRAL_INT64_T)
namespace random {
typedef random::subtract_with_carry<int64_t, (int64_t(1)<<48), 10, 24, 0> ranlux64_base;
}
+/** @copydoc boost::random::detail::ranlux_documentation */
typedef random::discard_block<random::ranlux64_base, 223, 24> ranlux64_3;
+/** @copydoc boost::random::detail::ranlux_documentation */
typedef random::discard_block<random::ranlux64_base, 389, 24> ranlux64_4;
#endif /* !BOOST_NO_INT64_T && !BOOST_NO_INTEGRAL_INT64_T */
Modified: branches/release/boost/random/shuffle_output.hpp
==============================================================================
--- branches/release/boost/random/shuffle_output.hpp (original)
+++ branches/release/boost/random/shuffle_output.hpp 2010-03-21 20:45:06 EDT (Sun, 21 Mar 2010)
@@ -28,7 +28,30 @@
namespace boost {
namespace random {
-// Carter Bays and S.D. Durham 1979
+/**
+ * Instatiations of class template shuffle_output model a
+ * \pseudo_random_number_generator. It mixes the output
+ * of some (usually \linear_congruential) \uniform_random_number_generator
+ * to get better statistical properties.
+ * The algorithm is described in
+ *
+ * @blockquote
+ * "Improving a poor random number generator", Carter Bays
+ * and S.D. Durham, ACM Transactions on Mathematical Software,
+ * Vol 2, No. 1, March 1976, pp. 59-64.
+ * http://doi.acm.org/10.1145/355666.355670
+ * @endblockquote
+ *
+ * The output of the base generator is buffered in an array of
+ * length k. Every output X(n) has a second role: It gives an
+ * index into the array where X(n+1) will be retrieved. Used
+ * array elements are replaced with fresh output from the base
+ * generator.
+ *
+ * Template parameters are the base generator and the array
+ * length k, which should be around 100. The template parameter
+ * val is the validation value checked by validation.
+ */
template<class UniformRandomNumberGenerator, int k,
#ifndef BOOST_NO_DEPENDENT_TYPES_IN_TEMPLATE_VALUE_PARAMETERS
typename UniformRandomNumberGenerator::result_type
@@ -45,18 +68,45 @@
BOOST_STATIC_CONSTANT(bool, has_fixed_range = false);
BOOST_STATIC_CONSTANT(int, buffer_size = k);
+ /**
+ * Constructs a @c shuffle_output generator by invoking the
+ * default constructor of the base generator.
+ *
+ * Complexity: Exactly k+1 invocations of the base generator.
+ */
shuffle_output() : _rng() { init(); }
#if defined(BOOST_MSVC) && _MSC_VER < 1300
// MSVC does not implicitly generate the copy constructor here
shuffle_output(const shuffle_output & x)
: _rng(x._rng), y(x.y) { std::copy(x.v, x.v+k, v); }
#endif
+ /**
+ * Constructs a shuffle_output generator by invoking the one-argument
+ * constructor of the base generator with the parameter seed.
+ *
+ * Complexity: Exactly k+1 invocations of the base generator.
+ */
template<class T>
explicit shuffle_output(T s) : _rng(s) { init(); }
+ /**
+ * Constructs a shuffle_output generator by using a copy
+ * of the provided generator.
+ *
+ * Precondition: The template argument UniformRandomNumberGenerator
+ * shall denote a CopyConstructible type.
+ *
+ * Complexity: Exactly k+1 invocations of the base generator.
+ */
explicit shuffle_output(const base_type & rng) : _rng(rng) { init(); }
template<class It> shuffle_output(It& first, It last)
: _rng(first, last) { init(); }
void seed() { _rng.seed(); init(); }
+ /**
+ * Invokes the one-argument seed method of the base generator
+ * with the parameter seed and re-initializes the internal buffer array.
+ *
+ * Complexity: Exactly k+1 invocations of the base generator.
+ */
template<class T>
void seed(T s) { _rng.seed(s); init(); }
template<class It> void seed(It& first, It last)
@@ -165,6 +215,15 @@
} // namespace random
// validation by experiment from Harry Erwin's generator.h (private e-mail)
+/**
+ * According to Harry Erwin (private e-mail), the specialization
+ * @c kreutzer1986 was suggested in:
+ *
+ * @blockquote
+ * "System Simulation: Programming Styles and Languages (International
+ * Computer Science Series)", Wolfgang Kreutzer, Addison-Wesley, December 1986.
+ * @endblockquote
+ */
typedef random::shuffle_output<
random::linear_congruential<uint32_t, 1366, 150889, 714025, 0>,
97, 139726> kreutzer1986;
Modified: branches/release/boost/random/subtract_with_carry.hpp
==============================================================================
--- branches/release/boost/random/subtract_with_carry.hpp (original)
+++ branches/release/boost/random/subtract_with_carry.hpp 2010-03-21 20:45:06 EDT (Sun, 21 Mar 2010)
@@ -62,10 +62,19 @@
carry = value / modulus;
}
}
-# endif
-// subtract-with-carry generator
-// Marsaglia and Zaman
+# endif
+/**
+ * Instantiations of @c subtract_with_carry model a
+ * \pseudo_random_number_generator. The algorithm is
+ * described in
+ *
+ * @blockquote
+ * "A New Class of Random Number Generators", George
+ * Marsaglia and Arif Zaman, Annals of Applied Probability,
+ * Volume 1, Number 3 (1991), 462-480.
+ * @endblockquote
+ */
template<class IntType, IntType m, unsigned int s, unsigned int r,
IntType val>
class subtract_with_carry
@@ -205,11 +214,13 @@
#endif
private:
+ /// \cond hide_private_members
// returns x(i-r+index), where index is in 0..r-1
IntType compute(unsigned int index) const
{
return x[(k+index) % long_lag];
}
+ /// \endcond
// state representation; next output (state) is x(i)
// x[0] ... x[k] x[k+1] ... x[long_lag-1] represents
@@ -248,6 +259,7 @@
// use a floating-point representation to produce values in [0..1)
+/** @copydoc boost::random::subtract_with_carry */
template<class RealType, int w, unsigned int s, unsigned int r, int val=0>
class subtract_with_carry_01
{
@@ -269,6 +281,7 @@
{ init_modulus(); seed(first,last); }
private:
+ /// \cond hide_private_members
void init_modulus()
{
#ifndef BOOST_NO_STDC_NAMESPACE
@@ -277,6 +290,7 @@
#endif
_modulus = pow(RealType(2), word_size);
}
+ /// \endcond hide_private_members
public:
// compiler-generated copy ctor and assignment operator are fine
@@ -416,7 +430,9 @@
#endif
private:
+ /// \cond hide_private_members
RealType compute(unsigned int index) const;
+ /// \endcond
unsigned int k;
RealType carry;
RealType x[long_lag];
@@ -435,12 +451,13 @@
const unsigned int subtract_with_carry_01<RealType, w, s, r, val>::short_lag;
#endif
+/// \cond hide_private_members
template<class RealType, int w, unsigned int s, unsigned int r, int val>
RealType subtract_with_carry_01<RealType, w, s, r, val>::compute(unsigned int index) const
{
return x[(k+index) % long_lag];
}
-
+/// \endcond
} // namespace random
} // namespace boost
Modified: branches/release/boost/random/triangle_distribution.hpp
==============================================================================
--- branches/release/boost/random/triangle_distribution.hpp (original)
+++ branches/release/boost/random/triangle_distribution.hpp 2010-03-21 20:45:06 EDT (Sun, 21 Mar 2010)
@@ -23,8 +23,12 @@
namespace boost {
-// triangle distribution, with a smallest, b most probable, and c largest
-// value.
+/**
+ * Instantiations of @c triangle_distribution model a \random_distribution.
+ * A @c triangle_distribution has three parameters, @c a, @c b, and @c c,
+ * which are the smallest, the most probable and the largest values of
+ * the distribution respectively.
+ */
template<class RealType = double>
class triangle_distribution
{
@@ -32,6 +36,12 @@
typedef RealType input_type;
typedef RealType result_type;
+ /**
+ * Constructs a @c triangle_distribution with the parameters
+ * @c a, @c b, and @c c.
+ *
+ * Preconditions: a <= b <= c.
+ */
explicit triangle_distribution(result_type a_arg = result_type(0),
result_type b_arg = result_type(0.5),
result_type c_arg = result_type(1))
@@ -42,8 +52,12 @@
}
// compiler-generated copy ctor and assignment operator are fine
+
+ /** Returns the @c a parameter of the distribution */
result_type a() const { return _a; }
+ /** Returns the @c b parameter of the distribution */
result_type b() const { return _b; }
+ /** Returns the @c c parameter of the distribution */
result_type c() const { return _c; }
void reset() { }
@@ -81,6 +95,7 @@
#endif
private:
+ /// \cond hide_private_members
void init()
{
#ifndef BOOST_NO_STDC_NAMESPACE
@@ -92,6 +107,7 @@
q1 = d1 / d2;
p1 = sqrt(d1 * d2);
}
+ /// \endcond
result_type _a, _b, _c;
result_type d1, d2, d3, q1, p1;
Modified: branches/release/boost/random/uniform_01.hpp
==============================================================================
--- branches/release/boost/random/uniform_01.hpp (original)
+++ branches/release/boost/random/uniform_01.hpp 2010-03-21 20:45:06 EDT (Sun, 21 Mar 2010)
@@ -27,6 +27,53 @@
namespace boost {
+#ifdef BOOST_RANDOM_DOXYGEN
+
+/**
+ * The distribution function uniform_01 models a \random_distribution.
+ * On each invocation, it returns a random floating-point value
+ * uniformly distributed in the range [0..1).
+ *
+ * The template parameter RealType shall denote a float-like value type
+ * with support for binary operators +, -, and /.
+ *
+ * Note: The current implementation is buggy, because it may not fill
+ * all of the mantissa with random bits. I'm unsure how to fill a
+ * (to-be-invented) @c boost::bigfloat class with random bits efficiently.
+ * It's probably time for a traits class.
+ */
+template<class RealType = double>
+class uniform_01
+{
+public:
+ typedef RealType input_type;
+ typedef RealType result_type;
+ result_type min BOOST_PREVENT_MACRO_SUBSTITUTION () const;
+ result_type max BOOST_PREVENT_MACRO_SUBSTITUTION () const;
+ void reset();
+
+ template<class Engine>
+ result_type operator()(Engine& eng);
+
+#ifndef BOOST_RANDOM_NO_STREAM_OPERATORS
+ template<class CharT, class Traits>
+ friend std::basic_ostream<CharT,Traits>&
+ operator<<(std::basic_ostream<CharT,Traits>& os, const new_uniform_01&)
+ {
+ return os;
+ }
+
+ template<class CharT, class Traits>
+ friend std::basic_istream<CharT,Traits>&
+ operator>>(std::basic_istream<CharT,Traits>& is, new_uniform_01&)
+ {
+ return is;
+ }
+#endif
+};
+
+#else
+
namespace detail {
template<class RealType>
@@ -217,6 +264,8 @@
#endif
};
+#endif
+
} // namespace boost
#include <boost/random/detail/enable_warnings.hpp>
Modified: branches/release/boost/random/uniform_int.hpp
==============================================================================
--- branches/release/boost/random/uniform_int.hpp (original)
+++ branches/release/boost/random/uniform_int.hpp 2010-03-21 20:45:06 EDT (Sun, 21 Mar 2010)
@@ -29,15 +29,30 @@
namespace boost {
-// uniform integer distribution on [min, max]
+/**
+ * The distribution function uniform_int models a \random_distribution.
+ * On each invocation, it returns a random integer value uniformly
+ * distributed in the set of integer numbers {min, min+1, min+2, ..., max}.
+ *
+ * The template parameter IntType shall denote an integer-like value type.
+ */
template<class IntType = int>
class uniform_int
{
public:
typedef IntType input_type;
typedef IntType result_type;
+
+ /// \cond hide_private_members
typedef typename make_unsigned<result_type>::type range_type;
+ /// \endcond
+ /**
+ * Constructs a uniform_int object. @c min and @c max are
+ * the parameters of the distribution.
+ *
+ * Requires: min <= max
+ */
explicit uniform_int(IntType min_arg = 0, IntType max_arg = 9)
: _min(min_arg), _max(max_arg)
{
@@ -49,7 +64,13 @@
init();
}
+ /**
+ * Returns: The "min" parameter of the distribution
+ */
result_type min BOOST_PREVENT_MACRO_SUBSTITUTION () const { return _min; }
+ /**
+ * Returns: The "max" parameter of the distribution
+ */
result_type max BOOST_PREVENT_MACRO_SUBSTITUTION () const { return _max; }
void reset() { }
@@ -93,6 +114,15 @@
#endif
private:
+
+#ifdef BOOST_MSVC
+#pragma warning(push)
+// disable division by zero warning, since we can't
+// actually divide by zero.
+#pragma warning(disable:4723)
+#endif
+
+ /// \cond hide_private_members
template<class Engine>
static result_type generate(Engine& eng, result_type min_value, result_type /*max_value*/, range_type range)
{
@@ -248,11 +278,17 @@
}
}
+#ifdef BOOST_MSVC
+#pragma warning(pop)
+#endif
+
void init()
{
_range = random::detail::subtract<result_type>()(_max, _min);
}
+ /// \endcond
+
// The result_type may be signed or unsigned, but the _range is always
// unsigned.
result_type _min, _max;
Modified: branches/release/boost/random/uniform_on_sphere.hpp
==============================================================================
--- branches/release/boost/random/uniform_on_sphere.hpp (original)
+++ branches/release/boost/random/uniform_on_sphere.hpp 2010-03-21 20:45:06 EDT (Sun, 21 Mar 2010)
@@ -24,6 +24,16 @@
namespace boost {
+/**
+ * Instantiations of class template uniform_on_sphere model a
+ * \random_distribution. Such a distribution produces random
+ * numbers uniformly distributed on the unit sphere of arbitrary
+ * dimension @c dim. The @c Cont template parameter must be a STL-like
+ * container type with begin and end operations returning non-const
+ * ForwardIterators of type @c Cont::iterator. Each invocation of the
+ * @c UniformRandomNumberGenerator shall result in a floating-point
+ * value in the range [0,1).
+ */
template<class RealType = double, class Cont = std::vector<RealType> >
class uniform_on_sphere
{
@@ -31,6 +41,10 @@
typedef RealType input_type;
typedef Cont result_type;
+ /**
+ * Constructs a @c uniform_on_sphere distribution.
+ * @c dim is the dimension of the sphere.
+ */
explicit uniform_on_sphere(int dim = 2) : _container(dim), _dim(dim) { }
// compiler-generated copy ctor and assignment operator are fine
Modified: branches/release/boost/random/uniform_real.hpp
==============================================================================
--- branches/release/boost/random/uniform_real.hpp (original)
+++ branches/release/boost/random/uniform_real.hpp 2010-03-21 20:45:06 EDT (Sun, 21 Mar 2010)
@@ -26,7 +26,17 @@
namespace boost {
-// uniform distribution on a real range
+/**
+ * The distribution function uniform_real models a random distribution.
+ * On each invocation, it returns a random floating-point value uniformly
+ * distributed in the range [min..max). The value is computed using
+ * std::numeric_limits<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.
+ */
template<class RealType = double>
class uniform_real
{
@@ -34,6 +44,12 @@
typedef RealType input_type;
typedef RealType result_type;
+ /**
+ * Constructs a uniform_real object. @c min and @c max are the
+ * parameters of the distribution.
+ *
+ * Requires: min <= max
+ */
explicit uniform_real(RealType min_arg = RealType(0),
RealType max_arg = RealType(1))
: _min(min_arg), _max(max_arg)
@@ -46,7 +62,13 @@
// compiler-generated copy ctor and assignment operator are fine
+ /**
+ * Returns: The "min" parameter of the distribution
+ */
result_type min BOOST_PREVENT_MACRO_SUBSTITUTION () const { return _min; }
+ /**
+ * Returns: The "max" parameter of the distribution
+ */
result_type max BOOST_PREVENT_MACRO_SUBSTITUTION () const { return _max; }
void reset() { }
Modified: branches/release/boost/random/uniform_smallint.hpp
==============================================================================
--- branches/release/boost/random/uniform_smallint.hpp (original)
+++ branches/release/boost/random/uniform_smallint.hpp 2010-03-21 20:45:06 EDT (Sun, 21 Mar 2010)
@@ -30,6 +30,52 @@
// uniform integer distribution on a small range [min, max]
+/**
+ * The distribution function uniform_smallint models a \random_distribution.
+ * On each invocation, it returns a random integer value uniformly distributed
+ * in the set of integer numbers {min, min+1, min+2, ..., max}. It assumes
+ * that the desired range (max-min+1) is small compared to the range of the
+ * underlying source of random numbers and thus makes no attempt to limit
+ * quantization errors.
+ *
+ * Let r<sub>out</sub>=(max-min+1) the desired range of integer numbers, and
+ * let r<sub>base</sub> 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 r<sub>out</sub> will be p<sub>out</sub>(i) =
+ * 1/r<sub>out</sub>. Likewise, assume a uniform distribution on r<sub>base</sub> for
+ * the underlying source of random numbers, i.e. p<sub>base</sub>(i) =
+ * 1/r<sub>base</sub>. Let p<sub>out_s</sub>(i) denote the random
+ * distribution generated by @c uniform_smallint. Then the sum over all
+ * i in r<sub>out</sub> of (p<sub>out_s</sub>(i)/p<sub>out</sub>(i) - 1)<sup>2</sup>
+ * shall not exceed r<sub>out</sub>/r<sub>base</sub><sup>2</sup>
+ * (r<sub>base</sub> mod r<sub>out</sub>)(r<sub>out</sub> -
+ * r<sub>base</sub> mod r<sub>out</sub>).
+ *
+ * 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
+ * p<sub>out</sub>(i) and the generated distribution p<sub>out_s</sub>(i).
+ * The property can be fulfilled with the calculation
+ * (base_rng mod r<sub>out</sub>), as follows: Let r = r<sub>base</sub> mod
+ * r<sub>out</sub>. The base distribution on r<sub>base</sub> is folded onto the
+ * range r<sub>out</sub>. The numbers i < r have assigned (r<sub>base</sub>
+ * div r<sub>out</sub>)+1 numbers of the base distribution, the rest has
+ * only (r<sub>base</sub> div r<sub>out</sub>). Therefore,
+ * p<sub>out_s</sub>(i) = ((r<sub>base</sub> div r<sub>out</sub>)+1) /
+ * r<sub>base</sub> for i < r and p<sub>out_s</sub>(i) = (r<sub>base</sub>
+ * div r<sub>out</sub>)/r<sub>base</sub> otherwise. Substituting this in the
+ * above sum formula leads to the desired result.
+ *
+ * Note: The upper bound for (r<sub>base</sub> mod r<sub>out</sub>)
+ * (r<sub>out</sub> - r<sub>base</sub> mod r<sub>out</sub>) is
+ * r<sub>out</sub><sup>2</sup>/4. Regarding the upper bound for the
+ * square sum of the relative quantization error of
+ * r<sub>out</sub><sup>3</sup>/(4*r<sub>base</sub><sup>2</sup>), it
+ * seems wise to either choose r<sub>base</sub> so that r<sub>base</sub> >
+ * 10*r<sub>out</sub><sup>2</sup> or ensure that r<sub>base</sub> is
+ * divisible by r<sub>out</sub>.
+ */
template<class IntType = int>
class uniform_smallint
{
@@ -37,6 +83,10 @@
typedef IntType input_type;
typedef IntType result_type;
+ /**
+ * Constructs a @c uniform_smallint. @c min and @c max are the
+ * lower and upper bounds of the output range, respectively.
+ */
explicit uniform_smallint(IntType min_arg = 0, IntType max_arg = 9)
: _min(min_arg), _max(max_arg)
{
@@ -76,7 +126,7 @@
r_base /= 2;
}
- return ((eng() - (eng.min)()) / _factor) % _range + _min;
+ return static_cast<result_type>(((eng() - (eng.min)()) / _factor) % _range + _min);
}
#ifndef BOOST_RANDOM_NO_STREAM_OPERATORS
Modified: branches/release/boost/random/variate_generator.hpp
==============================================================================
--- branches/release/boost/random/variate_generator.hpp (original)
+++ branches/release/boost/random/variate_generator.hpp 2010-03-21 20:45:06 EDT (Sun, 21 Mar 2010)
@@ -33,6 +33,8 @@
namespace boost {
+/// \cond hide_private_members
+
namespace random {
namespace detail {
@@ -83,7 +85,31 @@
} // namespace detail
} // namespace random
+///\endcond
+/**
+ * A random variate generator is used to join a random number
+ * generator together with a random number distribution.
+ * Boost.Random provides a vast choice of \generators as well
+ * as \distributions.
+ *
+ * Instantations of class template @c variate_generator model
+ * a \number_generator.
+ *
+ * The argument for the template parameter Engine shall be of
+ * the form U, U&, or U*, where U models a
+ * \uniform_random_number_generator. Then, the member
+ * engine_value_type names U (not the pointer or reference to U).
+ *
+ * Specializations of @c variate_generator satisfy the
+ * requirements of CopyConstructible. They also satisfy the
+ * requirements of Assignable unless the template parameter
+ * Engine is of the form U&.
+ *
+ * The complexity of all functions specified in this section
+ * is constant. No function described in this section except
+ * the constructor throws an exception.
+ */
template<class Engine, class Distribution>
class variate_generator
{
@@ -96,27 +122,84 @@
typedef Distribution distribution_type;
typedef typename Distribution::result_type result_type;
+ /**
+ * Constructs a @c variate_generator object with the associated
+ * \uniform_random_number_generator eng and the associated
+ * \random_distribution d.
+ *
+ * Throws: If and what the copy constructor of Engine or
+ * Distribution throws.
+ */
variate_generator(Engine e, Distribution d)
: _eng(decorated_engine(e)), _dist(d) { }
+ /**
+ * Returns: distribution()(e)
+ *
+ * Notes: The sequence of numbers produced by the
+ * \uniform_random_number_generator e, s<sub>e</sub>, is
+ * obtained from the sequence of numbers produced by the
+ * associated \uniform_random_number_generator eng, s<sub>eng</sub>,
+ * as follows: Consider the values of @c numeric_limits<T>::is_integer
+ * for @c T both @c Distribution::input_type and
+ * @c engine_value_type::result_type. If the values for both types are
+ * true, then se is identical to s<sub>eng</sub>. Otherwise, if the
+ * values for both types are false, then the numbers in s<sub>eng</sub>
+ * are divided by engine().max()-engine().min() to obtain the numbers
+ * in s<sub>e</sub>. Otherwise, if the value for
+ * @c engine_value_type::result_type is true and the value for
+ * @c Distribution::input_type is false, then the numbers in s<sub>eng</sub>
+ * are divided by engine().max()-engine().min()+1 to obtain the numbers in
+ * s<sub>e</sub>. Otherwise, the mapping from s<sub>eng</sub> to
+ * s<sub>e</sub> is implementation-defined. In all cases, an
+ * implicit conversion from @c engine_value_type::result_type to
+ * @c Distribution::input_type is performed. If such a conversion does
+ * not exist, the program is ill-formed.
+ */
result_type operator()() { return _dist(_eng); }
+ /**
+ * Returns: distribution()(e, value).
+ * For the semantics of e, see the description of operator()().
+ */
template<class T>
result_type operator()(T value) { return _dist(_eng, value); }
+ /**
+ * Returns: A reference to the associated uniform random number generator.
+ */
engine_value_type& engine() { return _eng.base().base(); }
+ /**
+ * Returns: A reference to the associated uniform random number generator.
+ */
const engine_value_type& engine() const { return _eng.base().base(); }
+ /**
+ * Returns: A reference to the associated random distribution.
+ */
distribution_type& distribution() { return _dist; }
+ /**
+ * Returns: A reference to the associated random distribution.
+ */
const distribution_type& distribution() const { return _dist; }
+ /**
+ * Precondition: distribution().min() is well-formed
+ *
+ * Returns: distribution().min()
+ */
result_type min BOOST_PREVENT_MACRO_SUBSTITUTION () const { return (distribution().min)(); }
+ /**
+ * Precondition: distribution().max() is well-formed
+ *
+ * Returns: distribution().max()
+ */
result_type max BOOST_PREVENT_MACRO_SUBSTITUTION () const { return (distribution().max)(); }
private:
#if BOOST_WORKAROUND(__BORLANDC__, <= 0x564)
typedef typename random::detail::engine_helper<
- boost::is_integral<typename decorated_engine::result_type>::value,
- boost::is_integral<typename Distribution::input_type>::value
+ ::boost::is_integral<typename decorated_engine::result_type>::value,
+ ::boost::is_integral<typename Distribution::input_type>::value
>::BOOST_NESTED_TEMPLATE impl<decorated_engine, typename Distribution::input_type>::type internal_engine_type;
#else
enum {
Modified: branches/release/boost/random/xor_combine.hpp
==============================================================================
--- branches/release/boost/random/xor_combine.hpp (original)
+++ branches/release/boost/random/xor_combine.hpp 2010-03-21 20:45:06 EDT (Sun, 21 Mar 2010)
@@ -27,13 +27,24 @@
namespace boost {
namespace random {
+/// \cond hide_private_members
#ifndef BOOST_NO_DEPENDENT_TYPES_IN_TEMPLATE_VALUE_PARAMETERS
#define BOOST_RANDOM_VAL_TYPE typename URNG1::result_type
#else
#define BOOST_RANDOM_VAL_TYPE uint32_t
#endif
+/// \endcond
-template<class URNG1, int s1, class URNG2, int s2, BOOST_RANDOM_VAL_TYPE val = 0>
+/**
+ * Instantiations of @c xor_combine model a \pseudo_random_number_generator.
+ * To produce its output it invokes each of the base generators, shifts
+ * their results and xors them together.
+ */
+template<class URNG1, int s1, class URNG2, int s2
+#ifndef BOOST_RANDOM_DOXYGEN
+, BOOST_RANDOM_VAL_TYPE val = 0
+#endif
+>
class xor_combine
{
public:
@@ -45,25 +56,58 @@
BOOST_STATIC_CONSTANT(int, shift1 = s1);
BOOST_STATIC_CONSTANT(int, shift2 = s2);
+ /**
+ * Constructors a @c xor_combine by default constructing
+ * both base generators.
+ */
xor_combine() : _rng1(), _rng2()
{ }
+ /**
+ * Constructs a @c xor_combine by copying two base generators.
+ */
xor_combine(const base1_type & rng1, const base2_type & rng2)
: _rng1(rng1), _rng2(rng2) { }
+ /**
+ * Constructs a @c xor_combine, seeding both base generators
+ * with @c v.
+ */
xor_combine(const result_type & v)
: _rng1(v), _rng2(v) { }
+ /**
+ * Constructs a @c xor_combine, seeding both base generators
+ * with values from the iterator range [first, last) and changes
+ * first to point to the element after the last one used. If there
+ * are not enough elements in the range to seed both generators,
+ * throws @c std::invalid_argument.
+ */
template<class It> xor_combine(It& first, It last)
: _rng1(first, last), _rng2( /* advanced by other call */ first, last) { }
+ /**
+ * Calls @c seed() for both base generators.
+ */
void seed() { _rng1.seed(); _rng2.seed(); }
+ /**
+ * @c seeds both base generators with @c v.
+ */
void seed(const result_type & v) { _rng1.seed(v); _rng2.seed(v); }
+ /**
+ * seeds both base generators with values from the iterator
+ * range [first, last) and changes first to point to the element
+ * after the last one used. If there are not enough elements in
+ * the range to seed both generators, throws @c std::invalid_argument.
+ */
template<class It> void seed(It& first, It last)
{
_rng1.seed(first, last);
_rng2.seed(first, last);
}
+ /** Returns the first base generator. */
const base1_type& base1() { return _rng1; }
+ /** Returns the second base generator. */
const base2_type& base2() { return _rng2; }
+ /** Returns the next value of the generator. */
result_type operator()()
{
// MSVC fails BOOST_STATIC_ASSERT with std::numeric_limits at class scope
@@ -75,7 +119,13 @@
return (_rng1() << s1) ^ (_rng2() << s2);
}
+ /**
+ * Returns the smallest value that the generator can produce.
+ */
result_type min BOOST_PREVENT_MACRO_SUBSTITUTION () const { return std::min BOOST_PREVENT_MACRO_SUBSTITUTION((_rng1.min)(), (_rng2.min)()); }
+ /**
+ * Returns the largest value that the generator can produce.
+ */
result_type max BOOST_PREVENT_MACRO_SUBSTITUTION () const { return std::max BOOST_PREVENT_MACRO_SUBSTITUTION((_rng1.min)(), (_rng2.max)()); }
static bool validation(result_type x) { return val == x; }
Modified: branches/release/doc/Jamfile.v2
==============================================================================
--- branches/release/doc/Jamfile.v2 (original)
+++ branches/release/doc/Jamfile.v2 2010-03-21 20:45:06 EDT (Sun, 21 Mar 2010)
@@ -49,6 +49,7 @@
<dependency>../libs/unordered/doc//unordered
<dependency>../libs/thread/doc//thread
<dependency>../libs/signals2/doc//hello_world_def_code_snippet.xml
+ <dependency>../libs/random/doc//random
## Add path references to the QuickBook generated docs...
@@ -71,6 +72,7 @@
<implicit-dependency>../libs/unordered/doc//unordered
<implicit-dependency>../libs/thread/doc//thread
<implicit-dependency>../libs/signals2/doc//hello_world_def_code_snippet.xml
+ <implicit-dependency>../libs/random/doc//random
<xsl:param>boost.libraries=../../libs/libraries.htm
Modified: branches/release/doc/src/boost.xml
==============================================================================
--- branches/release/doc/src/boost.xml (original)
+++ branches/release/doc/src/boost.xml 2010-03-21 20:45:06 EDT (Sun, 21 Mar 2010)
@@ -551,16 +551,7 @@
</libraryinfo>
</library>
- <library name="Random" dirname="random" html-only="1">
- <libraryinfo>
- <author>
- <firstname>Jens</firstname>
- <surname>Maurer</surname>
- </author>
- <librarypurpose>A complete system for random number generation</librarypurpose>
- <librarycategory name="category:math"/>
- </libraryinfo>
- </library>
+ <xi:include href="random.xml"/>
<library name="Rational" dirname="rational" html-only="1">
<libraryinfo>
Copied: branches/release/libs/random/doc/Jamfile.v2 (from r59910, /trunk/libs/random/doc/Jamfile.v2)
==============================================================================
--- /trunk/libs/random/doc/Jamfile.v2 (original)
+++ branches/release/libs/random/doc/Jamfile.v2 2010-03-21 20:45:06 EDT (Sun, 21 Mar 2010)
@@ -3,7 +3,7 @@
# Copyright (c) 2009
# Steven Watanabe
#
-# Distributed under the Boost Sofware License, Version 1.0. (See
+# Distributed under the Boost Software License, Version 1.0. (See
# accompanying file LICENSE_1_0.txt or copy at
# http://www.boost.org/LICENSE_1_0.txt)
@@ -12,6 +12,7 @@
import boostbook ;
import regex ;
import os ;
+import path ;
doxygen_files =
additive_combine
@@ -44,13 +45,21 @@
xor_combine
;
-# temporary hack for local docs
-local BOOST_ROOT = ../../../.. ;
+path-constant here : . ;
+path-constant boost-root : ../../.. ;
+
+# Figure out where the root of the boost tree is relative
+# to the html directory.
+local BOOST_ROOT = [ path.relative-to
+ [ path.join [ path.pwd ] html ]
+ [ path.root
+ [ path.make $(boost-root) ]
+ [ path.pwd ] ] ] ;
doxygen reference :
- ../../../boost/random/$(doxygen_files).hpp
- ../../../boost/nondet_random.hpp
- ../../../boost/random.hpp
+ $(here)/../../../boost/random/$(doxygen_files).hpp
+ $(here)/../../../boost/nondet_random.hpp
+ $(here)/../../../boost/random.hpp
:
<doxygen:param>EXPAND_ONLY_PREDEF=YES
<doxygen:param>"ALIASES= \\
@@ -102,7 +111,7 @@
<doxygen:xml-imagedir>images/random
;
-xml random : random.qbk ;
+xml random : random.qbk : <dependency>reference ;
boostbook standalone :
random
Copied: branches/release/libs/random/doc/concepts.qbk (from r59910, /trunk/libs/random/doc/concepts.qbk)
==============================================================================
--- /trunk/libs/random/doc/concepts.qbk (original)
+++ branches/release/libs/random/doc/concepts.qbk 2010-03-21 20:45:06 EDT (Sun, 21 Mar 2010)
@@ -1,3 +1,11 @@
+[/
+ / Copyright (c) 2009 Steven Watanabe
+ /
+ / Distributed under the Boost Software License, Version 1.0. (See
+ / accompanying file LICENSE_1_0.txt or copy at
+ / http://www.boost.org/LICENSE_1_0.txt)
+]
+
[section Introduction]
Random numbers are required in a number of different problem domains, such as
Copied: branches/release/libs/random/doc/distribution_performance_linux.qbk (from r59910, /trunk/libs/random/doc/distribution_performance_linux.qbk)
==============================================================================
--- /trunk/libs/random/doc/distribution_performance_linux.qbk (original)
+++ branches/release/libs/random/doc/distribution_performance_linux.qbk 2010-03-21 20:45:06 EDT (Sun, 21 Mar 2010)
@@ -1,3 +1,11 @@
+[/
+ / Copyright (c) 2009 Steven Watanabe
+ /
+ / Distributed under the Boost Software License, Version 1.0. (See
+ / accompanying file LICENSE_1_0.txt or copy at
+ / http://www.boost.org/LICENSE_1_0.txt)
+]
+
[table Distributions (Linux)
[[\[M rn/sec\]][minstd_rand][kreutzer1986][mt19937][lagged_fibonacci607]]
[[uniform_int][31.25][30.581][11.5607][16.0514]]
Copied: branches/release/libs/random/doc/distribution_performance_windows.qbk (from r59910, /trunk/libs/random/doc/distribution_performance_windows.qbk)
==============================================================================
--- /trunk/libs/random/doc/distribution_performance_windows.qbk (original)
+++ branches/release/libs/random/doc/distribution_performance_windows.qbk 2010-03-21 20:45:06 EDT (Sun, 21 Mar 2010)
@@ -1,3 +1,11 @@
+[/
+ / Copyright (c) 2009 Steven Watanabe
+ /
+ / Distributed under the Boost Software License, Version 1.0. (See
+ / accompanying file LICENSE_1_0.txt or copy at
+ / http://www.boost.org/LICENSE_1_0.txt)
+]
+
[table Distributions (Windows)
[[\[M rn/sec\]][minstd_rand][kreutzer1986][mt19937][lagged_fibonacci607]]
[[uniform_int][14.7449][27.465][6.65292][28.5714]]
Copied: branches/release/libs/random/doc/distributions.qbk (from r59910, /trunk/libs/random/doc/distributions.qbk)
==============================================================================
--- /trunk/libs/random/doc/distributions.qbk (original)
+++ branches/release/libs/random/doc/distributions.qbk 2010-03-21 20:45:06 EDT (Sun, 21 Mar 2010)
@@ -1,3 +1,11 @@
+[/
+ / Copyright (c) 2009 Steven Watanabe
+ /
+ / Distributed under the Boost Software License, Version 1.0. (See
+ / accompanying file LICENSE_1_0.txt or copy at
+ / http://www.boost.org/LICENSE_1_0.txt)
+]
+
In addition to the [link boost_random.reference.generators random number generators],
this library provides distribution functions which map one distribution
(often a uniform distribution provided by some generator) to another.
Copied: branches/release/libs/random/doc/generator_defs.qbk (from r59910, /trunk/libs/random/doc/generator_defs.qbk)
==============================================================================
--- /trunk/libs/random/doc/generator_defs.qbk (original)
+++ branches/release/libs/random/doc/generator_defs.qbk 2010-03-21 20:45:06 EDT (Sun, 21 Mar 2010)
@@ -1,3 +1,11 @@
+[/
+ / Copyright (c) 2009 Steven Watanabe
+ /
+ / Distributed under the Boost Software License, Version 1.0. (See
+ / accompanying file LICENSE_1_0.txt or copy at
+ / http://www.boost.org/LICENSE_1_0.txt)
+]
+
[template rand48_speed[] 68%]
[template lrand48_run_time_speed[] 12%]
[template minstd_rand0_speed[] 32%]
Copied: branches/release/libs/random/doc/generator_performance_linux.qbk (from r59910, /trunk/libs/random/doc/generator_performance_linux.qbk)
==============================================================================
--- /trunk/libs/random/doc/generator_performance_linux.qbk (original)
+++ branches/release/libs/random/doc/generator_performance_linux.qbk 2010-03-21 20:45:06 EDT (Sun, 21 Mar 2010)
@@ -1,3 +1,11 @@
+[/
+ / Copyright (c) 2009 Steven Watanabe
+ /
+ / Distributed under the Boost Software License, Version 1.0. (See
+ / accompanying file LICENSE_1_0.txt or copy at
+ / http://www.boost.org/LICENSE_1_0.txt)
+]
+
[table Basic Generators (Linux)
[[generator] [M rn/sec] [time per random number \[nsec\]] [relative speed compared to fastest \[percent\]]]
[[rand48][312.5][3.2][100%]]
Copied: branches/release/libs/random/doc/generator_performance_windows.qbk (from r59910, /trunk/libs/random/doc/generator_performance_windows.qbk)
==============================================================================
--- /trunk/libs/random/doc/generator_performance_windows.qbk (original)
+++ branches/release/libs/random/doc/generator_performance_windows.qbk 2010-03-21 20:45:06 EDT (Sun, 21 Mar 2010)
@@ -1,3 +1,11 @@
+[/
+ / Copyright (c) 2009 Steven Watanabe
+ /
+ / Distributed under the Boost Software License, Version 1.0. (See
+ / accompanying file LICENSE_1_0.txt or copy at
+ / http://www.boost.org/LICENSE_1_0.txt)
+]
+
[table Basic Generators (Windows)
[[generator] [M rn/sec] [time per random number \[nsec\]] [relative speed compared to fastest \[percent\]]]
[[rand48][98.5222][10.15][67%]]
Copied: branches/release/libs/random/doc/generators.qbk (from r59910, /trunk/libs/random/doc/generators.qbk)
==============================================================================
--- /trunk/libs/random/doc/generators.qbk (original)
+++ branches/release/libs/random/doc/generators.qbk 2010-03-21 20:45:06 EDT (Sun, 21 Mar 2010)
@@ -1,3 +1,11 @@
+[/
+ / Copyright (c) 2009 Steven Watanabe
+ /
+ / Distributed under the Boost Software License, Version 1.0. (See
+ / accompanying file LICENSE_1_0.txt or copy at
+ / http://www.boost.org/LICENSE_1_0.txt)
+]
+
This library provides several [prng pseudo-random number generators]. The
quality of a [prng pseudo random number generator] crucially depends on both
the algorithm and its parameters. This library implements the algorithms as
Copied: branches/release/libs/random/doc/nondet_random.qbk (from r59910, /trunk/libs/random/doc/nondet_random.qbk)
==============================================================================
--- /trunk/libs/random/doc/nondet_random.qbk (original)
+++ branches/release/libs/random/doc/nondet_random.qbk 2010-03-21 20:45:06 EDT (Sun, 21 Mar 2010)
@@ -1,3 +1,11 @@
+[/
+ / Copyright (c) 2009 Steven Watanabe
+ /
+ / Distributed under the Boost Software License, Version 1.0. (See
+ / accompanying file LICENSE_1_0.txt or copy at
+ / http://www.boost.org/LICENSE_1_0.txt)
+]
+
[section Header <boost/nondet_random.hpp> Synopsis]
namespace boost {
Copied: branches/release/libs/random/doc/performance.qbk (from r59910, /trunk/libs/random/doc/performance.qbk)
==============================================================================
--- /trunk/libs/random/doc/performance.qbk (original)
+++ branches/release/libs/random/doc/performance.qbk 2010-03-21 20:45:06 EDT (Sun, 21 Mar 2010)
@@ -1,3 +1,11 @@
+[/
+ / Copyright (c) 2009 Steven Watanabe
+ /
+ / Distributed under the Boost Software License, Version 1.0. (See
+ / accompanying file LICENSE_1_0.txt or copy at
+ / http://www.boost.org/LICENSE_1_0.txt)
+]
+
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
Copied: branches/release/libs/random/doc/performance_data.qbk (from r59910, /trunk/libs/random/doc/performance_data.qbk)
==============================================================================
--- /trunk/libs/random/doc/performance_data.qbk (original)
+++ branches/release/libs/random/doc/performance_data.qbk 2010-03-21 20:45:06 EDT (Sun, 21 Mar 2010)
@@ -1,3 +1,11 @@
+[/
+ / Copyright (c) 2009 Steven Watanabe
+ /
+ / Distributed under the Boost Software License, Version 1.0. (See
+ / accompanying file LICENSE_1_0.txt or copy at
+ / http://www.boost.org/LICENSE_1_0.txt)
+]
+
[template rand48_speed[] 100%]
[template lrand48_run_time_speed[] 96%]
[template lrand48__C_library__speed[] 21%]
Copied: branches/release/libs/random/doc/random.qbk (from r59910, /trunk/libs/random/doc/random.qbk)
==============================================================================
--- /trunk/libs/random/doc/random.qbk (original)
+++ branches/release/libs/random/doc/random.qbk 2010-03-21 20:45:06 EDT (Sun, 21 Mar 2010)
@@ -84,7 +84,7 @@
You should read the [concepts 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 [@boost:/libs/random/random_demo.cpp random_demo.cpp].
+to have a look at [@boost:/libs/random/example/random_demo.cpp random_demo.cpp].
For a very quick start, here's an example:
Copied: branches/release/libs/random/doc/random_number_generator.qbk (from r59910, /trunk/libs/random/doc/random_number_generator.qbk)
==============================================================================
--- /trunk/libs/random/doc/random_number_generator.qbk (original)
+++ branches/release/libs/random/doc/random_number_generator.qbk 2010-03-21 20:45:06 EDT (Sun, 21 Mar 2010)
@@ -1,3 +1,11 @@
+[/
+ / Copyright (c) 2009 Steven Watanabe
+ /
+ / Distributed under the Boost Software License, Version 1.0. (See
+ / accompanying file LICENSE_1_0.txt or copy at
+ / http://www.boost.org/LICENSE_1_0.txt)
+]
+
[section Synopsis of miscellaneous decorators in header <boost/random.hpp>]
namespace boost {
Copied: branches/release/libs/random/doc/tutorial.qbk (from r59910, /trunk/libs/random/doc/tutorial.qbk)
==============================================================================
--- /trunk/libs/random/doc/tutorial.qbk (original)
+++ branches/release/libs/random/doc/tutorial.qbk 2010-03-21 20:45:06 EDT (Sun, 21 Mar 2010)
@@ -1,3 +1,11 @@
+[/
+ / Copyright (c) 2009 Steven Watanabe
+ /
+ / Distributed under the Boost Software License, Version 1.0. (See
+ / accompanying file LICENSE_1_0.txt or copy at
+ / http://www.boost.org/LICENSE_1_0.txt)
+]
+
[section Generating integers in a range]
[import ../example/die.cpp]
Copied: branches/release/libs/random/example/die.cpp (from r59910, /trunk/libs/random/example/die.cpp)
==============================================================================
--- /trunk/libs/random/example/die.cpp (original)
+++ branches/release/libs/random/example/die.cpp 2010-03-21 20:45:06 EDT (Sun, 21 Mar 2010)
@@ -1,3 +1,12 @@
+// die.cpp
+//
+// Copyright (c) 2009
+// Steven Watanabe
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
//[die
/*`
For the source of this example see
Copied: branches/release/libs/random/example/weighted_die.cpp (from r59910, /trunk/libs/random/example/weighted_die.cpp)
==============================================================================
--- /trunk/libs/random/example/weighted_die.cpp (original)
+++ branches/release/libs/random/example/weighted_die.cpp 2010-03-21 20:45:06 EDT (Sun, 21 Mar 2010)
@@ -1,3 +1,12 @@
+// weighted_die.cpp
+//
+// Copyright (c) 2009
+// Steven Watanabe
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
//[weighted_die
/*`
For the source of this example see
Deleted: branches/release/libs/random/histogram.cpp
==============================================================================
--- branches/release/libs/random/histogram.cpp 2010-03-21 20:45:06 EDT (Sun, 21 Mar 2010)
+++ (empty file)
@@ -1,165 +0,0 @@
-/* boost histogram.cpp graphical verification of distribution functions
- *
- * Copyright Jens Maurer 2000
- * Distributed under the Boost Software License, Version 1.0. (See
- * accompanying file LICENSE_1_0.txt or copy at
- * http://www.boost.org/LICENSE_1_0.txt)
- *
- * $Id$
- *
- * This test program allows to visibly examine the results of the
- * distribution functions.
- */
-
-#include <iostream>
-#include <iomanip>
-#include <vector>
-#include <algorithm>
-#include <cmath>
-#include <string>
-#include <boost/random.hpp>
-
-
-void plot_histogram(const std::vector<int>& 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 NumberGenerator,
- class Sum = typename NumberGenerator::result_type>
-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 NumberGenerator,
- class Sum = typename NumberGenerator::result_type>
-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<class RNG>
-void histogram(RNG base, int samples, double from, double to,
- const std::string & name)
-{
- typedef squaresum_result<sum_result<RNG, double>, double > SRNG;
- SRNG gen((sum_result<RNG, double>(base)));
- const int nSlots = 60;
- std::vector<int> 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<class PRNG, class Dist>
-inline boost::variate_generator<PRNG&, Dist> make_gen(PRNG & rng, Dist d)
-{
- return boost::variate_generator<PRNG&, Dist>(rng, d);
-}
-
-template<class PRNG>
-void histograms()
-{
- PRNG rng;
- using namespace boost;
- histogram(make_gen(rng, uniform_smallint<>(0, 5)), 100000, -1, 6,
- "uniform_smallint(0,5)");
- histogram(make_gen(rng, uniform_int<>(0, 5)), 100000, -1, 6,
- "uniform_int(0,5)");
- histogram(make_gen(rng, uniform_real<>(0,1)), 100000, -0.5, 1.5,
- "uniform_real(0,1)");
- histogram(make_gen(rng, bernoulli_distribution<>(0.2)), 100000, -0.5, 1.5,
- "bernoulli(0.2)");
- histogram(make_gen(rng, binomial_distribution<>(4, 0.2)), 100000, -1, 5,
- "binomial(4, 0.2)");
- histogram(make_gen(rng, triangle_distribution<>(1, 2, 8)), 100000, 0, 10,
- "triangle(1,2,8)");
- histogram(make_gen(rng, geometric_distribution<>(5.0/6.0)), 100000, 0, 10,
- "geometric(5/6)");
- histogram(make_gen(rng, exponential_distribution<>(0.3)), 100000, 0, 10,
- "exponential(0.3)");
- histogram(make_gen(rng, cauchy_distribution<>()), 100000, -5, 5,
- "cauchy");
- histogram(make_gen(rng, lognormal_distribution<>(3, 2)), 100000, 0, 10,
- "lognormal");
- histogram(make_gen(rng, normal_distribution<>()), 100000, -3, 3,
- "normal");
- histogram(make_gen(rng, normal_distribution<>(0.5, 0.5)), 100000, -3, 3,
- "normal(0.5, 0.5)");
- histogram(make_gen(rng, poisson_distribution<>(1.5)), 100000, 0, 5,
- "poisson(1.5)");
- histogram(make_gen(rng, poisson_distribution<>(10)), 100000, 0, 20,
- "poisson(10)");
- histogram(make_gen(rng, gamma_distribution<>(0.5)), 100000, 0, 0.5,
- "gamma(0.5)");
- histogram(make_gen(rng, gamma_distribution<>(1)), 100000, 0, 3,
- "gamma(1)");
- histogram(make_gen(rng, gamma_distribution<>(2)), 100000, 0, 6,
- "gamma(2)");
-}
-
-
-int main()
-{
- histograms<boost::mt19937>();
- // histograms<boost::lagged_fibonacci607>();
-}
-
Deleted: branches/release/libs/random/instantiate.cpp
==============================================================================
--- branches/release/libs/random/instantiate.cpp 2010-03-21 20:45:06 EDT (Sun, 21 Mar 2010)
+++ (empty file)
@@ -1,437 +0,0 @@
-/* boost validate.cpp
- *
- * Copyright Jens Maurer 2000
- * Distributed under the Boost Software License, Version 1.0. (See
- * accompanying file LICENSE_1_0.txt or copy at
- * http://www.boost.org/LICENSE_1_0.txt)
- *
- * $Id$
- */
-
-#if defined(BOOST_MSVC) && BOOST_MSVC <= 1300
-#pragma warning( disable : 4786 )
-#endif
-
-#include <iostream>
-#include <sstream>
-#include <string>
-#include <cmath>
-#include <iterator>
-#include <vector>
-#include <boost/random.hpp>
-#include <boost/config.hpp>
-#include <boost/preprocessor/stringize.hpp>
-
-#include <boost/test/test_tools.hpp>
-#include <boost/test/included/test_exec_monitor.hpp>
-
-#ifdef BOOST_NO_STDC_NAMESPACE
- namespace std { using ::abs; using ::fabs; using ::pow; }
-#endif
-
-
-/*
- * General portability note:
- * MSVC mis-compiles explicit function template instantiations.
- * For example, f<A>() and f<B>() are both compiled to call f<A>().
- * 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.
- */
-
-/*
- * Check function signatures
- */
-
-#if BOOST_WORKAROUND( __BORLANDC__, BOOST_TESTED_AT( 0x570) )
-#pragma warn -par
-#endif
-template<class URNG, class Dist>
-void instantiate_dist(URNG& urng, const char * name, const Dist& dist)
-{
- // this makes a copy of urng
- boost::variate_generator<URNG, Dist> gen(urng, dist);
-
- // this keeps a reference to urng
- boost::variate_generator<URNG&, Dist> genref(urng, dist);
-
- BOOST_CHECK(gen.engine() == genref.engine());
-
-#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
- // and here is a pointer to (a copy of) the urng
- URNG copy = urng;
- boost::variate_generator<URNG*, Dist> genptr(©, dist);
-#endif
-
- for(int i = 0; i < 1000; ++i) {
- (void) gen();
- (void) genref();
-#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
- (void) genptr();
-#endif
- }
- // If the values are not exactly equal, we cannot
- // rely on them being close...
- typename Dist::result_type g = gen();
- BOOST_CHECK_EQUAL(g, genref());
-#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
- BOOST_CHECK_EQUAL(g, genptr());
-#endif
-
- (void) gen.engine();
- gen.distribution().reset();
-
- Dist d = dist; // copy ctor
- d = dist; // copy assignment
-
-#ifndef BOOST_RANDOM_NO_STREAM_OPERATORS
- {
- std::ostringstream file;
- file << urng << std::endl;
- file << d;
- std::istringstream input(file.str());
- // std::cout << file.str() << std::endl;
- URNG restored_engine;
- input >> restored_engine;
- input >> std::ws;
- Dist restored_dist;
- input >> restored_dist;
-#if !defined(BOOST_MSVC) || BOOST_MSVC > 1300 // MSVC brokenness
- boost::variate_generator<URNG, Dist> old(urng, d);
- boost::variate_generator<URNG, Dist> restored(restored_engine, restored_dist);
- // advance some more so that state is exercised
- for(int i = 0; i < 1000; ++i) {
- (void) old();
- (void) restored();
- }
- BOOST_CHECK_MESSAGE((std::abs(old()-restored()) < 0.0001),
- (std::string(name) + " old == restored_dist"));
-#endif // BOOST_MSVC
- }
-#endif // BOOST_RANDOM_NO_STREAM_OPERATORS
-}
-
-template<class URNG, class RealType>
-void instantiate_real_dist(URNG& urng, RealType /* ignored */)
-{
- instantiate_dist(urng, "uniform_01",
- boost::uniform_01<RealType>());
- instantiate_dist(urng, "uniform_real",
- boost::uniform_real<RealType>(0, 2.1));
- instantiate_dist(urng, "triangle_distribution",
- boost::triangle_distribution<RealType>(1, 1.5, 7));
- instantiate_dist(urng, "exponential_distribution",
- boost::exponential_distribution<RealType>(5));
- instantiate_dist(urng, "normal_distribution",
- boost::normal_distribution<RealType>());
- instantiate_dist(urng, "lognormal_distribution",
- boost::lognormal_distribution<RealType>(1, 1));
- instantiate_dist(urng, "cauchy_distribution",
- boost::cauchy_distribution<RealType>(1));
- instantiate_dist(urng, "gamma_distribution",
- boost::gamma_distribution<RealType>(1));
-}
-
-template<class URNG, class T, class Converted>
-void test_seed_conversion(URNG & urng, const T & t, const Converted &) {
- Converted c = static_cast<Converted>(t);
- if(static_cast<T>(c) == t) {
- URNG urng2(c);
- std::ostringstream msg;
- msg << "Testing seed: type " << typeid(Converted).name() << ", value " << c;
- BOOST_CHECK_MESSAGE(urng == urng2, msg.str());
- urng2.seed(c);
- BOOST_CHECK_MESSAGE(urng == urng2, msg.str());
- }
-}
-
-// rand48 uses non-standard seeding
-template<class T, class Converted>
-void test_seed_conversion(boost::rand48 & urng, const T & t, const Converted &) {
- boost::rand48 urng2(t);
- urng2.seed(t);
-}
-
-template<class URNG, class ResultType>
-void test_seed(const URNG &, const ResultType & value) {
- URNG urng(value);
-
- // integral types
- test_seed_conversion(urng, value, static_cast<char>(0));
- test_seed_conversion(urng, value, static_cast<signed char>(0));
- test_seed_conversion(urng, value, static_cast<unsigned char>(0));
- test_seed_conversion(urng, value, static_cast<short>(0));
- test_seed_conversion(urng, value, static_cast<unsigned short>(0));
- test_seed_conversion(urng, value, static_cast<int>(0));
- test_seed_conversion(urng, value, static_cast<unsigned int>(0));
- test_seed_conversion(urng, value, static_cast<long>(0));
- test_seed_conversion(urng, value, static_cast<unsigned long>(0));
-#if !defined(BOOST_NO_INT64_T)
- test_seed_conversion(urng, value, static_cast<boost::int64_t>(0));
- test_seed_conversion(urng, value, static_cast<boost::uint64_t>(0));
-#endif
-
- // floating point types
- test_seed_conversion(urng, value, static_cast<float>(0));
- test_seed_conversion(urng, value, static_cast<double>(0));
- test_seed_conversion(urng, value, static_cast<long double>(0));
-}
-
-template<class URNG, class ResultType>
-void instantiate_seed(const URNG & urng, const ResultType &) {
- {
- URNG urng;
- URNG urng2;
- urng2.seed();
- BOOST_CHECK(urng == urng2);
- }
- test_seed(urng, static_cast<ResultType>(0));
- test_seed(urng, static_cast<ResultType>(127));
- test_seed(urng, static_cast<ResultType>(539157235));
- test_seed(urng, static_cast<ResultType>(~0u));
-}
-
-// ranlux uses int32_t for seeding instead of result_type
-template<class ResultType>
-void instantiate_seed(const boost::ranlux3 & urng, const ResultType &) {
- instantiate_seed<boost::ranlux3, boost::uint32_t>(urng, ResultType());
-}
-template<class ResultType>
-void instantiate_seed(const boost::ranlux4 & urng, const ResultType &) {
- instantiate_seed<boost::ranlux4, boost::uint32_t>(urng, ResultType());
-}
-template<class ResultType>
-void instantiate_seed(const boost::ranlux3_01 & urng, const ResultType &) {
- instantiate_seed<boost::ranlux3_01, boost::uint32_t>(urng, ResultType());
-}
-template<class ResultType>
-void instantiate_seed(const boost::ranlux4_01 & urng, const ResultType &) {
- instantiate_seed<boost::ranlux4_01, boost::uint32_t>(urng, ResultType());
-}
-#if !defined(BOOST_NO_INT64_T) && !defined(BOOST_NO_INTEGRAL_INT64_T)
-template<class ResultType>
-void instantiate_seed(const boost::ranlux64_3 & urng, const ResultType &) {
- instantiate_seed<boost::ranlux64_3, boost::uint32_t>(urng, ResultType());
-}
-template<class ResultType>
-void instantiate_seed(const boost::ranlux64_4 & urng, const ResultType &) {
- instantiate_seed<boost::ranlux64_3, boost::uint32_t>(urng, ResultType());
-}
-#endif
-template<class ResultType>
-void instantiate_seed(const boost::ranlux64_3_01 & urng, const ResultType &) {
- instantiate_seed<boost::ranlux64_3_01, boost::uint32_t>(urng, ResultType());
-}
-template<class ResultType>
-void instantiate_seed(const boost::ranlux64_4_01 & urng, const ResultType &) {
- instantiate_seed<boost::ranlux64_4_01, boost::uint32_t>(urng, ResultType());
-}
-
-
-template<class URNG, class ResultType>
-void instantiate_urng(const std::string & s, const URNG & u, const ResultType & r)
-{
- std::cout << "Basic tests for " << s << std::endl;
- URNG urng;
- instantiate_seed(u, r); // seed() member function
- 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
-
- URNG urng2 = urng; // copy constructor
-#if !defined(BOOST_MSVC) || BOOST_MSVC > 1300 // MSVC brokenness
- BOOST_CHECK(urng == urng2); // operator==
- BOOST_CHECK(!(urng != urng2)); // operator!=
- urng();
- urng2 = urng; // copy assignment
- BOOST_CHECK(urng == urng2);
- urng2 = URNG(urng2); // copy constructor, not templated constructor
- BOOST_CHECK(urng == urng2);
-#endif // BOOST_MSVC
-
- const std::vector<int> v(9999u, 0x41);
- std::vector<int>::const_iterator it = v.begin();
- std::vector<int>::const_iterator it_end = v.end();
- URNG urng3(it, it_end);
- BOOST_CHECK(it != v.begin());
- std::iterator_traits<std::vector<int>::const_iterator>::difference_type n_words = (it - v.begin());
- std::cout << "; seeding uses " << n_words << " words" << std::endl;
-
- it = v.end();
- BOOST_CHECK_THROW(urng3.seed(it, it_end), std::invalid_argument);
-
- if(n_words > 1) {
- it = v.end();
- --it;
- BOOST_CHECK_THROW(urng3.seed(it, it_end), std::invalid_argument);
- }
-
- // check for min/max members
- ResultType min = (urng3.min)();
- (void) &min;
- ResultType max = (urng3.max)();
- (void) &max;
-
-#ifndef BOOST_RANDOM_NO_STREAM_OPERATORS
- // Streamable concept not supported for broken compilers
-
- // advance a little so that state is relatively arbitrary
- for(int i = 0; i < 9307; ++i)
- urng();
- urng2 = urng;
-
- {
- // narrow stream first
- std::ostringstream file;
- file << urng;
- // move forward
- urng();
- // restore old state
- std::istringstream input(file.str());
- input >> urng;
- // std::cout << file.str() << std::endl;
-#if !defined(BOOST_MSVC) || BOOST_MSVC > 1300 // MSVC brokenness
- // advance some more so that state is exercised
- for(int i = 0; i < 10000; ++i) {
- urng();
- urng2();
- }
- BOOST_CHECK(urng == urng2);
-#endif // BOOST_MSVC
- }
-
- urng2 = urng;
-#if !defined(BOOST_NO_STD_WSTREAMBUF) && !defined(BOOST_NO_STD_WSTRING)
- {
- // then wide stream
- std::wostringstream file;
- file << urng;
- // move forward
- urng();
- std::wistringstream input(file.str());
- input >> urng;
-#if !defined(BOOST_MSVC) || BOOST_MSVC > 1300 // MSVC brokenness
- // advance some more so that state is exercised
- for(int i = 0; i < 10000; ++i) {
- urng();
- urng2();
- }
- BOOST_CHECK(urng == urng2);
-#endif // BOOST_MSVC
- }
-#endif // BOOST_NO_STD_WSTREAMBUF, BOOST_NO_STD_WSTRING
-#endif // BOOST_RANDOM_NO_STREAM_OPERATORS
-
- // instantiate various distributions with this URNG
- instantiate_dist(urng, "uniform_smallint", boost::uniform_smallint<>(0, 11));
- instantiate_dist(urng, "uniform_int", boost::uniform_int<>(-200, 20000));
- instantiate_dist(urng, "bernoulli_distribution",
- boost::bernoulli_distribution<>(0.2));
- instantiate_dist(urng, "binomial_distribution",
- boost::binomial_distribution<>(4, 0.2));
- instantiate_dist(urng, "geometric_distribution",
- boost::geometric_distribution<>(0.8));
- instantiate_dist(urng, "poisson_distribution",
- boost::poisson_distribution<>(1));
-
- instantiate_real_dist(urng, 1.0f);
- instantiate_real_dist(urng, 1.0);
- instantiate_real_dist(urng, 1.0l);
-
-#if 0
- // We cannot compare the outcomes before/after save with std::abs(x-y)
- instantiate_dist("uniform_on_sphere",
- boost::uniform_on_sphere<URNG>(urng, 2));
-#endif
-}
-
-template<class T>
-void extra_tests(T*)
-{
-}
-
-#if !defined(BOOST_NO_INT64_T) && !defined(BOOST_NO_INTEGRAL_INT64_T)
-void extra_tests(boost::rand48*)
-{
- using namespace boost;
- 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
-
-void extra_tests(boost::minstd_rand*)
-{
- using namespace boost;
- minstd_rand mstd(42);
- mstd.seed(17);
-}
-
-void extra_tests(boost::mt19937*)
-{
- using namespace boost;
- minstd_rand mstd(42);
- mstd.seed(17);
-
- 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<mt19937> std_rng(mt2);
- (void) std_rng(10);
-}
-
-void instantiate_all()
-{
- using namespace boost;
-
- typedef boost::random::lagged_fibonacci<boost::uint32_t, 24, 607, 273> lagged_fibonacci;
-
- typedef BOOST_RANDOM_URNG_TEST::result_type result_type;
- instantiate_urng(BOOST_PP_STRINGIZE(BOOST_RANDOM_URNG_TEST), BOOST_RANDOM_URNG_TEST(), static_cast<result_type>(0));
- BOOST_RANDOM_URNG_TEST* type_ptr = 0;
- extra_tests(type_ptr);
-
-}
-
-
-#if defined(BOOST_MSVC) && _MSC_VER < 1300
-
-// These explicit instantiations are necessary, otherwise MSVC does
-// not find the <boost/operators.hpp> inline friends.
-// We ease the typing with a suitable preprocessor macro.
-#define INSTANT(x) \
-template class boost::uniform_smallint<x>; \
-template class boost::uniform_int<x>; \
-template class boost::uniform_real<x>; \
-template class boost::bernoulli_distribution<x>; \
-template class boost::geometric_distribution<x>; \
-template class boost::triangle_distribution<x>; \
-template class boost::exponential_distribution<x>; \
-template class boost::normal_distribution<x>; \
-template class boost::uniform_on_sphere<x>; \
-template class boost::lognormal_distribution<x>;
-
-INSTANT(boost::minstd_rand0)
-INSTANT(boost::minstd_rand)
-INSTANT(boost::ecuyer1988)
-INSTANT(boost::kreutzer1986)
-INSTANT(boost::hellekalek1995)
-INSTANT(boost::mt19937)
-INSTANT(boost::mt11213b)
-
-#undef INSTANT
-#endif
-
-
-int test_main(int, char*[])
-{
- instantiate_all();
- return 0;
-}
Deleted: branches/release/libs/random/integrate.hpp
==============================================================================
--- branches/release/libs/random/integrate.hpp 2010-03-21 20:45:06 EDT (Sun, 21 Mar 2010)
+++ (empty file)
@@ -1,79 +0,0 @@
-/* integrate.hpp header file
- *
- * Copyright Jens Maurer 2000
- * Distributed under the Boost Software License, Version 1.0. (See
- * accompanying file LICENSE_1_0.txt or copy at
- * http://www.boost.org/LICENSE_1_0.txt)
- *
- * $Id$
- *
- * Revision history
- * 01 April 2001: Modified to use new <boost/limits.hpp> header. (JMaddock)
- */
-
-#ifndef INTEGRATE_HPP
-#define INTEGRATE_HPP
-
-#include <boost/limits.hpp>
-
-template<class UnaryFunction>
-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<class UnaryFunction>
-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<class UnaryFunction>
-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<class UnaryFunction>
-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<result_type>::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 */
Deleted: branches/release/libs/random/nondet_random_speed.cpp
==============================================================================
--- branches/release/libs/random/nondet_random_speed.cpp 2010-03-21 20:45:06 EDT (Sun, 21 Mar 2010)
+++ (empty file)
@@ -1,64 +0,0 @@
-/* boost nondet_random_speed.cpp performance test
- *
- * Copyright Jens Maurer 2000
- * Distributed under the Boost Software License, Version 1.0. (See
- * accompanying file LICENSE_1_0.txt or copy at
- * http://www.boost.org/LICENSE_1_0.txt)
- *
- * $Id$
- *
- */
-
-#include <iostream>
-#include <string>
-#include <boost/timer.hpp>
-#include <boost/nondet_random.hpp>
-
-// 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<class Result, class RNG>
-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<class RNG>
-void run(int iter, const std::string & name)
-{
- RNG rng;
- timing<long>(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<unsigned int>(dev, iter, "random_device");
-#else
-#error The non-deterministic random device is currently available on Linux only.
-#endif
-
- return 0;
-}
Deleted: branches/release/libs/random/random_demo.cpp
==============================================================================
--- branches/release/libs/random/random_demo.cpp 2010-03-21 20:45:06 EDT (Sun, 21 Mar 2010)
+++ (empty file)
@@ -1,128 +0,0 @@
-/* boost random_demo.cpp profane demo
- *
- * Copyright Jens Maurer 2000
- * Distributed under the Boost Software License, Version 1.0. (See
- * accompanying file LICENSE_1_0.txt or copy at
- * http://www.boost.org/LICENSE_1_0.txt)
- *
- * $Id$
- *
- * A short demo program how to use the random number library.
- */
-
-#include <iostream>
-#include <fstream>
-#include <ctime> // std::time
-
-#include <boost/random/linear_congruential.hpp>
-#include <boost/random/uniform_int.hpp>
-#include <boost/random/uniform_real.hpp>
-#include <boost/random/variate_generator.hpp>
-
-// Sun CC doesn't handle boost::iterator_adaptor yet
-#if !defined(__SUNPRO_CC) || (__SUNPRO_CC > 0x530)
-#include <boost/generator_iterator.hpp>
-#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.
- typedef boost::uniform_int<> distribution_type;
- typedef boost::variate_generator<base_generator_type&, distribution_type> gen_type;
- gen_type die_gen(generator, distribution_type(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<gen_type> die(&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_real<> uni_dist(0,1);
- boost::variate_generator<base_generator_type&, boost::uniform_real<> > uni(generator, uni_dist);
-
- 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<unsigned int>(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);
-
- // as a degenerate case, you can set min = max for uniform_int
- boost::uniform_int<> degen_dist(4,4);
- boost::variate_generator<base_generator_type&, boost::uniform_int<> > deg(generator, degen_dist);
- std::cout << deg() << " " << deg() << " " << deg() << std::endl;
-
-#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;
-}
Deleted: branches/release/libs/random/random_device.cpp
==============================================================================
--- branches/release/libs/random/random_device.cpp 2010-03-21 20:45:06 EDT (Sun, 21 Mar 2010)
+++ (empty file)
@@ -1,117 +0,0 @@
-/* boost random_device.cpp implementation
- *
- * Copyright Jens Maurer 2000
- * Distributed under the Boost Software License, Version 1.0. (See
- * accompanying file LICENSE_1_0.txt or copy at
- * http://www.boost.org/LICENSE_1_0.txt)
- *
- * $Id$
- *
- */
-
-#include <boost/nondet_random.hpp>
-#include <string>
-#include <cassert>
-
-
-#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
-
-
-#if defined(__linux__) || defined (__FreeBSD__)
-
-// 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 <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h> // open
-#include <unistd.h> // read, close
-#endif
-
-#include <errno.h> // errno
-#include <string.h> // strerror
-#include <stdexcept> // 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<char *>(&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__ || __FreeBSD__
-
-
-boost::random_device::random_device(const std::string& token)
- : pimpl(new impl(token))
-{
- assert((std::numeric_limits<result_type>::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;
-}
-
-double boost::random_device::entropy() const
-{
- return 10;
-}
-
-unsigned int boost::random_device::operator()()
-{
- return pimpl->next();
-}
Deleted: branches/release/libs/random/random_speed.cpp
==============================================================================
--- branches/release/libs/random/random_speed.cpp 2010-03-21 20:45:06 EDT (Sun, 21 Mar 2010)
+++ (empty file)
@@ -1,366 +0,0 @@
-/* boost random_speed.cpp performance measurements
- *
- * Copyright Jens Maurer 2000
- * Distributed under the Boost Software License, Version 1.0. (See
- * accompanying file LICENSE_1_0.txt or copy at
- * http://www.boost.org/LICENSE_1_0.txt)
- *
- * $Id$
- */
-
-#include <iostream>
-#include <cstdlib>
-#include <string>
-#include <boost/config.hpp>
-#include <boost/random.hpp>
-#include <boost/progress.hpp>
-#include <boost/shared_ptr.hpp>
-
-/*
- * 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<A>() and f<B>() are both compiled to call f<A>().
- * 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 IntType>
-class linear_congruential
-{
-public:
- typedef IntType result_type;
-
- BOOST_STATIC_CONSTANT(bool, has_fixed_range = false);
-
- 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 BOOST_PREVENT_MACRO_SUBSTITUTION () const { return _c == 0 ? 1 : 0; }
- result_type max BOOST_PREVENT_MACRO_SUBSTITUTION () const { return _m -1; }
-
-private:
- IntType _x, _a, _c, _m;
-};
-
-
-// simplest "random" number generator possible, to check on overhead
-class counting
-{
-public:
- typedef int result_type;
-
- BOOST_STATIC_CONSTANT(bool, has_fixed_range = false);
-
- counting() : _x(0) { }
- result_type operator()() { return ++_x; }
- result_type min BOOST_PREVENT_MACRO_SUBSTITUTION () const { return 1; }
- result_type max BOOST_PREVENT_MACRO_SUBSTITUTION () const { return (std::numeric_limits<result_type>::max)(); }
-
-private:
- int _x;
-};
-
-
-// decoration of variate_generator to make it runtime-exchangeable
-// for speed comparison
-template<class Ret>
-class RandomGenBase
-{
-public:
- virtual Ret operator()() = 0;
- virtual ~RandomGenBase() { }
-};
-
-template<class URNG, class Dist, class Ret = typename Dist::result_type>
-class DynamicRandomGenerator
- : public RandomGenBase<Ret>
-{
-public:
- DynamicRandomGenerator(URNG& urng, const Dist& d) : _rng(urng, d) { }
- Ret operator()() { return _rng(); }
-private:
- boost::variate_generator<URNG&, Dist> _rng;
-};
-
-template<class Ret>
-class GenericRandomGenerator
-{
-public:
- typedef Ret result_type;
-
- GenericRandomGenerator() { };
- void set(boost::shared_ptr<RandomGenBase<Ret> > p) { _p = p; }
- // takes over ownership
- void set(RandomGenBase<Ret> * p) { _p.reset(p); }
- Ret operator()() { return (*_p)(); }
-private:
- boost::shared_ptr<RandomGenBase<Ret> > _p;
-};
-
-
-// start implementation of measuring timing
-
-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;
-}
-
-#if 0
-template<class RNG>
-void timing(RNG & rng, int iter, const std::string& name)
-{
- // make sure we're not optimizing too much
- volatile typename RNG::result_type tmp;
- boost::timer t;
- for(int i = 0; i < iter; i++)
- tmp = rng();
- show_elapsed(t.elapsed(), iter, name);
-}
-#endif
-
-// overload for using a copy, allows more concise invocation
-template<class RNG>
-void timing(RNG rng, int iter, const std::string& name)
-{
- // make sure we're not optimizing too much
- volatile typename RNG::result_type tmp;
- boost::timer t;
- for(int i = 0; i < iter; i++)
- tmp = rng();
- show_elapsed(t.elapsed(), iter, name);
-}
-
-template<class RNG>
-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<double> & tmp = rng();
- (void) tmp[0];
- }
- show_elapsed(t.elapsed(), iter, name);
-}
-
-template<class RNG>
-void run(int iter, const std::string & name, const RNG &)
-{
- std::cout << (RNG::has_fixed_range ? "fixed-range " : "");
- // BCC has trouble with string autoconversion for explicit specializations
- timing(RNG(), iter, std::string(name));
-}
-
-#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);
-}
-#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<class PRNG, class Dist>
-inline boost::variate_generator<PRNG&, Dist> make_gen(PRNG & rng, Dist d)
-{
- return boost::variate_generator<PRNG&, Dist>(rng, d);
-}
-
-template<class Gen>
-void distrib(int iter, const std::string & name, const Gen &)
-{
- Gen gen;
-
- timing(make_gen(gen, boost::uniform_int<>(-2, 4)),
- iter, name + " uniform_int");
-
- timing(make_gen(gen, boost::geometric_distribution<>(0.5)),
- iter, name + " geometric");
-
- timing(make_gen(gen, boost::binomial_distribution<int>(4, 0.8)),
- iter, name + " binomial");
-
- timing(make_gen(gen, boost::poisson_distribution<>(1)),
- iter, name + " poisson");
-
-
- timing(make_gen(gen, boost::uniform_real<>(-5.3, 4.8)),
- iter, name + " uniform_real");
-
- timing(make_gen(gen, boost::triangle_distribution<>(1, 2, 7)),
- iter, name + " triangle");
-
- timing(make_gen(gen, boost::exponential_distribution<>(3)),
- iter, name + " exponential");
-
- timing(make_gen(gen, boost::normal_distribution<>()),
- iter, name + " normal polar");
-
- timing(make_gen(gen, boost::lognormal_distribution<>()),
- iter, name + " lognormal");
-
- timing(make_gen(gen, boost::cauchy_distribution<>()),
- iter, name + " cauchy");
-
- timing(make_gen(gen, boost::cauchy_distribution<>()),
- iter, name + " gamma");
-
- timing_sphere(make_gen(gen, boost::uniform_on_sphere<>(3)),
- iter/10, name + " uniform_on_sphere");
-}
-
-
-template<class URNG, class Dist>
-inline boost::shared_ptr<DynamicRandomGenerator<URNG, Dist> >
-make_dynamic(URNG & rng, const Dist& d)
-{
- typedef DynamicRandomGenerator<URNG, Dist> type;
- return boost::shared_ptr<type>(new type(rng, d));
-}
-
-template<class Gen>
-void distrib_runtime(int iter, const std::string & n, const Gen &)
-{
- std::string name = n + " virtual function ";
- Gen gen;
-
- GenericRandomGenerator<int> g_int;
-
- g_int.set(make_dynamic(gen, boost::uniform_int<>(-2,4)));
- timing(g_int, iter, name + "uniform_int");
-
- g_int.set(make_dynamic(gen, boost::geometric_distribution<>(0.5)));
- timing(g_int, iter, name + "geometric");
-
- g_int.set(make_dynamic(gen, boost::binomial_distribution<>(4, 0.8)));
- timing(g_int, iter, name + "binomial");
-
- g_int.set(make_dynamic(gen, boost::poisson_distribution<>(1)));
- timing(g_int, iter, name + "poisson");
-
- GenericRandomGenerator<double> g;
-
- g.set(make_dynamic(gen, boost::uniform_real<>(-5.3, 4.8)));
- timing(g, iter, name + "uniform_real");
-
- g.set(make_dynamic(gen, boost::triangle_distribution<>(1, 2, 7)));
- timing(g, iter, name + "triangle");
-
- g.set(make_dynamic(gen, boost::exponential_distribution<>(3)));
- timing(g, iter, name + "exponential");
-
- g.set(make_dynamic(gen, boost::normal_distribution<>()));
- timing(g, iter, name + "normal polar");
-
- g.set(make_dynamic(gen, boost::lognormal_distribution<>()));
- timing(g, iter, name + "lognormal");
-
- g.set(make_dynamic(gen, boost::cauchy_distribution<>()));
- timing(g, iter, name + "cauchy");
-
- g.set(make_dynamic(gen, boost::gamma_distribution<>(0.4)));
- timing(g, iter, name + "gamma");
-}
-
-
-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<boost::uint64_t>
- 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");
-#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());
-
- run(iter, "subtract_with_carry", boost::random::ranlux_base());
- run(iter, "subtract_with_carry_01", boost::random::ranlux_base_01());
- run(iter, "ranlux3", boost::ranlux3());
- run(iter, "ranlux4", boost::ranlux4());
- run(iter, "ranlux3_01", boost::ranlux3_01());
- run(iter, "ranlux4_01", boost::ranlux4_01());
- run(iter, "counting", counting());
-
-#ifdef HAVE_MT19937INT_C
- // requires the original mt19937int.c
- run<float>(iter, "mt19937 original"); // coded for sgenrand()/genrand()
-#endif
-
- distrib(iter, "counting", counting());
- distrib_runtime(iter, "counting", counting());
-
- distrib(iter, "minstd_rand", boost::minstd_rand());
-
- distrib(iter, "kreutzer1986", boost::kreutzer1986());
-
- distrib(iter, "mt19937", boost::mt19937());
- distrib_runtime(iter, "mt19937", boost::mt19937());
-}
Deleted: branches/release/libs/random/random_test.cpp
==============================================================================
--- branches/release/libs/random/random_test.cpp 2010-03-21 20:45:06 EDT (Sun, 21 Mar 2010)
+++ (empty file)
@@ -1,291 +0,0 @@
-/* boost random_test.cpp various tests
- *
- * Copyright Jens Maurer 2000
- * Distributed under the Boost Software License, Version 1.0. (See
- * accompanying file LICENSE_1_0.txt or copy at
- * http://www.boost.org/LICENSE_1_0.txt)
- *
- * $Id$
- */
-
-#if defined(BOOST_MSVC) && BOOST_MSVC <= 1300
-#pragma warning( disable : 4786 )
-#endif
-
-#include <iostream>
-#include <sstream>
-#include <string>
-#include <cmath>
-#include <iterator>
-#include <vector>
-#include <boost/random.hpp>
-#include <boost/config.hpp>
-
-#include <boost/test/test_tools.hpp>
-#include <boost/test/included/test_exec_monitor.hpp>
-
-#ifdef BOOST_NO_STDC_NAMESPACE
- namespace std { using ::abs; using ::fabs; using ::pow; }
-#endif
-
-
-/*
- * General portability note:
- * MSVC mis-compiles explicit function template instantiations.
- * For example, f<A>() and f<B>() are both compiled to call f<A>().
- * 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.
- */
-
-/*
- * A few equidistribution tests
- */
-
-// yet to come...
-
-template<class Generator>
-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<int> 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<double>(sum)/range;
- double p = 1 / static_cast<double>(range);
- double threshold = 2*std::sqrt(static_cast<double>(iter)*p*(1-p));
- 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<class Generator>
-void test_uniform_int(Generator & gen)
-{
- typedef boost::uniform_int<int> int_gen;
-
- // large range => small range (modulo case)
- typedef boost::variate_generator<Generator&, int_gen> level_one;
-
- level_one uint12(gen, int_gen(1,2));
- BOOST_CHECK((uint12.distribution().min)() == 1);
- BOOST_CHECK((uint12.distribution().max)() == 2);
- check_uniform_int(uint12, 100000);
- level_one uint16(gen, int_gen(1,6));
- check_uniform_int(uint16, 100000);
-
- // test chaining to get all cases in operator()
-
- // identity map
- typedef boost::variate_generator<level_one&, int_gen> level_two;
- level_two uint01(uint12, int_gen(0, 1));
- check_uniform_int(uint01, 100000);
-
- // small range => larger range
- level_two uint05(uint12, int_gen(-3, 2));
- check_uniform_int(uint05, 100000);
-
- // small range => larger range
- level_two uint099(uint12, int_gen(0, 99));
- check_uniform_int(uint099, 100000);
-
- // larger => small range, rejection case
- typedef boost::variate_generator<level_two&, int_gen> level_three;
- level_three uint1_4(uint05, int_gen(1, 4));
- check_uniform_int(uint1_4, 100000);
-
- typedef boost::uniform_int<boost::uint8_t> int8_gen;
- typedef boost::variate_generator<Generator&, int8_gen> gen8_t;
-
- gen8_t gen8_03(gen, int8_gen(0, 3));
-
- // use the full range of the type, where the destination
- // range is a power of the source range
- typedef boost::variate_generator<gen8_t, int8_gen> uniform_uint8;
- uniform_uint8 uint8_0255(gen8_03, int8_gen(0, 255));
- check_uniform_int(uint8_0255, 100000);
-
- // use the full range, but a generator whose range is not
- // a root of the destination range.
- gen8_t gen8_02(gen, int8_gen(0, 2));
- uniform_uint8 uint8_0255_2(gen8_02, int8_gen(0, 255));
- check_uniform_int(uint8_0255_2, 100000);
-
- // expand the range to a larger type.
- typedef boost::variate_generator<gen8_t, int_gen> uniform_uint_from8;
- uniform_uint_from8 uint0300(gen8_03, int_gen(0, 300));
- check_uniform_int(uint0300, 100000);
-}
-
-#if defined(BOOST_MSVC) && _MSC_VER < 1300
-
-// These explicit instantiations are necessary, otherwise MSVC does
-// not find the <boost/operators.hpp> inline friends.
-// We ease the typing with a suitable preprocessor macro.
-#define INSTANT(x) \
-template class boost::uniform_smallint<x>; \
-template class boost::uniform_int<x>; \
-template class boost::uniform_real<x>; \
-template class boost::bernoulli_distribution<x>; \
-template class boost::geometric_distribution<x>; \
-template class boost::triangle_distribution<x>; \
-template class boost::exponential_distribution<x>; \
-template class boost::normal_distribution<x>; \
-template class boost::uniform_on_sphere<x>; \
-template class boost::lognormal_distribution<x>;
-
-INSTANT(boost::minstd_rand0)
-INSTANT(boost::minstd_rand)
-INSTANT(boost::ecuyer1988)
-INSTANT(boost::kreutzer1986)
-INSTANT(boost::hellekalek1995)
-INSTANT(boost::mt19937)
-INSTANT(boost::mt11213b)
-
-#undef INSTANT
-#endif
-
-#if !defined(BOOST_NO_INT64_T) && !defined(BOOST_NO_INTEGRAL_INT64_T)
-// testcase by Mario R�tti
-class ruetti_gen
-{
-public:
- ruetti_gen() : state((max)() - 1) {}
- typedef boost::uint64_t result_type;
- result_type min BOOST_PREVENT_MACRO_SUBSTITUTION () const { return 0; }
- result_type max BOOST_PREVENT_MACRO_SUBSTITUTION () const { return std::numeric_limits<result_type>::max BOOST_PREVENT_MACRO_SUBSTITUTION (); }
- result_type operator()() { return state--; }
-private:
- result_type state;
-};
-
-void test_overflow_range()
-{
- ruetti_gen gen;
- boost::variate_generator<ruetti_gen, boost::uniform_int<> >
- rng(gen, boost::uniform_int<>(0, 10));
- for (int i=0;i<10;i++)
- (void) rng();
-}
-#else
-void test_overflow_range()
-{ }
-#endif
-
-template <typename EngineT>
-struct rand_for_random_shuffle
-{
- explicit rand_for_random_shuffle(EngineT &engine)
- : m_engine(engine)
- { }
-
- template <typename IntT>
- IntT operator()(IntT upperBound)
- {
- assert(upperBound > 0);
-
- if (upperBound == 1)
- {
- return 0;
- }
-
- typedef boost::uniform_int<IntT> distribution_type;
- typedef boost::variate_generator<EngineT &, distribution_type> generator_type;
-
- return generator_type(m_engine, distribution_type(0, upperBound - 1))();
- }
-
- EngineT &m_engine;
-
-};
-
-// Test that uniform_int<> can be used with std::random_shuffle
-// Author: Jos Hickson
-void test_random_shuffle()
-{
- typedef boost::uniform_int<> distribution_type;
- typedef boost::variate_generator<boost::mt19937 &, distribution_type> generator_type;
-
- boost::mt19937 engine1(1234);
- boost::mt19937 engine2(1234);
-
- rand_for_random_shuffle<boost::mt19937> referenceRand(engine1);
-
- distribution_type dist(0,10);
- generator_type testRand(engine2, dist);
-
- std::vector<int> referenceVec;
-
- for (int i = 0; i < 200; ++i)
- {
- referenceVec.push_back(i);
- }
-
- std::vector<int> testVec(referenceVec);
-
- std::random_shuffle(referenceVec.begin(), referenceVec.end(), referenceRand);
- std::random_shuffle(testVec.begin(), testVec.end(), testRand);
-
- typedef std::vector<int>::iterator iter_type;
- iter_type theEnd(referenceVec.end());
-
- for (iter_type referenceIter(referenceVec.begin()), testIter(testVec.begin());
- referenceIter != theEnd;
- ++referenceIter, ++testIter)
- {
- BOOST_CHECK_EQUAL(*referenceIter, *testIter);
- }
-}
-
-
-int test_main(int, char*[])
-{
-
-#if !defined(__INTEL_COMPILER) || !defined(_MSC_VER) || __INTEL_COMPILER > 700
- boost::mt19937 mt;
- test_uniform_int(mt);
-
- // bug report from Ken Mahler: This used to lead to an endless loop.
- typedef boost::uniform_int<unsigned int> uint_dist;
- boost::minstd_rand mr;
- boost::variate_generator<boost::minstd_rand, uint_dist> r2(mr,
- uint_dist(0, 0xffffffff));
- r2();
- r2();
-
- // bug report from Fernando Cacciola: This used to lead to an endless loop.
- // also from Douglas Gregor
- boost::variate_generator<boost::minstd_rand, boost::uniform_int<> > x(mr, boost::uniform_int<>(0, 8361));
- (void) x();
-
- // bug report from Alan Stokes and others: this throws an assertion
- boost::variate_generator<boost::minstd_rand, boost::uniform_int<> > y(mr, boost::uniform_int<>(1,1));
- std::cout << "uniform_int(1,1) " << y() << ", " << y() << ", " << y()
- << std::endl;
-
- test_overflow_range();
- test_random_shuffle();
-
- return 0;
-#else
- std::cout << "Intel 7.00 on Win32 loops, so the test is disabled\n";
- return 1;
-#endif
-}
Copied: branches/release/libs/random/src/random_device.cpp (from r60199, /trunk/libs/random/src/random_device.cpp)
==============================================================================
--- /trunk/libs/random/src/random_device.cpp (original)
+++ branches/release/libs/random/src/random_device.cpp 2010-03-21 20:45:06 EDT (Sun, 21 Mar 2010)
@@ -31,38 +31,37 @@
#include <wincrypt.h>
#include <stdexcept> // std::invalid_argument
-const char * const boost::random_device::default_token = "";
+#pragma comment(lib, "Advapi32.lib")
+
+BOOST_RANDOM_DECL const char * const boost::random_device::default_token = MS_DEF_PROV_A;
class boost::random_device::impl
{
public:
- impl(const std::string & token) : path(token) {
- std::basic_string<TCHAR> prov_name(token.begin(), token.end());
- if(prov_name.empty()) prov_name = MS_DEF_PROV;
-
- TCHAR buffer[80];
+ impl(const std::string & token) : provider(token) {
+ char buffer[80];
DWORD type;
DWORD len;
// Find the type of the provider
for(DWORD i = 0; ; ++i) {
len = sizeof(buffer);
- if(!CryptEnumProviders(i, NULL, 0, &type, buffer, &len)) {
- error("Could not find provider");
+ if(!CryptEnumProvidersA(i, NULL, 0, &type, buffer, &len)) {
+ error("Could not find provider name");
}
- if(buffer == prov_name) {
+ if(buffer == provider) {
break;
}
}
- if(!CryptAcquireContext(&hProv, NULL, prov_name.c_str(), type,
+ if(!CryptAcquireContextA(&hProv, NULL, provider.c_str(), type,
CRYPT_VERIFYCONTEXT | CRYPT_SILENT)) {
- error("Failed to aqcuire CSP context");
+ error("Could not acquire CSP context");
}
}
~impl() {
- if(!CryptReleaseContext(hProv, 0)) error("could not release CSP");
+ if(!CryptReleaseContext(hProv, 0)) error("Could not release CSP context");
}
unsigned int next() {
@@ -79,8 +78,8 @@
private:
void error(const std::string & msg) {
DWORD error_code = GetLastError();
- TCHAR buf[80];
- DWORD num = FormatMessage(
+ char buf[80];
+ DWORD num = FormatMessageA(
FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
GetLastError(),
@@ -90,10 +89,10 @@
NULL);
throw std::invalid_argument("boost::random_device: " + msg +
- " random-number pseudo-device " + path +
+ " Cryptopraphic Service Provider " + provider +
": " + std::string(&buf[0], &buf[0] + num));
}
- const std::string path;
+ const std::string provider;
HCRYPTPROV hProv;
};
@@ -112,7 +111,7 @@
#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
+// -fhonor-std and Dietmar Kuhl's standard C++ library. Hack around that
// problem for now.
extern "C" {
static const int O_RDONLY = 0;
@@ -167,25 +166,25 @@
#endif // BOOST_WINDOWS
-boost::random_device::random_device(const std::string& token)
+BOOST_RANDOM_DECL boost::random_device::random_device(const std::string& token)
: pimpl(new impl(token))
{
assert((std::numeric_limits<result_type>::max)() == max_value);
}
-boost::random_device::~random_device()
+BOOST_RANDOM_DECL boost::random_device::~random_device()
{
// the complete class impl is now visible, so we're safe
// (see comment in random.hpp)
delete pimpl;
}
-double boost::random_device::entropy() const
+BOOST_RANDOM_DECL double boost::random_device::entropy() const
{
return 10;
}
-unsigned int boost::random_device::operator()()
+BOOST_RANDOM_DECL unsigned int boost::random_device::operator()()
{
return pimpl->next();
}
Deleted: branches/release/libs/random/statistic_tests.cpp
==============================================================================
--- branches/release/libs/random/statistic_tests.cpp 2010-03-21 20:45:06 EDT (Sun, 21 Mar 2010)
+++ (empty file)
@@ -1,664 +0,0 @@
-/* statistic_tests.cpp file
- *
- * Copyright Jens Maurer 2000, 2002
- * Distributed under the Boost Software License, Version 1.0. (See
- * accompanying file LICENSE_1_0.txt or copy at
- * http://www.boost.org/LICENSE_1_0.txt)
- *
- * $Id$
- *
- * Revision history
- */
-
-/*
- * NOTE: This is not part of the official boost submission. It exists
- * only as a collection of ideas.
- */
-
-#include <iostream>
-#include <iomanip>
-#include <string>
-#include <functional>
-#include <math.h> // lgamma is not in namespace std
-#include <vector>
-#include <algorithm>
-
-#include <boost/cstdint.hpp>
-#include <boost/random.hpp>
-
-#include "statistic_tests.hpp"
-#include "integrate.hpp"
-
-
-namespace boost {
-namespace random {
-
-// Wikramaratna 1989 ACORN
-template<class IntType, int k, IntType m, IntType val>
-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<class InputIterator>
- explicit additive_congruential(InputIterator start) { seed(start); }
- template<class InputIterator>
- 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 IntType, int r, int s, IntType m, IntType val>
-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<class Generator>
- explicit lagged_fibonacci_int(Generator & gen) { seed(gen); }
- void seed(IntType start)
- {
- linear_congruential<uint32_t, 299375077, 0, 0, 0> init;
- seed(init);
- }
- template<class Generator>
- 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<boost::uint64_t, 45965, 453816691,
- (boost::uint64_t(1)<<31), 0> LCG_Af2;
- typedef boost::random::linear_congruential<boost::uint64_t, 211936855, 0,
- (boost::uint64_t(1)<<29)-3, 0> LCG_Die1;
- typedef boost::random::linear_congruential<boost::uint32_t, 2824527309u, 0,
- 0, 0> LCG_Fis;
- typedef boost::random::linear_congruential<boost::uint64_t, 950706376u, 0,
- (boost::uint64_t(1)<<31)-1, 0> LCG_FM;
- typedef boost::random::linear_congruential<boost::int32_t, 51081, 0,
- 2147483647, 0> LCG_Hae;
- typedef boost::random::linear_congruential<boost::uint32_t, 69069, 1,
- 0, 0> LCG_VAX;
- typedef boost::random::inversive_congruential<boost::int64_t, 240318, 197,
- 1000081, 0> NLG_Inv1;
- typedef boost::random::inversive_congruential<boost::int64_t, 15707262,
- 13262967, (1<<24)-17, 0> NLG_Inv2;
- typedef boost::random::inversive_congruential<boost::int32_t, 1, 1,
- 2147483647, 0> NLG_Inv4;
- typedef boost::random::inversive_congruential<boost::int32_t, 1, 2,
- 1<<30, 0> NLG_Inv5;
- typedef boost::random::additive_congruential<boost::int32_t, 6,
- (1<<30)-35, 0> MRG_Acorn7;
- typedef boost::random::lagged_fibonacci_int<boost::uint32_t, 607, 273,
- 0, 0> MRG_Fib2;
-
- template<class Gen, class T>
- 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<class Gen, class T>
- void validate(T value, const std::string & name)
- {
- Gen gen(1234567);
- check_validation(gen, value, name);
- }
-
- void validate_all()
- {
- validate<LCG_Af2>(183269031u, "LCG_Af2");
- validate<LCG_Die1>(522319944u, "LCG_Die1");
- validate<LCG_Fis>(-2065162233u, "LCG_Fis");
- validate<LCG_FM>(581815473u, "LCG_FM");
- validate<LCG_Hae>(28931709, "LCG_Hae");
- validate<LCG_VAX>(1508154087u, "LCG_VAX");
- validate<NLG_Inv2>(6666884, "NLG_Inv2");
- validate<NLG_Inv4>(1521640076, "NLG_Inv4");
- validate<NLG_Inv5>(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<MRG_Fib2>(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<double, double>
-{
-public:
- chi_square_density(int freedom)
- : _exponent( static_cast<double>(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<double>
-{
-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<double>
-{
-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<class RNG>
- void run(RNG & rng, int n1, int n2)
- {
- using namespace boost;
- std::cout << "equidistribution: " << std::flush;
- equidistribution_experiment equi(classes);
- uniform_smallint<RNG> 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<unsigned int>(std::sqrt(double(classes)));
- assert(root * root == classes);
- uniform_smallint<RNG> 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<class RNG>
- void run(RNG & rng, int n1, int n2)
- {
- using namespace boost;
- std::cout << "KS: " << std::flush;
- // generator_reference_t<RNG> gen_ref(rng);
- RNG& gen_ref(rng);
- kolmogorov_experiment ks(n1);
- uniform_distribution ud((rng.min)(), (rng.max)());
- 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<class RNG>
- void run(RNG & rng, int n1, int n2)
- {
- using namespace boost;
- std::cout << "runs: up: " << std::flush;
- runs_experiment<true> r_up(classes);
- // generator_reference_t<RNG> 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<false> 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<class RNG>
- 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<RNG> 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<class RNG>
- void run(RNG & rng, int n1, int n2)
- {
- using namespace boost;
- std::cout << "poker: " << std::flush;
- poker_experiment poker(8, classes);
- uniform_smallint<RNG> 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<class RNG>
- 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<RNG> 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<int>(classes)-1),
- high_classes)
- { }
-
- template<class RNG>
- void run(RNG & rng, int n1, int n2)
- {
- using namespace boost;
- std::cout << "permutation: " << std::flush;
- permutation_experiment perm(classes);
-
- // generator_reference_t<RNG> 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<class RNG>
- void run(RNG & rng, int n1, int n2)
- {
- using namespace boost;
- std::cout << "maximum-of-t: " << std::flush;
- maximum_experiment<RNG> 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<class RNG>
- void run(RNG & rng, int n1, int n2)
- {
- using namespace boost;
- std::cout << "birthday spacing: " << std::flush;
- uniform_int<RNG> uni(rng, 0, (1<<25)-1);
- 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<class RNG>
- 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<RNG> 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<boost::minstd_rand>("minstd_rand");
- env.run_test<boost::mt19937>("mt19937");
- env.run_test<Haertel::LCG_Af2>("LCG_Af2");
- env.run_test<Haertel::LCG_Die1>("LCG_Die1");
- env.run_test<Haertel::LCG_Fis>("LCG_Fis");
- env.run_test<Haertel::LCG_FM>("LCG_FM");
- env.run_test<Haertel::LCG_Hae>("LCG_Hae");
- env.run_test<Haertel::LCG_VAX>("LCG_VAX");
- env.run_test<Haertel::NLG_Inv1>("NLG_Inv1");
- env.run_test<Haertel::NLG_Inv2>("NLG_Inv2");
- env.run_test<Haertel::NLG_Inv4>("NLG_Inv4");
- env.run_test<Haertel::NLG_Inv5>("NLG_Inv5");
-}
Deleted: branches/release/libs/random/statistic_tests.hpp
==============================================================================
--- branches/release/libs/random/statistic_tests.hpp 2010-03-21 20:45:06 EDT (Sun, 21 Mar 2010)
+++ (empty file)
@@ -1,638 +0,0 @@
-/* statistic_tests.hpp header file
- *
- * Copyright Jens Maurer 2000
- * Distributed under the Boost Software License, Version 1.0. (See
- * accompanying file LICENSE_1_0.txt or copy at
- * http://www.boost.org/LICENSE_1_0.txt)
- *
- * $Id$
- *
- */
-
-#ifndef STATISTIC_TESTS_HPP
-#define STATISTIC_TESTS_HPP
-
-#include <stdexcept>
-#include <iterator>
-#include <vector>
-#include <boost/limits.hpp>
-#include <algorithm>
-#include <cmath>
-
-#include <boost/random.hpp>
-#include <boost/config.hpp>
-
-
-#if defined(BOOST_MSVC) && BOOST_MSVC <= 1300
-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<class T>
-inline T fac(int k)
-{
- T result = 1;
- for(T i = 2; i <= k; ++i)
- result *= i;
- return result;
-}
-
-template<class T>
-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<T>(n-k);
-}
-
-template<class T>
-T stirling2(int n, int m)
-{
- T sum = 0;
- for(int k = 0; k <= m; ++k)
- sum += binomial<T>(m, k) * std::pow(double(k), n) *
- ( (m-k)%2 == 0 ? 1 : -1);
- return sum / fac<T>(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<class NumberGenerator, class Counter>
- void run(NumberGenerator f, Counter & count, int n) const
- {
- assert((f.min)() == 0 &&
- static_cast<unsigned int>((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<class NumberGenerator, class Counter>
- 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<class UnaryFunction>
- 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<double>::infinity();
- if(limit[classes-1] < (std::numeric_limits<double>::max)())
- limit[classes-1] = (std::numeric_limits<double>::max)();
-#if 0
- std::cout << __PRETTY_FUNCTION__ << ": ";
- for(unsigned int i = 0; i < classes; ++i)
- std::cout << limit[i] << " ";
- std::cout << std::endl;
-#endif
- }
-
- template<class NumberGenerator, class Counter>
- 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<double> limits_type;
- limits_type limit;
-};
-
-// runs-up/runs-down experiment
-template<bool up>
-class runs_experiment : public experiment_base
-{
-public:
- explicit runs_experiment(unsigned int classes) : experiment_base(classes) { }
-
- template<class UniformRandomNumberGenerator, class Counter>
- 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<double>(classes());
- else
- return static_cast<double>(r+1)/fac<double>(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<class UniformRandomNumberGenerator, class Counter>
- 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<result_type>(alpha * range);
- result_type high = static_cast<result_type>(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<double>(r));
- else
- return p * std::pow(1-p, static_cast<double>(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<class UniformRandomNumberGenerator, class Counter>
- void run(UniformRandomNumberGenerator f, Counter & count, int n) const
- {
- typedef typename UniformRandomNumberGenerator::result_type result_type;
- assert(std::numeric_limits<result_type>::is_integer);
- assert((f.min)() == 0);
- assert((f.max)() == static_cast<result_type>(range-1));
- std::vector<result_type> 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<double>(classes())) *
- stirling2<double>(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<class UniformRandomNumberGenerator, class Counter>
- void run(UniformRandomNumberGenerator f, Counter & count, int n) const
- {
- typedef typename UniformRandomNumberGenerator::result_type result_type;
- assert(std::numeric_limits<result_type>::is_integer);
- assert((f.min)() == 0);
- assert((f.max)() == static_cast<result_type>(d-1));
- std::vector<bool> 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<double>(d)/std::pow(d, static_cast<double>(d+classes()-2))*
- stirling2<double>(d+classes()-2, d);
- else
- return fac<double>(d)/std::pow(d, static_cast<double>(d+r)) *
- stirling2<double>(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<int>(t)), t(t)
- {
- assert(t > 1);
- }
-
- template<class UniformRandomNumberGenerator, class Counter>
- void run(UniformRandomNumberGenerator f, Counter & count, int n) const
- {
- typedef typename UniformRandomNumberGenerator::result_type result_type;
- std::vector<result_type> 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--) {
- typename std::vector<result_type>::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<class UniformRandomNumberGenerator, class Counter>
- void run(UniformRandomNumberGenerator f, Counter & count, int n_total) const
- {
- typedef typename UniformRandomNumberGenerator::result_type result_type;
- assert(std::numeric_limits<result_type>::is_integer);
- assert((f.min)() == 0);
- assert((f.max)() == static_cast<result_type>(m-1));
-
- for(int j = 0; j < n_total; j++) {
- std::vector<result_type> v(n);
- std::generate_n(v.begin(), n, f);
- std::sort(v.begin(), v.end());
- std::vector<result_type> 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<class Float>
-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<double>
-{
-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<double>(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<int>(std::ceil(t)); k <= n; k++)
- sum += binomial<double>(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<class NumberGenerator, class Distribution>
- double run(NumberGenerator gen, Distribution distrib) const
- {
- const int m = n;
- typedef std::vector<double> saved_temp;
- saved_temp a(m,1.0), b(m,0);
- std::vector<int> c(m,0);
- for(int i = 0; i < n; ++i) {
- double val = gen();
- double y = distrib(val);
- int k = static_cast<int>(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<double>(n));
- j += c[k];
- kplus = (std::max)(kplus, j/static_cast<double>(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 UniformRandomNumberGenerator>
-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<double (*)(double, double)>(&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<base_type> f;
- int t;
- };
- base_type & f;
- kolmogorov_experiment ke;
- int t;
-};
-
-// compute a chi-square value for the distribution approximation error
-template<class ForwardIterator, class UnaryFunction>
-typename UnaryFunction::result_type
-chi_square_value(ForwardIterator first, ForwardIterator last,
- UnaryFunction probability)
-{
- typedef std::iterator_traits<ForwardIterator> 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 RandomAccessContainer>
-class generic_counter
-{
-public:
- explicit generic_counter(unsigned int classes) : container(classes, 0) { }
- void operator()(int i)
- {
- assert(i >= 0);
- assert(static_cast<unsigned int>(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<class Experiment, class Generator>
-double run_experiment(const Experiment & experiment, Generator gen, int n)
-{
- generic_counter<std::vector<int> > 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, class Generator>
-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<class Experiment, class Generator>
-experiment_generator_t<Experiment, Generator>
-experiment_generator(const Experiment & e, Generator & gen, int n)
-{
- return experiment_generator_t<Experiment, Generator>(e, gen, n);
-}
-
-
-template<class Experiment, class Generator, class Distribution>
-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<class Experiment, class Generator, class Distribution>
-ks_experiment_generator_t<Experiment, Generator, Distribution>
-ks_experiment_generator(const Experiment & e, Generator & gen,
- const Distribution & distrib)
-{
- return ks_experiment_generator_t<Experiment, Generator, Distribution>
- (e, gen, distrib);
-}
-
-
-#endif /* STATISTIC_TESTS_HPP */
-
Modified: branches/release/libs/random/test/Jamfile.v2
==============================================================================
--- branches/release/libs/random/test/Jamfile.v2 (original)
+++ branches/release/libs/random/test/Jamfile.v2 2010-03-21 20:45:06 EDT (Sun, 21 Mar 2010)
@@ -1,4 +1,5 @@
# Copyright 2003 Jens Maurer
+# Copyright 2009-2010 Steven Watanabe
# Distributed under the Boost Software License, Version 1.0. (See accompany-
# ing file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
@@ -7,12 +8,10 @@
# bring in rules for testing
import testing ;
-project
- : source-location ..
- ;
+project /boost/random/test ;
run random_test.cpp ;
-run random_demo.cpp ;
+run ../example/random_demo.cpp ;
run validate.cpp ;
local all-urngs =
@@ -45,5 +44,8 @@
# run random_speed.cpp ;
# run statistic_tests.cpp ;
+exe statistic_tests.exe : statistic_tests.cpp ;
+explicit statistics_tests ;
-
+install statistic_tests : statistic_tests.exe : <install-type>EXE <location>. ;
+explicit statistic_tests ;
Copied: branches/release/libs/random/test/instantiate.cpp (from r60199, /trunk/libs/random/test/instantiate.cpp)
==============================================================================
--- /trunk/libs/random/test/instantiate.cpp (original)
+++ branches/release/libs/random/test/instantiate.cpp 2010-03-21 20:45:06 EDT (Sun, 21 Mar 2010)
@@ -50,6 +50,7 @@
template<class URNG, class Dist>
void instantiate_dist(URNG& urng, const char * name, const Dist& dist)
{
+ std::cout << "Testing " << name << std::endl;
// this makes a copy of urng
boost::variate_generator<URNG, Dist> gen(urng, dist);
@@ -115,6 +116,7 @@
template<class URNG, class RealType>
void instantiate_real_dist(URNG& urng, RealType /* ignored */)
{
+ std::cout << "Testing real distributions with " << typeid(RealType).name() << std::endl;
instantiate_dist(urng, "uniform_01",
boost::uniform_01<RealType>());
instantiate_dist(urng, "uniform_real",
@@ -278,6 +280,8 @@
#ifndef BOOST_RANDOM_NO_STREAM_OPERATORS
// Streamable concept not supported for broken compilers
+ std::cout << "Testing stream operators" << std::endl;
+
// advance a little so that state is relatively arbitrary
for(int i = 0; i < 9307; ++i)
urng();
Copied: branches/release/libs/random/test/integrate.hpp (from r60199, /trunk/libs/random/test/integrate.hpp)
==============================================================================
--- /trunk/libs/random/test/integrate.hpp (original)
+++ branches/release/libs/random/test/integrate.hpp 2010-03-21 20:45:06 EDT (Sun, 21 Mar 2010)
@@ -43,11 +43,11 @@
}
// compute b so that f(b) = y; assume f is monotone increasing
-template<class UnaryFunction>
-inline typename UnaryFunction::argument_type
+template<class UnaryFunction, class T>
+inline T
invert_monotone_inc(UnaryFunction f, typename UnaryFunction::result_type y,
- typename UnaryFunction::argument_type lower = -1,
- typename UnaryFunction::argument_type upper = 1)
+ T lower = -1,
+ T upper = 1)
{
while(upper-lower > 1e-6) {
double middle = (upper+lower)/2;
Copied: branches/release/libs/random/test/random_test.cpp (from r60199, /trunk/libs/random/test/random_test.cpp)
==============================================================================
--- /trunk/libs/random/test/random_test.cpp (original)
+++ branches/release/libs/random/test/random_test.cpp 2010-03-21 20:45:06 EDT (Sun, 21 Mar 2010)
@@ -163,7 +163,7 @@
#endif
#if !defined(BOOST_NO_INT64_T) && !defined(BOOST_NO_INTEGRAL_INT64_T)
-// testcase by Mario R�tti
+// testcase by Mario Rutti
class ruetti_gen
{
public:
Copied: branches/release/libs/random/test/statistic_tests.cpp (from r60199, /trunk/libs/random/test/statistic_tests.cpp)
==============================================================================
--- /trunk/libs/random/test/statistic_tests.cpp (original)
+++ branches/release/libs/random/test/statistic_tests.cpp 2010-03-21 20:45:06 EDT (Sun, 21 Mar 2010)
@@ -10,257 +10,30 @@
* Revision history
*/
-/*
- * NOTE: This is not part of the official boost submission. It exists
- * only as a collection of ideas.
- */
-
#include <iostream>
#include <iomanip>
#include <string>
#include <functional>
-#include <math.h> // lgamma is not in namespace std
#include <vector>
+#include <set>
#include <algorithm>
#include <boost/cstdint.hpp>
#include <boost/random.hpp>
-#include "statistic_tests.hpp"
-#include "integrate.hpp"
-
-
-namespace boost {
-namespace random {
-
-// Wikramaratna 1989 ACORN
-template<class IntType, int k, IntType m, IntType val>
-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<class InputIterator>
- explicit additive_congruential(InputIterator start) { seed(start); }
- template<class InputIterator>
- 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 IntType, int r, int s, IntType m, IntType val>
-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<class Generator>
- explicit lagged_fibonacci_int(Generator & gen) { seed(gen); }
- void seed(IntType start)
- {
- linear_congruential<uint32_t, 299375077, 0, 0, 0> init;
- seed(init);
- }
- template<class Generator>
- 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<boost::uint64_t, 45965, 453816691,
- (boost::uint64_t(1)<<31), 0> LCG_Af2;
- typedef boost::random::linear_congruential<boost::uint64_t, 211936855, 0,
- (boost::uint64_t(1)<<29)-3, 0> LCG_Die1;
- typedef boost::random::linear_congruential<boost::uint32_t, 2824527309u, 0,
- 0, 0> LCG_Fis;
- typedef boost::random::linear_congruential<boost::uint64_t, 950706376u, 0,
- (boost::uint64_t(1)<<31)-1, 0> LCG_FM;
- typedef boost::random::linear_congruential<boost::int32_t, 51081, 0,
- 2147483647, 0> LCG_Hae;
- typedef boost::random::linear_congruential<boost::uint32_t, 69069, 1,
- 0, 0> LCG_VAX;
- typedef boost::random::inversive_congruential<boost::int64_t, 240318, 197,
- 1000081, 0> NLG_Inv1;
- typedef boost::random::inversive_congruential<boost::int64_t, 15707262,
- 13262967, (1<<24)-17, 0> NLG_Inv2;
- typedef boost::random::inversive_congruential<boost::int32_t, 1, 1,
- 2147483647, 0> NLG_Inv4;
- typedef boost::random::inversive_congruential<boost::int32_t, 1, 2,
- 1<<30, 0> NLG_Inv5;
- typedef boost::random::additive_congruential<boost::int32_t, 6,
- (1<<30)-35, 0> MRG_Acorn7;
- typedef boost::random::lagged_fibonacci_int<boost::uint32_t, 607, 273,
- 0, 0> MRG_Fib2;
-
- template<class Gen, class T>
- 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<class Gen, class T>
- void validate(T value, const std::string & name)
- {
- Gen gen(1234567);
- check_validation(gen, value, name);
- }
-
- void validate_all()
- {
- validate<LCG_Af2>(183269031u, "LCG_Af2");
- validate<LCG_Die1>(522319944u, "LCG_Die1");
- validate<LCG_Fis>(-2065162233u, "LCG_Fis");
- validate<LCG_FM>(581815473u, "LCG_FM");
- validate<LCG_Hae>(28931709, "LCG_Hae");
- validate<LCG_VAX>(1508154087u, "LCG_VAX");
- validate<NLG_Inv2>(6666884, "NLG_Inv2");
- validate<NLG_Inv4>(1521640076, "NLG_Inv4");
- validate<NLG_Inv5>(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<MRG_Fib2>(1234567u, "MRG_Fib2");
- }
-} // namespace Haertel
-
-
+#include <boost/math/special_functions/gamma.hpp>
+#include <boost/math/distributions/uniform.hpp>
+#include <boost/math/distributions/chi_squared.hpp>
+#include <boost/math/distributions/normal.hpp>
+#include <boost/math/distributions/triangular.hpp>
+#include <boost/math/distributions/cauchy.hpp>
+#include <boost/math/distributions/gamma.hpp>
+#include <boost/math/distributions/exponential.hpp>
+#include <boost/math/distributions/lognormal.hpp>
-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<double, double>
-{
-public:
- chi_square_density(int freedom)
- : _exponent( static_cast<double>(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<double>
-{
-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<double>
-{
-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;
-};
+#include "statistic_tests.hpp"
+#include "integrate.hpp"
class test_environment;
@@ -268,7 +41,7 @@
{
protected:
explicit test_base(test_environment & env) : environment(env) { }
- void check(double val) const;
+ void check_(double val) const;
private:
test_environment & environment;
};
@@ -279,7 +52,7 @@
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)
+ test_distrib_chi_square(boost::math::chi_squared(classes-1), high_classes)
{ }
template<class RNG>
@@ -288,20 +61,20 @@
using namespace boost;
std::cout << "equidistribution: " << std::flush;
equidistribution_experiment equi(classes);
- uniform_smallint<RNG> uint_linear(rng, 0, classes-1);
- check(run_experiment(test_distrib_chi_square,
+ variate_generator<RNG&, uniform_smallint<> > uint_linear(rng, uniform_smallint<>(0, classes-1));
+ check_(run_experiment(test_distrib_chi_square,
experiment_generator(equi, uint_linear, n1), n2));
- check(run_experiment(test_distrib_chi_square,
+ 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<unsigned int>(std::sqrt(double(classes)));
assert(root * root == classes);
- uniform_smallint<RNG> uint_square(rng, 0, root-1);
- check(run_experiment(test_distrib_chi_square,
+ variate_generator<RNG&, uniform_smallint<> > uint_square(rng, uniform_smallint<>(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,
+ check_(run_experiment(test_distrib_chi_square,
experiment_generator(equi_2d, uint_square, n1), 2*n2));
std::cout << std::endl;
}
@@ -310,10 +83,10 @@
distribution_experiment test_distrib_chi_square;
};
-class ks_equidistribution_test : test_base
+class ks_distribution_test : test_base
{
public:
- ks_equidistribution_test(test_environment & env, unsigned int classes)
+ ks_distribution_test(test_environment & env, unsigned int classes)
: test_base(env),
test_distrib_chi_square(kolmogorov_smirnov_probability(5000),
classes)
@@ -322,16 +95,20 @@
template<class RNG>
void run(RNG & rng, int n1, int n2)
{
+ boost::math::uniform ud(static_cast<double>((rng.min)()), static_cast<double>((rng.max)()));
+ run(rng, ud, n1, n2);
+ }
+ template<class RNG, class Dist>
+ void run(RNG & rng, const Dist& dist, int n1, int n2)
+ {
using namespace boost;
std::cout << "KS: " << std::flush;
- // generator_reference_t<RNG> gen_ref(rng);
- RNG& gen_ref(rng);
kolmogorov_experiment ks(n1);
- uniform_distribution ud((rng.min)(), (rng.max)());
- 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));
+ check_(run_experiment(test_distrib_chi_square,
+ ks_experiment_generator(ks, rng, dist), n2));
+ check_(run_experiment(test_distrib_chi_square,
+ ks_experiment_generator(ks, rng, dist), 2*n2));
+ std::cout << std::endl;
}
private:
distribution_experiment test_distrib_chi_square;
@@ -343,7 +120,7 @@
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)
+ test_distrib_chi_square(boost::math::chi_squared(classes-1), high_classes)
{ }
template<class RNG>
@@ -352,19 +129,18 @@
using namespace boost;
std::cout << "runs: up: " << std::flush;
runs_experiment<true> r_up(classes);
- // generator_reference_t<RNG> 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));
+
+ check_(run_experiment(test_distrib_chi_square,
+ experiment_generator(r_up, rng, n1), n2));
+ check_(run_experiment(test_distrib_chi_square,
+ experiment_generator(r_up, rng, n1), 2*n2));
std::cout << " down: " << std::flush;
runs_experiment<false> 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));
+ check_(run_experiment(test_distrib_chi_square,
+ experiment_generator(r_down, rng, n1), n2));
+ check_(run_experiment(test_distrib_chi_square,
+ experiment_generator(r_down, rng, n1), 2*n2));
std::cout << std::endl;
}
@@ -379,21 +155,30 @@
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)
+ test_distrib_chi_square(boost::math::chi_squared(classes-1), high_classes)
{ }
template<class RNG>
void run(RNG & rng, int n1, int n2)
{
+ boost::math::uniform ud(
+ static_cast<double>((rng.min)()),
+ static_cast<double>((rng.max)()) +
+ (std::numeric_limits<typename RNG::result_type>::is_integer? 0.0 : 1.0));
+ run(rng, ud, n1, n2);
+ }
+
+ template<class RNG, class Dist>
+ void run(RNG & rng, const Dist& dist, int n1, int n2)
+ {
using namespace boost;
std::cout << "gaps: " << std::flush;
- gap_experiment gap(classes, 0.2, 0.8);
- // generator_reference_t<RNG> 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));
+ gap_experiment gap(classes, dist, 0.2, 0.8);
+
+ check_(run_experiment(test_distrib_chi_square,
+ experiment_generator(gap, rng, n1), n2));
+ check_(run_experiment(test_distrib_chi_square,
+ experiment_generator(gap, rng, n1), 2*n2));
std::cout << std::endl;
}
@@ -408,7 +193,7 @@
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)
+ test_distrib_chi_square(boost::math::chi_squared(classes-1), high_classes)
{ }
template<class RNG>
@@ -417,10 +202,10 @@
using namespace boost;
std::cout << "poker: " << std::flush;
poker_experiment poker(8, classes);
- uniform_smallint<RNG> usmall(rng, 0, 7);
- check(run_experiment(test_distrib_chi_square,
+ variate_generator<RNG&, uniform_smallint<> > usmall(rng, uniform_smallint<>(0, 7));
+ check_(run_experiment(test_distrib_chi_square,
experiment_generator(poker, usmall, n1), n2));
- check(run_experiment(test_distrib_chi_square,
+ check_(run_experiment(test_distrib_chi_square,
experiment_generator(poker, usmall, n1), 2*n2));
std::cout << std::endl;
}
@@ -435,7 +220,7 @@
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)
+ test_distrib_chi_square(boost::math::chi_squared(classes-1), high_classes)
{ }
template<class RNG>
@@ -445,10 +230,10 @@
std::cout << "coupon collector: " << std::flush;
coupon_collector_experiment coupon(5, classes);
- uniform_smallint<RNG> usmall(rng, 0, 4);
- check(run_experiment(test_distrib_chi_square,
+ variate_generator<RNG&, uniform_smallint<> > usmall(rng, uniform_smallint<>(0, 4));
+ check_(run_experiment(test_distrib_chi_square,
experiment_generator(coupon, usmall, n1), n2));
- check(run_experiment(test_distrib_chi_square,
+ check_(run_experiment(test_distrib_chi_square,
experiment_generator(coupon, usmall, n1), 2*n2));
std::cout << std::endl;
}
@@ -463,7 +248,7 @@
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<int>(classes)-1),
+ test_distrib_chi_square(boost::math::chi_squared(fac<int>(classes)-1),
high_classes)
{ }
@@ -476,9 +261,9 @@
// generator_reference_t<RNG> gen_ref(rng);
RNG& gen_ref(rng);
- check(run_experiment(test_distrib_chi_square,
+ check_(run_experiment(test_distrib_chi_square,
experiment_generator(perm, gen_ref, n1), n2));
- check(run_experiment(test_distrib_chi_square,
+ check_(run_experiment(test_distrib_chi_square,
experiment_generator(perm, gen_ref, n1), 2*n2));
std::cout << std::endl;
}
@@ -502,8 +287,8 @@
using namespace boost;
std::cout << "maximum-of-t: " << std::flush;
maximum_experiment<RNG> mx(rng, n1, 5);
- check(run_experiment(test_distrib_chi_square, mx, n2));
- check(run_experiment(test_distrib_chi_square, mx, 2*n2));
+ check_(run_experiment(test_distrib_chi_square, mx, n2));
+ check_(run_experiment(test_distrib_chi_square, mx, 2*n2));
std::cout << std::endl;
}
private:
@@ -513,8 +298,9 @@
class birthday_test : test_base
{
public:
- birthday_test(test_environment & env)
- : test_base(env)
+ birthday_test(test_environment & env, unsigned int high_classes)
+ : test_base(env),
+ test_distrib_chi_square(boost::math::chi_squared(4-1), high_classes)
{ }
template<class RNG>
@@ -522,30 +308,31 @@
{
using namespace boost;
std::cout << "birthday spacing: " << std::flush;
- uniform_int<RNG> uni(rng, 0, (1<<25)-1);
+ boost::variate_generator<RNG&, boost::uniform_int<> > uni(rng, boost::uniform_int<>(0, (1<<25)-1));
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
+ check_(run_experiment(test_distrib_chi_square,
+ experiment_generator(bsp, uni, n1), n2));
+ check_(run_experiment(test_distrib_chi_square,
+ experiment_generator(bsp, uni, n1), 2*n2));
std::cout << std::endl;
}
-
-
+private:
+ distribution_experiment test_distrib_chi_square;
};
+#ifdef BOOST_MSVC
+#pragma warning(disable:4355)
+#endif
+
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),
+ confidence_chi_square_quantil(quantile(boost::math::chi_squared(classes-1), confidence)),
+ test_distrib_chi_square6(boost::math::chi_squared(7-1), classes),
+ ksdist_test(*this, classes),
equi_test(*this, 100, classes),
rns_test(*this, 7, classes),
gp_test(*this, 7, classes),
@@ -553,14 +340,14 @@
cpn_test(*this, 15, classes),
perm_test(*this, 5, classes),
max_test(*this, classes),
- bday_test(*this)
+ bday_test(*this, classes)
{
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)
+ << cdf(boost::math::chi_squared(classes-1), confidence_chi_square_quantil)
<< std::endl;
}
@@ -571,14 +358,14 @@
if(!result) {
std::cout << "* [";
double prob = (val > 10*chi_square_conf ? 1 :
- chi_square_probability(classes-1)(0, val));
+ cdf(boost::math::chi_squared(classes-1), val));
std::cout << (1-prob) << "]";
}
std::cout << " " << std::flush;
return result;
}
- bool check(double chi_square_value) const
+ bool check_(double chi_square_value) const
{
return check_confidence(chi_square_value, confidence_chi_square_quantil);
}
@@ -591,10 +378,8 @@
std::cout << "Running tests on " << name << std::endl;
RNG rng(1234567);
- typedef boost::uniform_01<RNG> UGen;
-#if 1
- ksequi_test.run(rng, 5000, 250);
+ ksdist_test.run(rng, 5000, 250);
equi_test.run(rng, 5000, 250);
rns_test.run(rng, 100000, 250);
gp_test.run(rng, 10000, 250);
@@ -602,17 +387,34 @@
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;
}
+ template<class RNG, class Dist, class ExpectedDist>
+ void run_test(const std::string & name, const Dist & dist, const ExpectedDist & expected_dist)
+ {
+ using namespace boost;
+
+ std::cout << "Running tests on " << name << std::endl;
+
+ RNG rng;
+ variate_generator<RNG&, Dist> vgen(rng, dist);
+
+ ksdist_test.run(vgen, expected_dist, 5000, 250);
+ rns_test.run(vgen, 100000, 250);
+ gp_test.run(vgen, expected_dist, 10000, 250);
+ perm_test.run(vgen, 1200, 250);
+
+ std::cout << std::endl;
+ }
+
private:
double confidence;
double confidence_chi_square_quantil;
distribution_experiment test_distrib_chi_square6;
- ks_equidistribution_test ksequi_test;
+ ks_distribution_test ksdist_test;
equidistribution_test equi_test;
runs_test rns_test;
gap_test gp_test;
@@ -623,42 +425,79 @@
birthday_test bday_test;
};
-void test_base::check(double val) const
+void test_base::check_(double val) const
{
- environment.check(val);
+ environment.check_(val);
}
-void print_ks_table()
+class program_args
{
- 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))
- << " ";
+public:
+ program_args(int argc, char** argv)
+ {
+ if(argc > 0) {
+ names.insert(argv + 1, argv + argc);
}
- std::cout << std::endl;
}
-}
+ bool check_(const std::string & test_name) const
+ {
+ return(names.empty() || names.find(test_name) != names.end());
+ }
+private:
+ std::set<std::string> names;
+};
-int main()
+int main(int argc, char* argv[])
{
- // Haertel::validate_all();
+ program_args args(argc, argv);
test_environment env(0.99);
- env.run_test<boost::minstd_rand>("minstd_rand");
- env.run_test<boost::mt19937>("mt19937");
- env.run_test<Haertel::LCG_Af2>("LCG_Af2");
- env.run_test<Haertel::LCG_Die1>("LCG_Die1");
- env.run_test<Haertel::LCG_Fis>("LCG_Fis");
- env.run_test<Haertel::LCG_FM>("LCG_FM");
- env.run_test<Haertel::LCG_Hae>("LCG_Hae");
- env.run_test<Haertel::LCG_VAX>("LCG_VAX");
- env.run_test<Haertel::NLG_Inv1>("NLG_Inv1");
- env.run_test<Haertel::NLG_Inv2>("NLG_Inv2");
- env.run_test<Haertel::NLG_Inv4>("NLG_Inv4");
- env.run_test<Haertel::NLG_Inv5>("NLG_Inv5");
+
+#define TEST(name) \
+ if(args.check_(#name)) \
+ env.run_test<boost::name>(#name)
+
+ TEST(minstd_rand0);
+ TEST(minstd_rand);
+ TEST(rand48);
+ TEST(ecuyer1988);
+ TEST(kreutzer1986);
+ TEST(taus88);
+ TEST(hellekalek1995);
+ TEST(mt11213b);
+ TEST(mt19937);
+ TEST(lagged_fibonacci607);
+ TEST(lagged_fibonacci1279);
+ TEST(lagged_fibonacci2281);
+ TEST(lagged_fibonacci3217);
+ TEST(lagged_fibonacci4423);
+ TEST(lagged_fibonacci9689);
+ TEST(lagged_fibonacci19937);
+ TEST(lagged_fibonacci23209);
+ TEST(lagged_fibonacci44497);
+ TEST(ranlux3);
+ TEST(ranlux4);
+
+#if !defined(BOOST_NO_INT64_T) && !defined(BOOST_NO_INTEGRAL_INT64_T)
+ TEST(ranlux64_3);
+ TEST(ranlux64_4);
+#endif
+
+ TEST(ranlux3_01);
+ TEST(ranlux4_01);
+ TEST(ranlux64_3_01);
+ TEST(ranlux64_4_01);
+
+ if(args.check_("normal"))
+ env.run_test<boost::mt19937>("normal", boost::normal_distribution<>(), boost::math::normal());
+ if(args.check_("triangle"))
+ env.run_test<boost::mt19937>("triangle", boost::triangle_distribution<>(0, 1, 3), boost::math::triangular(0, 1, 3));
+ if(args.check_("cauchy"))
+ env.run_test<boost::mt19937>("cauchy", boost::cauchy_distribution<>(), boost::math::cauchy());
+ if(args.check_("gamma"))
+ env.run_test<boost::mt19937>("gamma", boost::gamma_distribution<>(1), boost::math::gamma_distribution<>(1));
+ if(args.check_("exponential"))
+ env.run_test<boost::mt19937>("exponential", boost::exponential_distribution<>(), boost::math::exponential());
+ if(args.check_("lognormal"))
+ env.run_test<boost::mt19937>("lognormal", boost::lognormal_distribution<>(1, 1),
+ boost::math::lognormal(std::log(1.0/std::sqrt(2.0)), std::sqrt(std::log(2.0))));
}
Copied: branches/release/libs/random/test/statistic_tests.hpp (from r60199, /trunk/libs/random/test/statistic_tests.hpp)
==============================================================================
--- /trunk/libs/random/test/statistic_tests.hpp (original)
+++ branches/release/libs/random/test/statistic_tests.hpp 2010-03-21 20:45:06 EDT (Sun, 21 Mar 2010)
@@ -21,7 +21,9 @@
#include <boost/random.hpp>
#include <boost/config.hpp>
+#include <boost/bind.hpp>
+#include "integrate.hpp"
#if defined(BOOST_MSVC) && BOOST_MSVC <= 1300
namespace std
@@ -84,7 +86,7 @@
: experiment_base(classes) { }
template<class NumberGenerator, class Counter>
- void run(NumberGenerator f, Counter & count, int n) const
+ void run(NumberGenerator & f, Counter & count, int n) const
{
assert((f.min)() == 0 &&
static_cast<unsigned int>((f.max)()) == classes()-1);
@@ -102,7 +104,7 @@
: equidistribution_experiment(classes) { }
template<class NumberGenerator, class Counter>
- void run(NumberGenerator f, Counter & count, int n) const
+ void run(NumberGenerator & f, Counter & count, int n) const
{
unsigned int range = (f.max)()+1;
assert((f.min)() == 0 && range*range == classes());
@@ -119,12 +121,12 @@
class distribution_experiment : public equidistribution_experiment
{
public:
- template<class UnaryFunction>
- distribution_experiment(UnaryFunction probability , unsigned int classes)
+ template<class Distribution>
+ distribution_experiment(Distribution dist , 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[i] = quantile(dist, (i+1)*0.05);
limit[classes-1] = std::numeric_limits<double>::infinity();
if(limit[classes-1] < (std::numeric_limits<double>::max)())
limit[classes-1] = (std::numeric_limits<double>::max)();
@@ -137,7 +139,7 @@
}
template<class NumberGenerator, class Counter>
- void run(NumberGenerator f, Counter & count, int n) const
+ void run(NumberGenerator & f, Counter & count, int n) const
{
for(int i = 0; i < n; ++i) {
limits_type::const_iterator it =
@@ -150,6 +152,36 @@
limits_type limit;
};
+template<bool up, bool is_float>
+struct runs_direction_helper
+{
+ template<class T>
+ static T init(T)
+ {
+ return (std::numeric_limits<T>::max)();
+ }
+};
+
+template<>
+struct runs_direction_helper<true, true>
+{
+ template<class T>
+ static T init(T)
+ {
+ return -(std::numeric_limits<T>::max)();
+ }
+};
+
+template<>
+struct runs_direction_helper<true, false>
+{
+ template<class T>
+ static T init(T)
+ {
+ return (std::numeric_limits<T>::min)();
+ }
+};
+
// runs-up/runs-down experiment
template<bool up>
class runs_experiment : public experiment_base
@@ -157,11 +189,15 @@
public:
explicit runs_experiment(unsigned int classes) : experiment_base(classes) { }
- template<class UniformRandomNumberGenerator, class Counter>
- void run(UniformRandomNumberGenerator f, Counter & count, int n) const
+ template<class NumberGenerator, class Counter>
+ void run(NumberGenerator & f, Counter & count, int n) const
{
- typedef typename UniformRandomNumberGenerator::result_type result_type;
- result_type init = (up ? (f.min)() : (f.max)());
+ typedef typename NumberGenerator::result_type result_type;
+ result_type init =
+ runs_direction_helper<
+ up,
+ !std::numeric_limits<result_type>::is_integer
+ >::init(result_type());
result_type previous = init;
unsigned int length = 0;
for(int i = 0; i < n; ++i) {
@@ -190,19 +226,17 @@
class gap_experiment : public experiment_base
{
public:
- gap_experiment(unsigned int classes, double alpha, double beta)
- : experiment_base(classes), alpha(alpha), beta(beta) { }
+ template<class Dist>
+ gap_experiment(unsigned int classes, const Dist & dist, double alpha, double beta)
+ : experiment_base(classes), alpha(alpha), beta(beta), low(quantile(dist, alpha)), high(quantile(dist, beta)) {}
- template<class UniformRandomNumberGenerator, class Counter>
- void run(UniformRandomNumberGenerator f, Counter & count, int n) const
+ template<class NumberGenerator, class Counter>
+ void run(NumberGenerator & 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<result_type>(alpha * range);
- result_type high = static_cast<result_type>(beta * range);
+ typedef typename NumberGenerator::result_type result_type;
unsigned int length = 0;
for(int i = 0; i < n; ) {
- result_type value = f() - (f.min)();
+ result_type value = f();
if(value < low || value > high)
++length;
else {
@@ -222,6 +256,7 @@
}
private:
double alpha, beta;
+ double low, high;
};
// poker experiment
@@ -235,7 +270,7 @@
}
template<class UniformRandomNumberGenerator, class Counter>
- void run(UniformRandomNumberGenerator f, Counter & count, int n) const
+ void run(UniformRandomNumberGenerator & f, Counter & count, int n) const
{
typedef typename UniformRandomNumberGenerator::result_type result_type;
assert(std::numeric_limits<result_type>::is_integer);
@@ -282,7 +317,7 @@
}
template<class UniformRandomNumberGenerator, class Counter>
- void run(UniformRandomNumberGenerator f, Counter & count, int n) const
+ void run(UniformRandomNumberGenerator & f, Counter & count, int n) const
{
typedef typename UniformRandomNumberGenerator::result_type result_type;
assert(std::numeric_limits<result_type>::is_integer);
@@ -330,12 +365,14 @@
}
template<class UniformRandomNumberGenerator, class Counter>
- void run(UniformRandomNumberGenerator f, Counter & count, int n) const
+ void run(UniformRandomNumberGenerator & f, Counter & count, int n) const
{
typedef typename UniformRandomNumberGenerator::result_type result_type;
std::vector<result_type> v(t);
for(int i = 0; i < n; ++i) {
- std::generate_n(v.begin(), t, f);
+ for(int j = 0; j < t; ++j) {
+ v[j] = f();
+ }
int x = 0;
for(int r = t-1; r > 0; r--) {
typename std::vector<result_type>::iterator it =
@@ -360,7 +397,7 @@
}
template<class UniformRandomNumberGenerator, class Counter>
- void run(UniformRandomNumberGenerator f, Counter & count, int n_total) const
+ void run(UniformRandomNumberGenerator & f, Counter & count, int n_total) const
{
typedef typename UniformRandomNumberGenerator::result_type result_type;
assert(std::numeric_limits<result_type>::is_integer);
@@ -421,7 +458,7 @@
n_n = std::pow(static_cast<double>(n), n);
}
- double operator()(double t) const
+ double cdf(double t) const
{
if(approx) {
return 1-std::exp(-2*t*t)*(1-2.0/3.0*t/sqrt_n);
@@ -434,8 +471,8 @@
return 1 - t/n_n * sum;
}
}
- double operator()(double t1, double t2) const
- { return operator()(t2) - operator()(t1); }
+ //double operator()(double t1, double t2) const
+ //{ return operator()(t2) - operator()(t1); }
private:
bool approx;
@@ -444,6 +481,16 @@
double n_n;
};
+inline double cdf(const kolmogorov_smirnov_probability& dist, double val)
+{
+ return dist.cdf(val);
+}
+
+inline double quantile(const kolmogorov_smirnov_probability& dist, double val)
+{
+ return invert_monotone_inc(boost::bind(&cdf, dist, _1), val, 0.0, 1000.0);
+}
+
/*
* Experiments for generators with continuous distribution functions
*/
@@ -452,15 +499,15 @@
public:
kolmogorov_experiment(int n) : n(n), ksp(n) { }
template<class NumberGenerator, class Distribution>
- double run(NumberGenerator gen, Distribution distrib) const
+ double run(NumberGenerator & gen, Distribution distrib) const
{
const int m = n;
typedef std::vector<double> saved_temp;
saved_temp a(m,1.0), b(m,0);
std::vector<int> c(m,0);
for(int i = 0; i < n; ++i) {
- double val = gen();
- double y = distrib(val);
+ double val = static_cast<double>(gen());
+ double y = cdf(distrib, val);
int k = static_cast<int>(std::floor(m*y));
if(k >= m)
--k; // should not happen
@@ -484,13 +531,24 @@
}
double probability(double x) const
{
- return ksp(x);
+ return cdf(ksp, x);
}
private:
int n;
kolmogorov_smirnov_probability ksp;
};
+struct power_distribution
+{
+ power_distribution(double t) : t(t) {}
+ double t;
+};
+
+double cdf(const power_distribution& dist, double val)
+{
+ return std::pow(val, dist.t);
+}
+
// maximum-of-t test (KS-based)
template<class UniformRandomNumberGenerator>
class maximum_experiment
@@ -502,14 +560,13 @@
double operator()() const
{
- double res = ke.run(generator(f, t),
- std::bind2nd(std::ptr_fun(static_cast<double (*)(double, double)>(&std::pow)), t));
- return res;
+ generator gen(f, t);
+ return ke.run(gen, power_distribution(t));
}
private:
struct generator {
- generator(base_type & f, int t) : f(f), t(t) { }
+ generator(base_type & f, int t) : f(f, boost::uniform_01<>()), t(t) { }
double operator()()
{
double mx = f();
@@ -518,7 +575,7 @@
return mx;
}
private:
- boost::uniform_01<base_type> f;
+ boost::variate_generator<base_type&, boost::uniform_01<> > f;
int t;
};
base_type & f;
@@ -579,7 +636,18 @@
// chi_square test
template<class Experiment, class Generator>
-double run_experiment(const Experiment & experiment, Generator gen, int n)
+double run_experiment(const Experiment & experiment, Generator & gen, int n)
+{
+ generic_counter<std::vector<int> > 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));
+}
+
+// chi_square test
+template<class Experiment, class Generator>
+double run_experiment(const Experiment & experiment, const Generator & gen, int n)
{
generic_counter<std::vector<int> > v(experiment.classes());
experiment.run(gen, v, n);
@@ -595,7 +663,7 @@
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); }
+ double operator()() const { return run_experiment(experiment, generator, n); }
private:
const Experiment & experiment;
Generator & generator;
@@ -617,7 +685,7 @@
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); }
+ double operator()() const { return experiment.run(generator, distribution); }
private:
const Experiment & experiment;
Generator & generator;
Copied: branches/release/libs/random/test/validate.cpp (from r60199, /trunk/libs/random/test/validate.cpp)
==============================================================================
--- /trunk/libs/random/test/validate.cpp (original)
+++ branches/release/libs/random/test/validate.cpp 2010-03-21 20:45:06 EDT (Sun, 21 Mar 2010)
@@ -44,45 +44,45 @@
*/
// own run
-bool check(unsigned long x, const boost::mt11213b&) { return x == 3809585648U; }
+bool check_(unsigned long x, const boost::mt11213b&) { return x == 3809585648U; }
// validation by experiment from mt19937.c
-bool check(unsigned long x, const boost::mt19937&) { return x == 4123659995U; }
+bool check_(unsigned long x, const boost::mt19937&) { return x == 4123659995U; }
// validation values from the publications
-bool check(int x, const boost::minstd_rand0&) { return x == 1043618065; }
+bool check_(int x, const boost::minstd_rand0&) { return x == 1043618065; }
// validation values from the publications
-bool check(int x, const boost::minstd_rand&) { return x == 399268537; }
+bool check_(int x, const boost::minstd_rand&) { return x == 399268537; }
#if !defined(BOOST_NO_INT64_T) && !defined(BOOST_NO_INTEGRAL_INT64_T)
// by experiment from lrand48()
-bool check(unsigned long x, const boost::rand48&) { return x == 1993516219; }
+bool check_(unsigned long x, const boost::rand48&) { return x == 1993516219; }
#endif
// ????
-bool check(unsigned long x, const boost::taus88&) { return x == 3535848941U; }
+bool check_(unsigned long x, const boost::taus88&) { return x == 3535848941U; }
// ????
-bool check(int x, const boost::ecuyer1988&) { return x == 2060321752; }
+bool check_(int x, const boost::ecuyer1988&) { return x == 2060321752; }
// validation by experiment from Harry Erwin's generator.h (private e-mail)
-bool check(unsigned int x, const boost::kreutzer1986&) { return x == 139726; }
+bool check_(unsigned int x, const boost::kreutzer1986&) { return x == 139726; }
-bool check(double x, const boost::lagged_fibonacci607&) { return std::abs(x-0.401269) < 1e-5; }
+bool check_(double x, const boost::lagged_fibonacci607&) { return std::abs(x-0.401269) < 1e-5; }
// principal operation validated with CLHEP, values by experiment
-bool check(unsigned long x, const boost::ranlux3&) { return x == 5957620; }
-bool check(unsigned long x, const boost::ranlux4&) { return x == 8587295; }
+bool check_(unsigned long x, const boost::ranlux3&) { return x == 5957620; }
+bool check_(unsigned long x, const boost::ranlux4&) { return x == 8587295; }
-bool check(float x, const boost::ranlux3_01&)
+bool check_(float x, const boost::ranlux3_01&)
{ return std::abs(x-5957620/std::pow(2.0f,24)) < 1e-6; }
-bool check(float x, const boost::ranlux4_01&)
+bool check_(float x, const boost::ranlux4_01&)
{ return std::abs(x-8587295/std::pow(2.0f,24)) < 1e-6; }
-bool check(double x, const boost::ranlux64_3_01&)
+bool check_(double x, const boost::ranlux64_3_01&)
{ return std::abs(x-0.838413) < 1e-6; }
-bool check(double x, const boost::ranlux64_4_01&)
+bool check_(double x, const boost::ranlux64_4_01&)
{ return std::abs(x-0.59839) < 1e-6; }
template<class PRNG>
@@ -94,7 +94,7 @@
rng();
typename PRNG::result_type val = rng();
// make sure the validation function is a static member
- bool result = check(val, rng);
+ bool result = check_(val, rng);
// allow for a simple eyeball check for MSVC instantiation brokenness
// (if the numbers for all generators are the same, it's obviously broken)
Deleted: branches/release/libs/random/validate.cpp
==============================================================================
--- branches/release/libs/random/validate.cpp 2010-03-21 20:45:06 EDT (Sun, 21 Mar 2010)
+++ (empty file)
@@ -1,131 +0,0 @@
-/* boost validate.cpp
- *
- * Copyright Jens Maurer 2000
- * Distributed under the Boost Software License, Version 1.0. (See
- * accompanying file LICENSE_1_0.txt or copy at
- * http://www.boost.org/LICENSE_1_0.txt)
- *
- * $Id$
- */
-
-#if defined(BOOST_MSVC) && BOOST_MSVC <= 1300
-#pragma warning( disable : 4786 )
-#endif
-
-#include <iostream>
-#include <sstream>
-#include <string>
-#include <cmath>
-#include <iterator>
-#include <vector>
-#include <boost/random.hpp>
-#include <boost/config.hpp>
-
-#include <boost/test/test_tools.hpp>
-#include <boost/test/included/test_exec_monitor.hpp>
-
-#ifdef BOOST_NO_STDC_NAMESPACE
- namespace std { using ::abs; using ::fabs; using ::pow; }
-#endif
-
-
-/*
- * General portability note:
- * MSVC mis-compiles explicit function template instantiations.
- * For example, f<A>() and f<B>() are both compiled to call f<A>().
- * 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
- */
-
-// own run
-bool check(unsigned long x, const boost::mt11213b&) { return x == 3809585648U; }
-
-// validation by experiment from mt19937.c
-bool check(unsigned long x, const boost::mt19937&) { return x == 4123659995U; }
-
-// validation values from the publications
-bool check(int x, const boost::minstd_rand0&) { return x == 1043618065; }
-
-// validation values from the publications
-bool check(int x, const boost::minstd_rand&) { return x == 399268537; }
-
-#if !defined(BOOST_NO_INT64_T) && !defined(BOOST_NO_INTEGRAL_INT64_T)
-// by experiment from lrand48()
-bool check(unsigned long x, const boost::rand48&) { return x == 1993516219; }
-#endif
-
-// ????
-bool check(unsigned long x, const boost::taus88&) { return x == 3535848941U; }
-
-// ????
-bool check(int x, const boost::ecuyer1988&) { return x == 2060321752; }
-
-// validation by experiment from Harry Erwin's generator.h (private e-mail)
-bool check(unsigned int x, const boost::kreutzer1986&) { return x == 139726; }
-
-bool check(double x, const boost::lagged_fibonacci607&) { return std::abs(x-0.401269) < 1e-5; }
-
-// principal operation validated with CLHEP, values by experiment
-bool check(unsigned long x, const boost::ranlux3&) { return x == 5957620; }
-bool check(unsigned long x, const boost::ranlux4&) { return x == 8587295; }
-
-bool check(float x, const boost::ranlux3_01&)
-{ return std::abs(x-5957620/std::pow(2.0f,24)) < 1e-6; }
-bool check(float x, const boost::ranlux4_01&)
-{ return std::abs(x-8587295/std::pow(2.0f,24)) < 1e-6; }
-
-bool check(double x, const boost::ranlux64_3_01&)
-{ return std::abs(x-0.838413) < 1e-6; }
-bool check(double x, const boost::ranlux64_4_01&)
-{ return std::abs(x-0.59839) < 1e-6; }
-
-template<class PRNG>
-void validate(const std::string & name, const PRNG &)
-{
- std::cout << "validating " << name << ": ";
- PRNG rng; // default ctor
- for(int i = 0; i < 9999; i++)
- rng();
- typename PRNG::result_type val = rng();
- // make sure the validation function is a static member
- bool result = check(val, rng);
-
- // 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_CHECK(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("mt11213b", mt11213b());
- validate("mt19937", mt19937());
- validate("kreutzer1986", kreutzer1986());
- validate("ranlux3", ranlux3());
- validate("ranlux4", ranlux4());
- validate("ranlux3_01", ranlux3_01());
- validate("ranlux4_01", ranlux4_01());
- validate("ranlux64_3_01", ranlux64_3_01());
- validate("ranlux64_4_01", ranlux64_4_01());
- validate("taus88", taus88());
- validate("lagged_fibonacci607", lagged_fibonacci607());
-}
-
-int test_main(int, char*[])
-{
- validate_all();
- return 0;
-}
Deleted: branches/release/libs/random/wg21-proposal.html
==============================================================================
--- branches/release/libs/random/wg21-proposal.html 2010-03-21 20:45:06 EDT (Sun, 21 Mar 2010)
+++ (empty file)
@@ -1,3608 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
-
-<html>
-<head>
- <meta http-equiv="Content-Language" content="en-us">
- <meta http-equiv="Content-Type" content="text/html; charset=us-ascii">
-
- <title>A Proposal to Add an Extensible Random Number Facility to the
- Standard Library</title>
-</head>
-
-<body bgcolor="#FFFFFF" text="#000000">
- <font size="-1">Jens Maurer <Jens.Maurer_at_[hidden]><br>
- 2002-11-10<br>
- Document N1398=02-0056</font>
-
- <p><font size="-1"><code>$Id: proposal.html,v 1.44 2002/11/10 20:42:15
- jmaurer Exp $</code></font></p>
-
- <h1>A Proposal to Add an Extensible Random Number Facility to the Standard
- Library (N1398)</h1>
-
- <blockquote>
- Any one who considers arithmetical methods of producing random digits is,
- of course, in a state of sin.
- </blockquote>
-
- <p align="right">John von Neumann, 1951</p>
-
- <h2>Revision history</h2>
-
- <ul>
- <li>2002-11-10: Publication in the Post-Santa Cruz mailing.</li>
-
- <li>The <code>seed(first, last)</code> interface now needs "unsigned
- long" values.</li>
-
- <li>Introduce "variate_generator", adjust distribution interface
- accordingly.</li>
-
- <li>Add "add-on packages" discussion.</li>
-
- <li>All distribution parameters must be defaulted.</li>
-
- <li>Add "target audience" subsection to "motivation" section.</li>
-
- <li>Add discussion of manager class.</li>
-
- <li>Engines are independent of distributions, thus consider respective
- lifetimes.</li>
-
- <li>Add "sharing of engines" as a major requirement.</li>
-
- <li>Add some open issues.</li>
-
- <li>2002-10-11: First publication on the C++ committee's library
- reflector.</li>
- </ul>
-
- <h2>I. Motivation</h2>
-
- <blockquote>
- <i>Why is this important? What kinds of problems does it address, and
- what kinds of programmers, is it intended to support? Is it based on
- existing practice?</i>
- </blockquote>Computers are deterministic machines by design: equal input
- data results in equal output, given the same internal state. Sometimes,
- applications require seemingly non-deterministic behaviour, usually
- provided by generating random numbers. Such applications include:
-
- <ul>
- <li>numerics (simulation, Monte-Carlo integration)</li>
-
- <li>games (shuffling card decks, non-deterministic enemy behavior)</li>
-
- <li>testing (generation of test input data for good coverage)</li>
-
- <li>security (generation of cryptographic keys)</li>
- </ul>
-
- <p>Programmers in all of the above areas have to find ways to generate
- random numbers. However, the difficulty to find generators that are both
- efficient and have good quality is often underestimated, and so ad-hoc
- implementations often fail to meet either or both of these goals.</p>
-
- <p>The C++ standard library includes <code>std::rand</code>, inherited from
- the C standard library, as the only facility to generate pseudo-random
- numbers. It is underspecified, because the generation function is not
- defined, and indeed early C standard library implementations provided
- surprisingly bad generators. Furthermore, the interface relies on global
- state, making it difficult or inefficient to provide for correct operation
- for simultaneous invocations in multi-threaded applications.</p>
-
- <p>There is a lot of existing practice in this area. A multitude of
- libraries, usually implemented in C or Fortran, is available from the
- scientific community. Some implement just one random number engine, others
- seek to provide a full framework. I know of no comprehensive C++ framework
- for generating random numbers that adheres to the design principles put
- forth in section III.</p>
-
- <p>Random number generators are appropriate for this TR because they fall
- into one of the domains (numerics) identified in N1314 as a target for the
- TR.</p>
-
- <h3>Target Audience</h3>There are several different kinds of programmers
- that are assumed to use the facilities provided in this proposal.
-
- <ul>
- <li>programmers that provide additional engines</li>
-
- <li>programmers that provide additional distributions</li>
-
- <li>programmers that provide generic add-on packages</li>
-
- <li>programmers that need random numbers</li>
- </ul>This proposal specifies an infrastructure so that the needs of all
- four groups are met. The first two groups benefit from a modular design so
- that they can plug in their contributions. Providing add-on packages
- benefits from a design that suits to generic programming needs. Finally,
- users in need of random numbers benefit from an interface to the package
- that is easy to use.
-
- <h2>II. Impact On the Standard</h2>
-
- <blockquote>
- <i>What does it depend on, and what depends on it? Is it a pure
- extension, or does it require changes to standard components? Does it
- require core language changes?</i>
- </blockquote>This proposal is a pure library extension. It does not require
- changes to any standard classes or functions. It does not require changes
- to any of the standard requirement tables. It does not require any changes
- in the core language, and it has been implemented in standard C++ as per
- ISO 14882:1998.
-
- <p>The ISO C99 extension that specify integral types having a given minimum
- or exact bitwidth (e.g. <code>int32_t</code>) aids in implementing this
- proposal, however these types (or the equivalent thereof under another
- name) can be defined with template metaprogramming in standard C++, so
- these are not strictly necessary.</p>
-
- <p>In case the ISO C99 extensions become part of the TR, section IV should
- be reviewed whether some requirements could be reformulated with the ISO
- C99 extensions.</p>
-
- <p>In case a standard reference-counted smart pointer becomes part of the
- TR, section IV should be reviewed and instances of the smart pointer be
- added to the acceptable template parameters for a
- <code>variate_generator</code>.</p>
-
- <h2>III. Design Decisions</h2>
-
- <blockquote>
- <i>Why did you choose the specific design that you did? What alternatives
- did you consider, and what are the tradeoffs? What are the consequences
- of your choice, for users and implementors? What decisions are left up to
- implementors? If there are any similar libraries in use, how do their
- design decisions compare to yours?</i>
- </blockquote>The design decisions are compared to those in the following
- libraries:
-
- <ul>
- <li>CLHEP (original at http://wwwinfo.cern.ch/asd/lhc++/clhep/index.html,
- modifications from FermiLab at (anonymous CVS)
- :pserver:anonymous_at_[hidden]:/usr/people/cvsuser/repository)</li>
-
- <li>crng 1.1: Random-number generators (RNGs) implemented as Python
- extension types coded in C (at http://www.sbc.su.se/~per/crng/)</li>
-
- <li>Swarm 2.1.1 (multi-agent simulation of complex systems), random
- number package, using a Smalltalk-like programming language (at
- http://www.santafe.edu/projects/swarm/swarmdocs/set/swarm.random.sgml.reference.html)</li>
-
- <li>GNU Scientific Library: general scientific computing library
- implemented in C, comprehensive coverage of random number engines and
- distributions (at http://sources.redhat.com/gsl)</li>
- </ul>The choice of engines and distributions is also contrasted against the
- following literature:
-
- <ul>
- <li>Donald E. Knuth, "The Art of Computer Programming Vol. 2"</li>
-
- <li>William H. Press et al., "Numerical Recipes in C"</li>
- </ul>
-
- <h3>A. Overview on Requirements</h3>Here is a short overview on the
- requirements for the random number framework.
-
- <ul>
- <li>allows users to choose in speed / size / quality trade-offs</li>
-
- <li>has a tight enough specification to get reliable cross-platform
- results</li>
-
- <li>allows storage of state on non-volatile media (e.g., in a disk file)
- to resume computation later</li>
-
- <li>does not impede sequence "jump-ahead" for parallel computation</li>
-
- <li>provides a variety of base engines, not just one</li>
-
- <li>allows the user to write its own base engines and use it with the
- library-provided distributions</li>
-
- <li>provides the most popular distributions</li>
-
- <li>allows the user to write its own distributions and use it with the
- library-provided engines</li>
-
- <li>allows sharing of engines by several distributions</li>
-
- <li>does not prevent implementations with utmost efficiency</li>
-
- <li>provides both pseudo-random number engines (for simulations etc.) and
- "true" non-deterministic random numbers (for cryptography)</li>
- </ul>All of the requirements are revisited in detail in the following
- sections.
-
- <h3>B. Pseudo-Random vs. Non-Deterministic Random Numbers</h3>This section
- tries to avoid philosophical discussions about randomness as much as
- possible, a certain amount of intuition is assumed.
-
- <p>In this proposal, a <em>pseudo-random number engine</em> is defined as
- an initial internal state x(0), a function f that moves from one internal
- state to the next x(i+1) := f(x(i)), and an output function o that produces
- the output o(x(i)) of the generator. This is an entirely deterministic
- process, it is determined by the initial state x(0) and functions f and o
- only. The initial state x(0) is determined from a seed. Apparent randomness
- is achieved only because the user has limited perception.</p>
-
- <p>A <em>non-deterministic random-number engine</em> provides a sequence of
- random numbers x(i) that cannot be foreseen. Examples are certain
- quantum-level physics experiments, measuring the time difference between
- radioactive decay of individual atoms or noise of a Zehner diode.
- Relatively unforeseeable random sources are also (the low bits of) timing
- between key touches, mouse movements, Ethernet packet arrivals, etc. An
- estimate for the amount of unforeseeability is the entropy, a concept from
- information theory. Completely foreseeable sequences (e.g., from
- pseudo-random number engines) have entropy 0, if all bits are
- unforeseeable, the entropy is equal to the number of bits in each
- number.</p>
-
- <p>Pseudo-random number engines are usually much faster than
- non-deterministic random-number engines, because the latter require I/O to
- query some randomness device outside of the computer. However, there is a
- common interface feature subset of both pseudo-random and non-deterministic
- random-number engines. For example, a non-deterministic random-number
- engine could be employed to produce random numbers with normal
- distribution; I believe this to be an unlikely scenario in practice.</p>
-
- <p>Other libraries, including those mentioned above, only provide either
- pseudo-random numbers, suitable for simulations and games, or
- non-deterministic random numbers, suitable for cryptographic
- applications.</p>
-
- <h3>C. Separation of Engines and Distributions</h3>Random-number generation
- is usually conceptually separated into <em>random-number engines</em> that
- produce uniformly distributed random numbers between a given minimum and
- maximum and <em>random-number distributions</em> that retrieve uniformly
- distributed random numbers from some engine and produce numbers according
- to some distribution (e.g., Gaussian normal or Bernoulli distribution).
- Returning to the formalism from section A, the former can be identified
- with the function f and the latter with the output function o.
-
- <p>This proposal honours this conceptual separation, and provides a class
- template to merge an arbitrary engine with an arbitrary distribution on
- top. To this end, this proposal sets up requirements for engines so that
- each of them can be used to provide uniformly distributed random numbers
- for any of the distributions. The resulting freedom of combination allows
- for the utmost re-use.</p>
-
- <p>Engines have usually been analyzed with all mathematical and empirical
- tools currently available. Nonetheless, those tools show the absence of a
- particular weakness only, and are not exhaustive. Albeit unlikely, a new
- kind of test (for example, a use of random numbers in a new kind of
- simulation or game) could show serious weaknesses in some engines that were
- not known before.</p>
-
- <p>This proposal attempts to specify the engines precisely; two different
- implementations, with the same seed, should return the same output
- sequence. This forces implementations to use the well-researched engines
- specified hereinafter, and users can have confidence in their quality and
- the limits thereof.</p>
-
- <p>On the other hand, the specifications for the distributions only define
- the statistical result, not the precise algorithm to use. This is different
- from engines, because for distribution algorithms, rigorous proofs of their
- correctness are available, usually under the precondition that the input
- random numbers are (truely) uniformly distributed. For example, there are
- at least a handful of algorithms known to produce normally distributed
- random numbers from uniformly distributed ones. Which one of these is most
- efficient depends on at least the relative execution speeds for various
- transcendental functions, cache and branch prediction behaviour of the CPU,
- and desired memory use. This proposal therefore leaves the choice of the
- algorithm to the implementation. It follows that output sequences for the
- distributions will not be identical across implementations. It is expected
- that implementations will carefully choose the algorithms for distributions
- up front, since it is certainly surprising to customers if some
- distribution produces different numbers from one implementation version to
- the next.</p>
-
- <p>Other libraries usually provide the same differentiation between engines
- and distributions. Libraries rarely have a wrapper around both engine and
- distribution, but it turns out that this can hide some complexities from
- the authors of distributions, since some facitilies need to be provided
- only once. A previous version of this proposal had distributions directly
- exposed to the user, and the distribution type dependent on the engine
- type. In various discussions, this was considered as too much coupling.</p>
-
- <p>Since other libraries do not aim to provide a portable specification
- framework, engines are sometimes only described qualitatively without
- giving the exact parameterization. Also, distributions are given as
- specific functions or classes, so the quality-of-implementation question
- which distribution algorithm to employ does not need to be addressed.</p>
-
- <h3>D. Templates vs. Virtual Functions</h3>The layering sketched in the
- previous subsection can be implemented by either a template mechanism or by
- using virtual functions in a class hierarchy. This proposal uses templates.
- Template parameters are usually some base type and values denoting fixed
- parameters for the functions f and o, e.g. a word size or modulus.
-
- <p>For virtual functions in a class hierarchy, the core language requires a
- (nearly) exact type match for a function in a derived classes overriding a
- function in a base class. This seems to be unnecessarily restrictive,
- because engines can sometimes benefit from using different integral base
- types. Also, with current compiler technology, virtual functions prevent
- inlining when a pointer to the base class is used to call a virtual
- function that is overridden in some derived class. In particular with
- applications such as simulations that sometimes use millions of
- pseudo-random numbers per second, losing significant amounts of performance
- due to missed inlining opportunities appears to not be acceptable.</p>
-
- <p>The CLHEP library bases all its engines on the abstract base class
- <code>HepRandomEngine</code>. Specific engines derive from this class and
- override its pure virtual functions. Similarly, all distributions are based
- on the base class <code>HepRandom</code>. Specific distributions derive
- from this class, override operator(), and provide a number of specific
- non-virtual functions.</p>
-
- <p>The GNU Scientific Library, while coded in C, adheres to the principles
- of object-structuring; all engines can be used with any of the
- distributions. The technical implementation is by mechanisms similar to
- virtual functions.</p>
-
- <h3>E. Parameterization and Initialization for Engines</h3>Engines usually
- have a "base" type which is used to store its internal state. Also, they
- usually have a choice of parameters. For example, a linear congruential
- engine is defined by x(i+1) = (a*x(i)+c) mod m, so f(x) = (a*x+c) mod m;
- the base type is "int" and parameters are a, c, and m. Finding parameters
- for a given function f that make for good randomness in the resulting
- engine's generated numbers x(i) requires extensive and specialized
- mathematical training and experience. In order to make good random numbers
- available to a large number of library users, this proposal not only
- defines generic random-number engines, but also provides a number of
- predefined well-known good parameterizations for those. Usually, there are
- only a few (less than five) well-known good parameterizations for each
- engine, so it appears feasible to provide these.
-
- <p>Since random-number engines are mathematically designed with computer
- implementation in mind, parameters are usually integers representable in a
- machine word, which usually coincides nicely with a C++ built-in type. The
- parameters could either be given as (compile-time) template arguments or as
- (run-time) constructor arguments.</p>
-
- <p>Providing parameters as template arguments allows for providing
- predefined parameterizations as simple "typedef"s. Furthermore, the
- parameters appear as integral constants, so the compiler can value-check
- the given constants against the engine's base type. Also, the library
- implementor can choose different implementations depending on the values of
- the parameters, without incurring any runtime overhead. For example, there
- is an efficient method to compute (a*x) mod m, provided that a certain
- magnitude of m relative to the underlying type is not exceeded.
- Additionally, the compiler's optimizer can benefit from the constants and
- potentially produce better code, for example by unrolling loops with fixed
- loop count.</p>
-
- <p>As an alternative, providing parameters as constructor arguments allows
- for more flexibility for the library user, for example when experimenting
- with several parameterizations. Predefined parameterizations can be
- provided by defining wrapper types which default the constructor
- parameters.</p>
-
- <p>Other libraries have hard-coded the parameters of their engines and do
- not allow the user any configuration of them at all. If the user wishes to
- change the parameters, he has to re-implement the engine's algorithm. In my
- opinion, this approach unnecessarily restricts re-use.</p>
-
- <p>Regarding initialization, this proposal chooses to provide
- "deterministic seeding" with the default constructor and the
- <code>seed</code> function without parameters: Two engines constructed
- using the default constructor will output the same sequence. In contrast,
- the CLHEP library's default constructed engines will take a fresh seed from
- a seed table for each instance. While this approach may be convenient for a
- certain group of users, it relies on global state and can easily be
- emulated by appropriately wrapping engines with deterministic seeding.</p>
-
- <p>In addition to the default constructor, all engines provide a
- constructor and <code>seed</code> function taking an iterator range
- [it1,it2) pointing to unsigned integral values. An engine initializes its
- state by successively consuming values from the iterator range, then
- returning the advanced iterator it1. This approach has the advantage that
- the user can completely exploit the large state of some engines for
- initialization. Also, it allows to initialize compound engines in a uniform
- manner. For example, a compound engine consisting of two simpler engines
- would initialize the first engine with its [it1,it2). The first engine
- returns a smaller iterator range that it has not consumed yet. This can be
- used to initialize the second engine.</p>
-
- <p>The iterator range [it1,it2) is specified to point to unsigned long
- values. There is no way to determine from a generic user program how the
- initialization values will be treated and what range of bits must be
- provided, except by enumerating all engines, e.g. in template
- specializations. The problem is that a given generator might have differing
- requirements on the values of the seed range even within one
- <code>seed</code> call.</p>
-
- <p>For example, imagine a</p>
- <pre>
- xor_combine<lagged_fibonacci<...>, mersenne_twister<...> >
-</pre>generator. For this, <code>seed(first, last)</code> will consume values
-as follows: First, seed the state of the <code>lagged_fibonacci</code>
-generator by consuming one item from [first, last) for each word of state.
-The values are reduced to (e.g.) 24 bits to fit the
-<code>lagged_fibonacci</code> state requirements. Then, seed the state of the
-<code>mersenne_twister</code> by consuming some number of items from the
-remaining [first, last). The values are reduced to 32 bits to fit the <code>
- mersenne_twister</code> state requirements.
-
- <p>How does a concise programming interface for those increasingly complex
- and varying requirements on [first, last) look like? I don't know, and I
- don't want to complicate the specification by inventing something
- complicated here.</p>
-
- <p>Thus, the specification says for each generator how it uses the seed
- values, and how many are consumed. Additional features are left to the
- user.</p>
-
- <p>In a way, this is similar to STL containers: It is intended that the
- user can exchange iterators to various containers in generic algorithms,
- but the container itself is not meant to be exchanged, i.e. having a
- Container template parameter is often not adequate. That is analogous to
- the random number case: The user can pass an engine around and use its
- <code>operator()</code> and <code>min</code> and <code>max</code> functions
- generically. However, the user can't generically query the engine
- attributes and parameters, simply because most are entirely different in
- semantics for each engine.</p>
-
- <p>The <code>seed(first, last)</code> interface can serve two purposes:</p>
-
- <ol>
- <li>In a generic context, the user can pass several integer values >=
- 1 for seeding. It is unlikely that the user explores the full state space
- with the seeds she provides, but she can be reasonably sure that her
- seeds aren't entirely incorrect. (There is no formal guarantee for that,
- except that the ability to provide bad seeds usually means the
- parameterization of the engine is bad, e.g. a non-prime modulus for a
- linear congruential engine.) For example, if the user wants a
- <code>seed(uint32_t)</code> on top of <code>seed(first, last)</code>, one
- option is to use a <code>linear_congruential</code> generator that
- produces the values required for <code>seed(first, last)</code>. When the
- user defines the iterator type for <code>first</code> and
- <code>last</code> so that it encapsulates the
- <code>linear_congruential</code> engine in <code>operator++</code>, the
- user doesn't even need to know beforehand how many values
- <code>seed(first, last)</code> will need.</li>
-
- <li>If the user is in a non-generic context, he knows the specific
- template type of the engine (probably not the template value-based
- parameterization, though). The precise specification for
- <code>seed(first, last)</code> allows to know what values need to be
- passed in so that a specific initial state is attained, for example to
- compare one implementation of the engine with another one that uses
- different seeding.</li>
-
- <li>If the user requires both, he needs to inject knowledge into (1) so
- that he is in the position of (2). One way to inject the knowledge is to
- use (partial) template specialization to add the knowledge. The specific
- parameterization of some engine can then be obtained by querying the data
- members of the engines.</li>
- </ol>
-
- <p>I haven't seen the iterator-based approach to engine initialization in
- other libraries; most initialization approaches rely on a either a single
- value or on per-engine specific approaches to initialization.</p>
-
- <p>An alternative approach is to pass a zero-argument function object
- ("generator") for seeding. It is trivial to implement a generator from a
- given iterator range, but it is more complicated to implement an iterator
- range from a generator. Also, the exception object that is specified to be
- thrown when the iterator range is exhausted could be configured in a
- user-provided iterator to generator mapping. With this approach, some
- engines would have three one-argument constructors: One taking a single
- integer for seeding, one taking a (reference?) to a (templated) generator,
- and the copy constructor. It appears that the opportunities for ambiguities
- or choosing the wrong overload are too confusing to the unsuspecting
- user.</p>
-
- <h3>F. Parameterization and Initialization for Distributions</h3>The
- distributions specified in this proposal have template parameters that
- indicate the output data type (e.g. <code>float</code>,
- <code>double</code>, <code>long double</code>) that the user desires.
-
- <p>The probability density functions of distributions usually have
- parameters. These are mapped to constructor parameters, to be set at
- runtime by the library user according to her requirements. The parameters
- for a distribution object cannot change after its construction. When
- constructing the distribution, this allows to pre-compute some data
- according to the parameters given without risk of inadvertently
- invalidating them later.</p>
-
- <p>Distributions may implement <code>operator()(T x)</code>, for arbitrary
- type <code>T</code>, to meet special needs, for example a "one-shot" mode
- where each invocation uses different distribution parameters.</p>
-
- <h3>G. Properties as Traits vs. In-Class Constants</h3>Users might wish to
- query compile-time properties of the engines and distributions, e.g. their
- base types, constant parameters, etc. This is similar to querying the
- properties of the built-in types such as <code>double</code> using
- <code>std::numeric_limits<></code>. However, engines and
- distributions cannot be simple types, so it does not appear to be necessary
- to separate the properties into separate traits classes. Instead,
- compile-time properties are given as members types and static member
- constants.
-
- <h3>H. Which Engines to Include</h3>There is a multitude of pseudo-random
- number engines available in both literature and code. Some engines, such as
- Mersenne Twister, have an independent algorithm ("base engine"). Others
- change the values or order of output of other engines to improve
- randomness, for example Knuth's "Algorithm B" ("compound engine"). The
- template mechanism allows easy combination of base and compound engines.
-
- <p>Engines may be categorized according to the following dimensions.</p>
-
- <ul>
- <li>integers or floating-point numbers produced (Some engines produce
- uniformly distributed integers in the range [min,max], however, most
- distribution functions expect uniformly distributed floating-point
- numbers in the range [0,1) as the input sequence. The obvious conversion
- requires a relatively costly integer to floating-point conversion plus a
- floating-point multiplication by (max-min+1)<sup>-1</sup> for each random
- number used. To save the multiplication, some engines can directly
- produce floating-point numbers in the range [0,1) by maintaining the
- state x(i) in an appropriately normalized form, given a sufficiently good
- implementation of basic floating-point operations (e.g. IEEE 754).</li>
-
- <li>quality of random numbers produced (What is the cycle length? Does
- the engine pass all relevant statistical tests? Up to what dimension are
- numbers equidistributed?)</li>
-
- <li>speed of generation (How many and what kind of operations have to be
- performed to produce one random number, on average?)</li>
-
- <li>size of state (How may machine words of storage are required to hold
- the state x(i) of the random engine?)</li>
-
- <li>option for independent subsequences (Is it possible to move from x(i)
- to x(i+k) with at most O(log(k)) steps? This allows to efficiently use
- subsequences x(0)...x(k-1), x(k)...x(2k-1), ..., x(jk)...x((j+1)k-1),
- ..., for example for parallel computation, where each of the m processors
- gets assigned the (independent) subsequence starting at x(jk) (0 <= k
- < m).)</li>
- </ul>According to the criteria above, the engines given below were chosen.
- The quality and size indications were completed according to best known
- parameterizations. Other parameterizations usually yield poorer quality
- and/or less size.
-
- <table border="1" summary="">
- <tr>
- <th>engine</th>
-
- <th>int / float</th>
-
- <th>quality</th>
-
- <th>speed</th>
-
- <th>size of state</th>
-
- <th>subsequences</th>
-
- <th>comments</th>
- </tr>
-
- <tr>
- <td>linear_congruential</td>
-
- <td>int</td>
-
- <td>medium</td>
-
- <td>medium</td>
-
- <td>1 word</td>
-
- <td>yes</td>
-
- <td>cycle length is limited to the maximum value representable in one
- machine word, passes most statisticial tests with chosen
- parameters.</td>
- </tr>
-
- <tr>
- <td>mersenne_twister</td>
-
- <td>int</td>
-
- <td>good</td>
-
- <td>fast</td>
-
- <td>624 words</td>
-
- <td>no</td>
-
- <td>long cycles, passes all statistical tests, good equidistribution in
- high dimensions</td>
- </tr>
-
- <tr>
- <td>subtract_with_carry</td>
-
- <td>both</td>
-
- <td>medium</td>
-
- <td>fast</td>
-
- <td>25 words</td>
-
- <td>no</td>
-
- <td>very long cycles possible, fails some statistical tests. Can be
- improved with the discard_block compound engine.</td>
- </tr>
-
- <tr>
- <td>discard_block</td>
-
- <td>both</td>
-
- <td>good</td>
-
- <td>slow</td>
-
- <td>base engine + 1 word</td>
-
- <td>no</td>
-
- <td>compound engine that removes correlation provably by throwing away
- significant chunks of the base engine's sequence, the resulting speed
- is reduced to 10% to 3% of the base engine's.</td>
- </tr>
-
- <tr>
- <td>xor_combine</td>
-
- <td>int</td>
-
- <td>good</td>
-
- <td>fast</td>
-
- <td>base engines</td>
-
- <td>yes, if one of the base engines</td>
-
- <td>compound engine that XOR-combines the sequences of two base
- engines</td>
- </tr>
- </table>
-
- <p>Some engines were considered for inclusion, but left out for the
- following reasons:</p>
-
- <table border="1" summary="">
- <tr>
- <th>engine</th>
-
- <th>int / float</th>
-
- <th>quality</th>
-
- <th>speed</th>
-
- <th>size of state</th>
-
- <th>subsequences</th>
-
- <th>comments</th>
- </tr>
-
- <tr>
- <td>shuffle_output</td>
-
- <td>int</td>
-
- <td>good</td>
-
- <td>fast</td>
-
- <td>base engine + 100 words</td>
-
- <td>no</td>
-
- <td>compound engine that reorders the base engine's output, little
- overhead for generation (one multiplication)</td>
- </tr>
-
- <tr>
- <td>lagged_fibonacci</td>
-
- <td>both</td>
-
- <td>medium</td>
-
- <td>fast</td>
-
- <td>up to 80,000 words</td>
-
- <td>no</td>
-
- <td>very long cycles possible, fails birthday spacings test. Same
- principle of generation as <code>subtract_with_carry</code>, i.e. x(i)
- = x(i-s) (*) x(i-r), where (*) is either of +, -, xor with or without
- carry.</td>
- </tr>
-
- <tr>
- <td>inversive_congruential (Hellekalek 1995)</td>
-
- <td>int</td>
-
- <td>good</td>
-
- <td>slow</td>
-
- <td>1 word</td>
-
- <td>no</td>
-
- <td>x(i+1) = a x(i)<sup>-1</sup> + c. Good equidistribution in several
- dimensions. Provides no apparent advantage compared to ranlux; the
- latter can produce floating-point numbers directly.</td>
- </tr>
-
- <tr>
- <td>additive_combine (L'Ecuyer 1988)</td>
-
- <td>int</td>
-
- <td>good</td>
-
- <td>medium</td>
-
- <td>2 words</td>
-
- <td>yes</td>
-
- <td>Combines two linear congruential generators. Same principle of
- combination as <code>xor_combine</code>, i.e. z(i) = x(i) (*) y(i),
- where (*) is one of +, -, xor.</td>
- </tr>
-
- <tr>
- <td>R250 (Kirkpatrick and Stoll)</td>
-
- <td>int</td>
-
- <td>bad</td>
-
- <td>fast</td>
-
- <td>~ 20 words</td>
-
- <td>no</td>
-
- <td>General Feedback Shift Register with two taps: Easily exploitable
- correlation.</td>
- </tr>
-
- <tr>
- <td>linear_feedback_shift</td>
-
- <td>int</td>
-
- <td>medium</td>
-
- <td>fast</td>
-
- <td>1 word</td>
-
- <td>no</td>
-
- <td>cycle length is limited to the maximum value representable in one
- machine word, fails some statistical tests, can be improved with the
- xor_combine compound engine.</td>
- </tr>
- </table>
-
- <p>The GNU Scientific Library and Swarm have additional engine that are not
- mentioned in the table below.</p>
-
- <table border="1" summary="">
- <tr>
- <th>Engine</th>
-
- <th>this proposal</th>
-
- <th>CLHEP</th>
-
- <th>crng</th>
-
- <th>GNU Scientific Library</th>
-
- <th>Swarm</th>
-
- <th>Numerical Recipes</th>
-
- <th>Knuth</th>
- </tr>
-
- <tr>
- <td>LCG(2<sup>31</sup>-1, 16807)</td>
-
- <td>minstd_rand0</td>
-
- <td>-</td>
-
- <td>ParkMiller</td>
-
- <td>ran0, minstd</td>
-
- <td>-</td>
-
- <td>ran0</td>
-
- <td>p106, table 1, line 19</td>
- </tr>
-
- <tr>
- <td>LCG(2<sup>32</sup>, a=1664525, c=1013904223)</td>
-
- <td>linear_congruential< ..., 1664525, 1013904223, (1 << 32)
- ></td>
-
- <td>-</td>
-
- <td>-</td>
-
- <td>-</td>
-
- <td>LCG1gen</td>
-
- <td>-</td>
-
- <td>p106, table 1, line 16</td>
- </tr>
-
- <tr>
- <td>LCG1 + LCG2 + LCG3</td>
-
- <td>-</td>
-
- <td>-</td>
-
- <td>WichmannHill</td>
-
- <td>-</td>
-
- <td>-</td>
-
- <td>-</td>
-
- <td>-</td>
- </tr>
-
- <tr>
- <td>(LCG1 - LCG2 + LCG3 - LCG4) mod m0</td>
-
- <td>-</td>
-
- <td>-</td>
-
- <td>-</td>
-
- <td>-</td>
-
- <td>C4LCGXgen</td>
-
- <td>-</td>
-
- <td>-</td>
- </tr>
-
- <tr>
- <td>LCG(2<sup>31</sup>-1, 16807) with Bays/Durham shuffle</td>
-
- <td>shuffle_output<minstd_rand0, 32> (shuffle_output not in this
- proposal)</td>
-
- <td>-</td>
-
- <td>-</td>
-
- <td>ran1</td>
-
- <td>PMMLCG1gen</td>
-
- <td>ran1</td>
-
- <td>Algorithm "B"</td>
- </tr>
-
- <tr>
- <td>(LCG(2<sup>31</sup>-85, 40014) + LCG(2<sup>31</sup>-249, 40692))
- mod 2<sup>31</sup>-85</td>
-
- <td>ecuyer1988 (additive_combine not in this proposal)</td>
-
- <td>Ranecu</td>
-
- <td>LEcuyer</td>
-
- <td>-</td>
-
- <td>C2LCGXgen</td>
-
- <td>-</td>
-
- <td>-</td>
- </tr>
-
- <tr>
- <td>(LCG(2<sup>31</sup>-85, 40014) with Bays/Durham shuffle +
- LCG(2<sup>31</sup>-249, 40692)) mod 2<sup>31</sup>-85</td>
-
- <td>additive_combine< shuffle_output<<br>
- linear_congruential<int, 40014, 0, 2147483563>, 32>,<br>
- linear_congruential<int, 40692, 0, 2147483399> >
- (additive_combine and shuffle_output not in this proposal)</td>
-
- <td>-</td>
-
- <td>-</td>
-
- <td>ran2</td>
-
- <td>-</td>
-
- <td>ran2</td>
-
- <td>-</td>
- </tr>
-
- <tr>
- <td>X(i) = (X(i-55) - X(i-33)) mod 10<sup>9</sup></td>
-
- <td>-</td>
-
- <td>-</td>
-
- <td>-</td>
-
- <td>ran3</td>
-
- <td>~SCGgen</td>
-
- <td>ran3</td>
-
- <td>-</td>
- </tr>
-
- <tr>
- <td>X(i) = (X(i-100) - X(i-37)) mod 2<sup>30</sup></td>
-
- <td>-</td>
-
- <td>-</td>
-
- <td>-</td>
-
- <td>-</td>
-
- <td>-</td>
-
- <td>-</td>
-
- <td>ran_array</td>
- </tr>
-
- <tr>
- <td>X(i) = (X(i-55) + X(i-24)) mod 2<sup>32</sup></td>
-
- <td>lagged_fibonacci< ..., 32, 55, 24, ...> (lagged_fibonacci not
- in this proposal)</td>
-
- <td>-</td>
-
- <td>-</td>
-
- <td>-</td>
-
- <td>ACGgen</td>
-
- <td>-</td>
-
- <td>-</td>
- </tr>
-
- <tr>
- <td>DEShash(i,j)</td>
-
- <td>-</td>
-
- <td>-</td>
-
- <td>-</td>
-
- <td>-</td>
-
- <td>-</td>
-
- <td>ran4</td>
-
- <td>-</td>
- </tr>
-
- <tr>
- <td>MT</td>
-
- <td>mt19937</td>
-
- <td>MTwistEngine</td>
-
- <td>MT19937</td>
-
- <td>mt19937</td>
-
- <td>MT19937gen</td>
-
- <td>-</td>
-
- <td>-</td>
- </tr>
-
- <tr>
- <td>X(i) = (X(i-37) - X(i-24) - carry) mod 2<sup>32</sup></td>
-
- <td>subtract_with_carry< ..., (1<<32), 37, 24, ...></td>
-
- <td>-</td>
-
- <td>-</td>
-
- <td>-</td>
-
- <td>SWB1gen</td>
-
- <td>-</td>
-
- <td>-</td>
- </tr>
-
- <tr>
- <td>X(i) = (X(i-43) - X(i-22) - carry) mod 2<sup>32</sup>-5</td>
-
- <td>subtract_with_carry< ..., (1<<32)-5, 43, 22, ...></td>
-
- <td>-</td>
-
- <td>-</td>
-
- <td>-</td>
-
- <td>PSWBgen</td>
-
- <td>-</td>
-
- <td>-</td>
- </tr>
-
- <tr>
- <td>RCARRY with block discard by Lüscher</td>
-
- <td>discard_block< subtract_with_carry<...>, ...></td>
-
- <td>RanluxEngine, Ranlux64Engine</td>
-
- <td>Ranlux</td>
-
- <td>ranlx*</td>
-
- <td>-</td>
-
- <td>-</td>
-
- <td>-</td>
- </tr>
-
- <tr>
- <td>Hurd</td>
-
- <td>-</td>
-
- <td>Hurd160, Hurd288</td>
-
- <td>-</td>
-
- <td>-</td>
-
- <td>-</td>
-
- <td>-</td>
-
- <td>-</td>
- </tr>
-
- <tr>
- <td>physical model by Ranshi</td>
-
- <td>-</td>
-
- <td>Ranshi</td>
-
- <td>-</td>
-
- <td>-</td>
-
- <td>-</td>
-
- <td>-</td>
-
- <td>-</td>
- </tr>
-
- <tr>
- <td>return predefined data</td>
-
- <td>-</td>
-
- <td>NonRandom</td>
-
- <td>-</td>
-
- <td>-</td>
-
- <td>-</td>
-
- <td>-</td>
-
- <td>-</td>
- </tr>
-
- <tr>
- <td>RANMAR: z(i) = (z(i-97) - z(i-33)) mod 2<sup>24</sup>; y(i+1) =
- (y(i)-c) mod 2<sup>24</sup>-3; X(i) = (z(i) - y(i)) mod
- 2<sup>24</sup></td>
-
- <td>additive_combine< lagged_fibonacci< (1<<24), 97, 33,
- ... >, linear_congruential< (1<<24)-3, 1, c, ...>
- (additive_combine and lagged_fibonacci not in this proposal)</td>
-
- <td>JamesRandom</td>
-
- <td>-</td>
-
- <td>ranmar</td>
-
- <td>-</td>
-
- <td>-</td>
-
- <td>-</td>
- </tr>
-
- <tr>
- <td>Taus88</td>
-
- <td>taus88 = xor_combine ...</td>
-
- <td>-</td>
-
- <td>Taus88</td>
-
- <td>taus, taus2</td>
-
- <td>-</td>
-
- <td>-</td>
-
- <td>-</td>
- </tr>
-
- <tr>
- <td>Taus60</td>
-
- <td>xor_combine< linear_feedback_shift< 31, 13, 12 >, 0,
- linear_feedback_shift< 29, 2, 4 >, 2, 0>
- (linear_feedback_shift not in this proposal)</td>
-
- <td>-</td>
-
- <td>-</td>
-
- <td>-</td>
-
- <td>C2TAUSgen</td>
-
- <td>-</td>
-
- <td>-</td>
- </tr>
-
- <tr>
- <td>GFSR, 4-tap</td>
-
- <td>-</td>
-
- <td>-</td>
-
- <td>-</td>
-
- <td>gfsr4</td>
-
- <td>-</td>
-
- <td>-</td>
-
- <td>-</td>
- </tr>
-
- <tr>
- <td>MRG32k3a</td>
-
- <td>-</td>
-
- <td>-</td>
-
- <td>MRG32k3a</td>
-
- <td>-</td>
-
- <td>-</td>
-
- <td>-</td>
-
- <td>-</td>
- </tr>
- </table>
-
- <h3>I. Which Distributions to Include</h3>The following distributions were
- chosen due to their relatively widespread use:
-
- <ul>
- <li>Integer uniform</li>
-
- <li>Floating-point uniform</li>
-
- <li>Exponential</li>
-
- <li>Normal</li>
-
- <li>Gamma</li>
-
- <li>Poisson</li>
-
- <li>Binomial</li>
-
- <li>Geometric</li>
-
- <li>Bernoulli</li>
- </ul>The GNU Scientific Library has a multitude of additional distributions
- that are not mentioned in the table below.
-
- <table border="1" summary="">
- <tr>
- <th>Distribution</th>
-
- <th>this proposal</th>
-
- <th>CLHEP</th>
-
- <th>crng</th>
-
- <th>GNU Scientific Library</th>
-
- <th>Swarm</th>
-
- <th>Numerical Recipes</th>
-
- <th>Knuth</th>
- </tr>
-
- <tr>
- <td>uniform (int)</td>
-
- <td>uniform_int</td>
-
- <td>-</td>
-
- <td>-</td>
-
- <td>-</td>
-
- <td>UniformIntegerDist</td>
-
- <td>-</td>
-
- <td>-</td>
- </tr>
-
- <tr>
- <td>uniform (float)</td>
-
- <td>uniform_real</td>
-
- <td>RandFlat</td>
-
- <td>UniformDeviate</td>
-
- <td>flat</td>
-
- <td>UniformDoubleDist</td>
-
- <td>-</td>
-
- <td>uniform</td>
- </tr>
-
- <tr>
- <td>exponential</td>
-
- <td>exponential_distribution</td>
-
- <td>RandExponential</td>
-
- <td>ExponentialDeviate</td>
-
- <td>exponential</td>
-
- <td>ExponentialDist</td>
-
- <td>exponential</td>
-
- <td>exponential</td>
- </tr>
-
- <tr>
- <td>normal</td>
-
- <td>normal_distribution</td>
-
- <td>RandGauss*</td>
-
- <td>NormalDeviate</td>
-
- <td>gaussian</td>
-
- <td>NormalDist</td>
-
- <td>normal (gaussian)</td>
-
- <td>normal</td>
- </tr>
-
- <tr>
- <td>lognormal</td>
-
- <td>-</td>
-
- <td>-</td>
-
- <td>-</td>
-
- <td>lognormal</td>
-
- <td>LogNormalDist</td>
-
- <td>-</td>
-
- <td>-</td>
- </tr>
-
- <tr>
- <td>gamma</td>
-
- <td>gamma_distribution</td>
-
- <td>RandGamma</td>
-
- <td>GammaDeviate</td>
-
- <td>gamma</td>
-
- <td>GammaDist</td>
-
- <td>gamma</td>
-
- <td>gamma</td>
- </tr>
-
- <tr>
- <td>beta</td>
-
- <td>-</td>
-
- <td>-</td>
-
- <td>BetaDeviate</td>
-
- <td>beta</td>
-
- <td>-</td>
-
- <td>-</td>
-
- <td>beta</td>
- </tr>
-
- <tr>
- <td>poisson</td>
-
- <td>poisson_distribution</td>
-
- <td>Poisson</td>
-
- <td>PoissonDeviate</td>
-
- <td>poisson</td>
-
- <td>PoissonDist</td>
-
- <td>poisson</td>
-
- <td>poisson</td>
- </tr>
-
- <tr>
- <td>binomial</td>
-
- <td>binomial_distribution</td>
-
- <td>RandBinomial</td>
-
- <td>BinomialDeviate</td>
-
- <td>binomial</td>
-
- <td>-</td>
-
- <td>binomial</td>
-
- <td>binomial</td>
- </tr>
-
- <tr>
- <td>geometric</td>
-
- <td>geometric_distribution</td>
-
- <td>-</td>
-
- <td>GeometricDeviate</td>
-
- <td>geometric</td>
-
- <td>-</td>
-
- <td>-</td>
-
- <td>geometric</td>
- </tr>
-
- <tr>
- <td>bernoulli</td>
-
- <td>bernoulli_distribution</td>
-
- <td>-</td>
-
- <td>BernoulliDeviate</td>
-
- <td>bernoulli</td>
-
- <td>BernoulliDist</td>
-
- <td>-</td>
-
- <td>-</td>
- </tr>
-
- <tr>
- <td>random bit</td>
-
- <td>-</td>
-
- <td>RandBit</td>
-
- <td>-</td>
-
- <td>-</td>
-
- <td>RandomBitDist</td>
-
- <td>-</td>
-
- <td>-</td>
- </tr>
-
- <tr>
- <td>breit-wigner</td>
-
- <td>-</td>
-
- <td>RandBreitWigner</td>
-
- <td>-</td>
-
- <td>-</td>
-
- <td>-</td>
-
- <td>-</td>
-
- <td>-</td>
- </tr>
-
- <tr>
- <td>chi-square</td>
-
- <td>-</td>
-
- <td>RandChiSquare</td>
-
- <td>-</td>
-
- <td>chisq</td>
-
- <td>-</td>
-
- <td>-</td>
-
- <td>chi-square</td>
- </tr>
-
- <tr>
- <td>landau</td>
-
- <td>-</td>
-
- <td>Landau</td>
-
- <td>-</td>
-
- <td>landau</td>
-
- <td>-</td>
-
- <td>-</td>
-
- <td>-</td>
- </tr>
-
- <tr>
- <td>F</td>
-
- <td>-</td>
-
- <td>-</td>
-
- <td>-</td>
-
- <td>F</td>
-
- <td>-</td>
-
- <td>-</td>
-
- <td>F (variance-ratio)</td>
- </tr>
-
- <tr>
- <td>t</td>
-
- <td>-</td>
-
- <td>-</td>
-
- <td>-</td>
-
- <td>t</td>
-
- <td>-</td>
-
- <td>-</td>
-
- <td>t</td>
- </tr>
- </table>
-
- <h3>J. Taxonomy of Concepts</h3>All of the engines support the number
- generator requirements, i.e. they are zero-argument function objects which
- return numbers. All of the distributions are one-argument function objects,
- taking a reference to an engine and returning numbers. All of the engines
- and some of the distributions return uniformly distributed random numbers.
- This is reflected in the concept of the uniform random number generator,
- which refines number generator. Engines for pseudo-random numbers model the
- requirements for pseudo-random number engine, which refines uniform random
- number generator.
- <pre>
-NumberGenerator ---- UniformRandomNumberGenerator ---- PseudoRandomNumberGenerator
- \--- RandomDistribution
-</pre>
-
- <h3>K. Validation</h3>How can a user have confidence that the
- implementation of a random-number engine is exactly as specified, correctly
- taking into account any platform pecularities (e.g., odd-sized ints)? After
- all, minor typos in the implementation might not be apparent; the numbers
- produced may look "random". This proposal therefore specifies for each
- engine the 10000th number in the random number sequence that a
- default-constructed engine object produces.
-
- <p>This is considered an important feature for library implementors and
- serious users to check whether the provided library on the given platform
- returns the correct numbers. It could be argued that a library implementor
- should provide a correct implementation of some standard feature in any
- case.</p>
-
- <p>No other library I have encountered provides explicit validation values
- in either their specification or their implementation, although some of
- them claim to be widely portable.</p>
-
- <p>Another design option for validation that was part of early drafts of
- this proposal is moving the reference number (10000th value in the
- sequence) from specification space to implementation space, thus providing
- a <code>validation(x)</code> static member function for each engine that
- compares the hard-coded 10000th value of the sequence with some
- user-provided value <code>x</code> presumeably obtained by actually
- invoking the random-number engine object 10000 times. Due to the
- template-based design, this amounted to a "val" template value parameter
- for each engine, and the <code>validation(x)</code> function reduced to the
- trivial comparison "val == x". Handling validation for floating-point
- engines required more machinery, because template value parameters cannot
- be of floating-point type. Also, from a conceptual perspective, it seemed
- odd to demand a validation decision from the very entitiy which one wanted
- to validate.</p>
-
- <h3>L. Non-Volatile Storage of Engine and Distribution
- State</h3>Pseudo-random number engines and distributions may store their
- state on a <code>std::ostream</code> in textual form and recover it from an
- appropriate <code>std::istream</code>. Each engine specifies how its
- internal state is represented. The specific algorithm of a distribution is
- left implementation-defined, thus no specifics about the representation of
- its internal state are given. A store operation must not affect the number
- sequence produced. It is expected that such external storage happens rarely
- as opposed to producing random numbers, thus no particular attention to
- performance is paid.
-
- <p>Engines and distributions use the usual idioms of
- <code>operator<<</code> and <code>operator>></code>. If the
- user needs additional processing before or after storage on non-volatile
- media, there is always the option to use a temporary
- <code>std::stringstream</code>.</p>
-
- <p>Distributions sometimes store values from their associated source of
- random numbers across calls to their <code>operator()</code>. For example,
- a common method for generating normally distributed random numbers is to
- retrieve two uniformly distributed random numbers and compute two normally
- distributed random numbers out of them. In order to reset the
- distribution's random number cache to a defined state, each distribution
- has a <code>reset</code> member function. It should be called on a
- distribution whenever its associated engine is exchanged or restored.</p>
-
- <h3>M. Values vs. References</h3>Compounded engines such as
- <code>shuffle_output</code> and <code>discard_block</code> contain a base
- engine by value, because compounding is not intended to be used by
- reference to an existing (re-used) engine object.
-
- <p>The wrapper <code>variate_generator</code> can store engines either by
- value or by reference, explicitly chosen by the template parameters. This
- allows to use references to a single engine in several
- <code>variate_generator</code>, but makes it explicit to the user that he
- is responsible for the management of the lifetime of the engine.</p>
-
- <h3>N. Providing the Probability Density Function in Distributions</h3>Some
- libraries provide the probability density function of a given distribution
- as part of that distribution's interface. While this may be useful
- occasionally, this proposal does not provide for such a feature. One reason
- is separation of concerns: The distribution class templates might benefit
- from precomputing large tables of values depending on the distribution
- parameters, while the computation of the probability density function does
- not. Also, the function representation is often straightforward, so the
- user can easily code it himself.
-
- <h3>O. Implementation-defined behaviour</h3>This proposal specifies
- implementation-defined behaviour in a number of places. I believe this is
- unavoidable; this section provides detailed reasoning, including why the
- implementation is required to document the choice.
-
- <p>The precise state-holding base data types for the various engines are
- left implementation-defined, because engines are usually optimized for
- binary integers with 32 bits of word size. The specification in this
- proposal cannot foresee whether a 32 bit quantity on the machine is
- available in C++ as short, int, long, or not at all. It is up to the
- implementation to decide which data type fits best. The implementation is
- required to document the choice of data type, so that users can
- (non-portably) rely on the precise type, for example for further
- computation. Should the ISO C99 extensions become part of ISO C++, the
- implementation-defined types could be replaced by e.g.
- <code>int_least32_t</code>.</p>
-
- <p>The method how to produce non-deterministic random numbers is considered
- implementation-defined, because it inherently depends on the implementation
- and possibly even on the runtime environment: Imagine a platform that has
- operating system support for randomness collection, e.g. from user
- keystrokes and Ethernet inter-packet arrival timing (Linux
- <code>/dev/random</code> does this). If, in some installation, access to
- the operating system functions providing these services has been
- restricted, the C++ non-deterministic random number engine has been
- deprived of its randomness. An implementation is required to document how
- it obtains the non-deterministic random numbers, because only then can
- users' confidence in them grow. Confidence is of particular concern in the
- area of cryptography.</p>
-
- <p>The algorithms how to produce the various distributions are specified as
- implementation-defined, because there is a vast variety of algorithms known
- for each distribution. Each has a different trade-off in terms of speed,
- adaptation to recent computer architectures, and memory use. The
- implementation is required to document its choice so that the user can
- judge whether it is acceptable quality-wise.</p>
-
- <h3>P. Lower and upper bounds on UniformRandomNumberGenerator</h3>The
- member functions <code>min()</code> and <code>max()</code> return the lower
- and upper bounds of a UniformRandomNumberGenerator. This could be a
- random-number engine or one of the <code>uniform_int</code> and
- <code>uniform_real</code> distributions.
-
- <p>Those bounds are not specified to be tight, because for some engines,
- the bounds depend on the seeds. The seed can be changed during the lifetime
- of the engine object, while the values returned by <code>min()</code> and
- <code>max()</code> are invariant. Therefore, <code>min()</code> and
- <code>max()</code> must return conservative bounds that are independent of
- the seed.</p>
-
- <h3>Q. With or without manager class</h3>This proposal presents a design
- with a manager class template, <code>variate_generator</code>, after
- extensive discussion with some members of the computing division of Fermi
- National Accelerator Laboratory. User-written and library-provided engines
- and distributions plug in to the manager class. The approach is remotely
- similar to the locale design in the standard library, where (user-written)
- facets plug in to the (library-provided) locale class.
-
- <p>Earlier versions of this propsoal made (potentially user-written)
- distributions directly visible to (some other) user that wants to get
- random numbers distributed accordingly ("client"), there was no additional
- management layer between the distribution and the client.</p>
-
- <p>The following additional features could be provided by the management
- layer:</p>
-
- <ul>
- <li>The management layer contains an adaptor (to convert the engine's
- output into the distribution's input) in addition to the engine and the
- distribution.</li>
-
- <li>Adaptors and distributions do not store state, but instead, in each
- invocation, consume an arbitrary number of input values and produce a
- fixed number of output values. The management layer is responsible for
- connecting the engine - adaptor - distribution chain, invoking each part
- when more numbers are needed from the next part of the chain.</li>
-
- <li>On request, the management layer is responsible for saving and
- restoring the buffers that exist between engine, adaptor, and
- distribution.</li>
-
- <li>On request, the management layer shares engines with another instance
- of the management layer.</li>
- </ul>It is envisioned that user-written distributions will often be based
- on some arbitrary algorithmic distribution, instead of trying to implement
- a given mathematical probability density function. Here is an example:
-
- <ul>
- <li>Retrieve a uniform integer with value either 1 or 2.</li>
-
- <li>If 1, return a number with normal distribution.</li>
-
- <li>If 2, return a number with gamma distribution.</li>
- </ul>Both in this case and when implementing complex distributions based on
- a probability density function (e.g. the gamma distribution), it is
- important to be able to arbitrarily nest distributions. Either design
- allows for this with utmost ease: Compounding distributions are contained
- in the compound by value, and each one produces a single value on
- invocation. With the alternative design of giving distributions the freedom
- to produce more than one output number in each invocation, compound
- distributions such as the one shown above need to handle the situation that
- each of the compounding members could provide several output values, the
- number of which is unknown at the time the distribution is written.
- (Remember that it is unfeasible to prescribe a precise algorithm for each
- library-provided distribution in the standard, see subsection O.) That
- approach shifts implementation effort from the place where it came up, i.e.
- the distribution that chose to use an algorithm that produces several
- values in one invocation, to the places where that distribution is used.
- This, considered by itself, does not seem to be a good approach. Also, only
- very few distributions lead to a natural implementation that produces
- several values in one invocation; so far, the normal distribution is the
- only one known to me. However, it is expected that there will be plenty of
- distributions that use a normal distribution as its base, so far those
- known to me are lognormal and uniform_on_sphere (both not part of this
- proposal). As a conclusion, independent of whether the design provides for
- a management layer or not, distributions should always return a single
- value on each invocation, and management of buffers for additional values
- that might be produced should be internal to the distribution. Should it
- become necessary for the user to employ buffer management more often, a
- user-written base class for the distributions could be of help.
-
- <p>The ability to share engines is important. This proposal makes lifetime
- management issues explicit by requiring pointer or reference types in the
- template instantiation of <code>variate_generator</code> if reference
- semantics are desired. Without a management class, providing this features
- is much more cumbersome and imposes additional burden on the programmers
- that produce distributions. Alternatively, reference semantics could always
- be used, but this is an error-prone approach due to the lack of a standard
- reference-counted smart pointer. I believe it is impossible to add a
- reference-counted sharing mechanism in a manager-class-free design without
- giving its precise type. And that would certainly conflict in semantic
- scope with a smart pointer that will get into the standard eventually.</p>
-
- <p>The management layer allows for a few common features to be factored
- out, in particular access to the engine and some member typedefs.</p>
-
- <p>Comparison of other differing features between manager and non-manager
- designs:</p>
-
- <ul>
- <li>When passing a <code>variate_generator</code> as a an argument to a
- function, the design in this proposal allows selecting only those
- function signatures during overload resolution that are intended to be
- called with a <code>variate_generator</code>. In contrast, misbehaviour
- is possible without a manager class, similar to iterators in function
- signatures: <code>template<class BiIter> void f(BiIter it)</code>
- matches <code>f(5)</code>, without regard to the bidirectional iterator
- requirements. An error then happens when instantiating f. The situation
- worsens when several competing function templates are available and the
- wrong one is chosen accidentally.</li>
-
- <li>With the engine passed into the distribution's constructor, the full
- type hierarchy of engine (and possibly adaptor) are available to the
- distribution, allowing to cache information derived from the engine (e.g.
- its value range) . Also, (partial) specialization of distributions could
- be written that optimize the interaction with a specific engine and/or
- adaptor. In this proposal's design, this information is available in the
- <code>variate_generator</code> template only. However, optimizations by
- specialization for the engine/adaptor combination are perceived to
- possibly have high benefit, while those for the (engine+adaptor) /
- distribution combination are presumed to be much less beneficial.</li>
-
- <li>Having distribution classes directly exposed to the client easily
- allows that the user writes a distribution with an additional arbitrary
- member function declaration, intended to produce random numbers while
- taking additional parameters into account. In this proposal's design,
- this is possible by using the generic <code>operator()(T x)</code>
- forwarding function.</li>
- </ul>
-
- <h3>R. Add-on packages</h3>This proposal specifies a framework for random
- number generation. Users might have additional requirements not met by this
- framework. The following extensions have been identified, and they are
- expressly not addressed in this proposal. It is perceived that these items
- can be seamlessly implemented in an add-on package which sits on top of an
- implementation according to this proposal.
-
- <ul>
- <li>unique seeding: Make it easy for the user to provide a unique seed
- for each instance of a pseudo-random number engine. Design idea:
- <pre>
- class unique_seed;
-
- template<class Engine>
- Engine seed(unique_seed&);
-</pre>The "seed" function retrieves some unique seed from the unique_seed
-class and then uses the <code>seed(first, last)</code> interface of an engine
-to implant that unique seed. Specific seeding requirements for some engine
-can be met by (partial) template specialization.
- </li>
-
- <li>runtime-replaceable distributions and associated save/restore
- functionality: Provide a class hierarchy that invokes distributions by
- means of a virtual function, thereby allowing for runtime replacement of
- the actual distribution. Provide a factory function to reconstruct the
- distribution instance after saving it to some non-volatile media.</li>
- </ul>
-
- <h3>S. Adaptors</h3>Sometimes, users may want to have better control how
- the bits from the engine are used to fill the mantissa of the
- floating-point value that serves as input to some distribution. This is
- possible by writing an engine wrapper and passing that in to the
- <code>variate_generator</code> as the engine. The
- <code>variate_generator</code> will only apply automatic adaptations if the
- output type of the engine is integers and the input type for the
- distribution is floating-point or vice versa.
-
- <h3>Z. Open issues</h3>
-
- <ul>
- <li>Some engines require non-negative template arguments, usually bit
- counts. Should these be given as "int" or "unsigned int"? Using "unsigned
- int" sometimes adds significant clutter to the presentation. Or "size_t",
- but this is probably too large a type?</li>
- </ul>
-
- <h2>IV. Proposed Text</h2>(Insert the following as a new section in clause
- 26 "Numerics". Adjust the overview at the beginning of clause 26
- accordingly.)
-
- <p>This subclause defines a facility for generating random numbers.</p>
-
- <h3>Random number requirements</h3>A number generator is a function object
- (std:20.3 [lib.function.objects]).
-
- <p>In the following table, <code>X</code> denotes a number generator class
- returning objects of type <code>T</code>, and <code>u</code> is a (possibly
- <code>const</code>) value of <code>X</code>.</p>
-
- <table border="1" summary="">
- <tr>
- <th colspan="4" align="center">Number generator requirements (in
- addition to function object)</th>
- </tr>
-
- <tr>
- <td>expression</td>
-
- <td>return type</td>
-
- <td>pre/post-condition</td>
-
- <td>complexity</td>
- </tr>
-
- <tr>
- <td><code>X::result_type</code></td>
-
- <td>T</td>
-
- <td><code>std::numeric_limits<T>::is_specialized</code> is
- <code>true</code></td>
-
- <td>compile-time</td>
- </tr>
- </table>
-
- <p>In the following table, <code>X</code> denotes a uniform random number
- generator class returning objects of type <code>T</code>, <code>u</code> is
- a value of <code>X</code> and <code>v</code> is a (possibly
- <code>const</code>) value of <code>X</code>.</p>
-
- <table border="1" summary="">
- <tr>
- <th colspan="4" align="center">Uniform random number generator
- requirements (in addition to number generator)</th>
- </tr>
-
- <tr>
- <td>expression</td>
-
- <td>return type</td>
-
- <td>pre/post-condition</td>
-
- <td>complexity</td>
- </tr>
-
- <tr>
- <td><code>u()</code></td>
-
- <td>T</td>
-
- <td>-</td>
-
- <td>amortized constant</td>
- </tr>
-
- <tr>
- <td><code>v.min()</code></td>
-
- <td><code>T</code></td>
-
- <td>Returns some l where l is less than or equal to all values
- potentially returned by <code>operator()</code>. The return value of
- this function shall not change during the lifetime of
- <code>v</code>.</td>
-
- <td>constant</td>
- </tr>
-
- <tr>
- <td><code>v.max()</code></td>
-
- <td><code>T</code></td>
-
- <td>If <code>std::numeric_limits<T>::is_integer</code>, returns l
- where l is less than or equal to all values potentially returned by
- <code>operator()</code>, otherwise, returns l where l is strictly less
- than all values potentially returned by <code>operator()</code>. In any
- case, the return value of this function shall not change during the
- lifetime of <code>v</code>.</td>
-
- <td>constant</td>
- </tr>
- </table>
-
- <p>In the following table, <code>X</code> denotes a pseudo-random number
- engine class returning objects of type <code>T</code>, <code>t</code> is a
- value of <code>T</code>, <code>u</code> is a value of <code>X</code>,
- <code>v</code> is an lvalue of <code>X</code>, <code>it1</code> is an
- lvalue and <code>it2</code> is a (possibly <code>const</code>) value of an
- input iterator type <code>It</code> having an unsigned integral value type,
- <code>x</code>, <code>y</code> are (possibly <code>const</code>) values of
- <code>X</code>, <code>os</code> is convertible to an lvalue of type
- <code>std::ostream</code>, and <code>is</code> is convertible to an lvalue
- of type <code>std::istream</code>.</p>
-
- <p>A pseudo-random number engine x has a state x(i) at any given time. The
- specification of each pseudo-random number engines defines the size of its
- state in multiples of the size of its <code>result_type</code>, given as an
- integral constant expression.</p>
-
- <table border="1" summary="">
- <tr>
- <th colspan="4" align="center">Pseudo-random number engine requirements
- (in addition to uniform random number generator,
- <code>CopyConstructible</code>, and <code>Assignable</code>)</th>
- </tr>
-
- <tr>
- <td>expression</td>
-
- <td>return type</td>
-
- <td>pre/post-condition</td>
-
- <td>complexity</td>
- </tr>
-
- <tr>
- <td><code>X()</code></td>
-
- <td>-</td>
-
- <td>creates an engine with the same initial state as all other
- default-constructed engines of type <code>X</code> in the program.</td>
-
- <td>O(size of state)</td>
- </tr>
-
- <tr>
- <td><code>X(it1, it2)</code></td>
-
- <td>-</td>
-
- <td>creates an engine with the initial state given by the range
- <code>[it1,it2)</code>. <code>it1</code> is advanced by the size of
- state. If the size of the range [it1,it2) is insufficient, leaves
- <code>it1 == it2</code> and throws <code>invalid_argument</code>.</td>
-
- <td>O(size of state)</td>
- </tr>
-
- <tr>
- <td><code>u.seed()</code></td>
-
- <td>void</td>
-
- <td>post: <code>u == X()</code></td>
-
- <td>O(size of state)</td>
- </tr>
-
- <tr>
- <td><code>u.seed(it1, it2)</code></td>
-
- <td>void</td>
-
- <td>post: If there are sufficiently many values in [it1, it2) to
- initialize the state of <code>u</code>, then <code>u ==
- X(it1,it2)</code>. Otherwise, <code>it1 == it2</code>, throws
- <code>invalid_argument</code>, and further use of <code>u</code>
- (except destruction) is undefined until a <code>seed</code> member
- function has been executed without throwing an exception.</td>
-
- <td>O(size of state)</td>
- </tr>
-
- <tr>
- <td><code>u()</code></td>
-
- <td><code>T</code></td>
-
- <td>given the state u(i) of the engine, computes u(i+1), sets the state
- to u(i+1), and returns some output dependent on u(i+1)</td>
-
- <td>amortized constant</td>
- </tr>
-
- <tr>
- <td><code>x == y</code></td>
-
- <td><code>bool</code></td>
-
- <td><code>==</code> is an equivalence relation. The current state x(i)
- of x is equal to the current state y(j) of y.</td>
-
- <td>O(size of state)</td>
- </tr>
-
- <tr>
- <td><code>x != y</code></td>
-
- <td><code>bool</code></td>
-
- <td><code>!(x == y)</code></td>
-
- <td>O(size of state)</td>
- </tr>
-
- <tr>
- <td><code>os << x</code></td>
-
- <td><code>std::ostream&</code></td>
-
- <td>writes the textual representation of the state x(i) of
- <code>x</code> to <code>os</code>, with
- <code>os.<em>fmtflags</em></code> set to
- <code>ios_base::dec|ios_base::fixed|ios_base::left</code> and the fill
- character set to the space character. In the output, adjacent numbers
- are separated by one or more space characters.<br>
- post: The <code>os.<em>fmtflags</em></code> and fill character are
- unchanged.</td>
-
- <td>O(size of state)</td>
- </tr>
-
- <tr>
- <td><code>is >> v</code></td>
-
- <td><code>std::istream&</code></td>
-
- <td>sets the state v(i) of <code>v</code> as determined by reading its
- textual representation from <code>is</code>.<br>
- post: The <code>is.<em>fmtflags</em></code> are unchanged.</td>
-
- <td>O(size of state)</td>
- </tr>
- </table>
-
- <p>In the following table, <code>X</code> denotes a random distribution
- class returning objects of type <code>T</code>, <code>u</code> is a value
- of <code>X</code>, <code>x</code> is a (possibly const) value of
- <code>X</code>, and <code>e</code> is an lvalue of an arbitrary type that
- meets the requirements of a uniform random number generator, returning
- values of type <code>U</code>.</p>
-
- <table border="1" summary="">
- <tr>
- <th colspan="4" align="center">Random distribution requirements (in
- addition to number generator, <code>CopyConstructible</code>, and
- <code>Assignable</code>)</th>
- </tr>
-
- <tr>
- <td>expression</td>
-
- <td>return type</td>
-
- <td>pre/post-condition</td>
-
- <td>complexity</td>
- </tr>
-
- <tr>
- <td><code>X::input_type</code></td>
-
- <td>U</td>
-
- <td>-</td>
-
- <td>compile-time</td>
- </tr>
-
- <tr>
- <td><code>u.reset()</code></td>
-
- <td><code>void</code></td>
-
- <td>subsequent uses of <code>u</code> do not depend on values produced
- by <code>e</code> prior to invoking <code>reset</code>.</td>
-
- <td>constant</td>
- </tr>
-
- <tr>
- <td><code>u(e)</code></td>
-
- <td><code>T</code></td>
-
- <td>the sequence of numbers returned by successive invocations with the
- same object <code>e</code> is randomly distributed with some
- probability density function p(x)</td>
-
- <td>amortized constant number of invocations of <code>e</code></td>
- </tr>
-
- <tr>
- <td><code>os << x</code></td>
-
- <td><code>std::ostream&</code></td>
-
- <td>writes a textual representation for the parameters and additional
- internal data of the distribution <code>x</code> to
- <code>os</code>.<br>
- post: The <code>os.<em>fmtflags</em></code> and fill character are
- unchanged.</td>
-
- <td>O(size of state)</td>
- </tr>
-
- <tr>
- <td><code>is >> u</code></td>
-
- <td><code>std::istream&</code></td>
-
- <td>restores the parameters and additional internal data of the
- distribution <code>u</code>.<br>
- pre: <code>is</code> provides a textual representation that was
- previously written by <code>operator<<</code><br>
- post: The <code>is.<em>fmtflags</em></code> are unchanged.</td>
-
- <td>O(size of state)</td>
- </tr>
- </table>
-
- <p>Additional requirements: The sequence of numbers produced by repeated
- invocations of <code>x(e)</code> does not change whether or not <code>os
- << x</code> is invoked between any of the invocations
- <code>x(e)</code>. If a textual representation is written using <code>os
- << x</code> and that representation is restored into the same or a
- different object <code>y</code> of the same type using <code>is >>
- y</code>, repeated invocations of <code>y(e)</code> produce the same
- sequence of random numbers as would repeated invocations of
- <code>x(e)</code>.</p>
-
- <p>In the following subclauses, a template parameter named
- <code>UniformRandomNumberGenerator</code> shall denote a class that
- satisfies all the requirements of a uniform random number generator.
- Moreover, a template parameter named <code>Distribution</code> shall denote
- a type that satisfies all the requirements of a random distribution.
- Furthermore, a template parameter named <code>RealType</code> shall denote
- a type that holds an approximation to a real number. This type shall meet
- the requirements for a numeric type (26.1 [lib.numeric.requirements]), the
- binary operators +, -, *, / shall be applicable to it, a conversion from
- <code>double</code> shall exist, and function signatures corresponding to
- those for type <code>double</code> in subclause 26.5 [lib.c.math] shall be
- available by argument-dependent lookup (3.4.2 [basic.lookup.koenig]).
- <em>[Note: The built-in floating-point types <code>float</code> and
- <code>double</code> meet these requirements.]</em></p>
-
- <h3>Header <code><random></code> synopsis</h3>
- <pre>
-namespace std {
- template<class UniformRandomNumberGenerator, class Distribution>
- class variate_generator;
-
- template<class IntType, IntType a, IntType c, IntType m>
- class linear_congruential;
-
- template<class UIntType, int w, int n, int m, int r, UIntType a, int u,
- int s, UIntType b, int t, UIntType c, int l>
- class mersenne_twister;
-
- template<class IntType, IntType m, int s, int r>
- class subtract_with_carry;
-
- template<class RealType, int w, int s, int r>
- class subtract_with_carry_01;
-
- template<class UniformRandomNumberGenerator, int p, int r>
- class discard_block;
-
- template<class UniformRandomNumberGenerator1, int s1,
- class UniformRandomNumberGenerator2, int s2>
- class xor_combine;
-
- class random_device;
-
- template<class IntType = int>
- class uniform_int;
-
- template<class RealType = double>
- class bernoulli_distribution;
-
- template<class IntType = int, class RealType = double>
- class geometric_distribution;
-
- template<class IntType = int, class RealType = double>
- class poisson_distribution;
-
- template<class IntType = int, class RealType = double>
- class binomial_distribution;
-
- template<class RealType = double>
- class uniform_real;
-
- template<class RealType = double>
- class exponential_distribution;
-
- template<class RealType = double>
- class normal_distribution;
-
- template<class RealType = double>
- class gamma_distribution;
-
-} // namespace std
-</pre>
-
- <h3>Class template <code>variate_generator</code></h3>A
- <code>variate_generator</code> produces random numbers, drawing randomness
- from an underlying uniform random number generator and shaping the
- distribution of the numbers corresponding to a distribution function.
- <pre>
-template<class Engine, class Distribution>
-class variate_generator
-{
-public:
- typedef Engine engine_type;
- typedef /* <em>implementation defined</em> */ engine_value_type;
- typedef Distribution distribution_type;
- typedef typename Distribution::result_type result_type;
-
- variate_generator(engine_type eng, distribution_type d);
-
- result_type operator()();
- template<class T> result_type operator()(T value);
-
- engine_value_type& engine();
- const engine_value_type& engine() const;
-
- distribution_type& distribution();
- const distribution_type& distribution() const;
-
- result_type min() const;
- result_type max() const;
-};
-</pre>The template argument for the parameter <code>Engine</code> shall be of
-the form <code><em>U</em></code>, <code><em>U</em>&</code>, or <code><em>
- U</em>*</code>, where <code><em>U</em></code> denotes a class that
- satisfies all the requirements of a uniform random number generator. The
- member <code>engine_value_type</code> shall name <code><em>U</em></code>.
-
- <p>Specializations of <code>variate_generator</code> satisfy the
- requirements of CopyConstructible. They also satisfy the requirements of
- Assignable unless the template parameter <code>Engine</code> is of the form
- <code><em>U</em>&</code>.</p>
-
- <p>The complexity of all functions specified in this section is constant.
- No function described in this section except the constructor throws an
- exception.</p>
- <pre>
- variate_generator(engine_type eng, distribution_type d)
-</pre><strong>Effects:</strong> Constructs a <code>variate_generator</code>
-object with the associated uniform random number generator <code>eng</code>
-and the associated random distribution <code>d</code>.<br>
- <strong>Throws:</strong> If and what the copy constructor of Engine or
- Distribution throws.
- <pre>
- result_type operator()()
-</pre><strong>Returns:</strong> <code>distribution()(e)</code><br>
- <strong>Notes:</strong> The sequence of numbers produced by the uniform
- random number generator <code>e</code>, s<sub>e</sub>, is obtained from the
- sequence of numbers produced by the associated uniform random number
- generator <code>eng</code>, s<sub>eng</sub>, as follows: Consider the
- values of <code>numeric_limits<<em>T</em>>::is_integer</code> for
- <code><em>T</em></code> both <code>Distribution::input_type</code> and
- <code>engine_value_type::result_type</code>. If the values for both types
- are <code>true</code>, then s<sub>e</sub> is identical to s<sub>eng</sub>.
- Otherwise, if the values for both types are <code>false</code>, then the
- numbers in s<sub>eng</sub> are divided by
- <code>engine().max()-engine().min()</code> to obtain the numbers in
- s<sub>e</sub>. Otherwise, if the value for
- <code>engine_value_type::result_type</code> is <code>true</code> and the
- value for <code>Distribution::input_type</code> is <code>false</code>, then
- the numbers in s<sub>eng</sub> are divided by
- <code>engine().max()-engine().min()+1</code> to obtain the numbers in
- s<sub>e</sub>. Otherwise, the mapping from s<sub>eng</sub> to s<sub>e</sub>
- is implementation-defined. In all cases, an implicit conversion from
- <code>engine_value_type::result_type</code> to
- <code>Distribution::input_type</code> is performed. If such a conversion
- does not exist, the program is ill-formed.
- <pre>
- template<class T> result_type operator()(T value)
-</pre><strong>Returns:</strong> <code>distribution()(e, value)</code>. For
-the semantics of <code>e</code>, see the description of
-<code>operator()()</code>.
- <pre>
- engine_value_type& engine()
-</pre><strong>Returns:</strong> A reference to the associated uniform random
-number generator.
- <pre>
- const engine_value_type& engine() const
-</pre><strong>Returns:</strong> A reference to the associated uniform random
-number generator.
- <pre>
- distribution_type& distribution()
-</pre><strong>Returns:</strong> A reference to the associated random
-distribution.
- <pre>
- const distribution_type& distribution() const
-</pre><strong>Returns:</strong> A reference to the associated random
-distribution.
- <pre>
- result_type min() const
-</pre><strong>Precondition:</strong> <code>distribution().min()</code> is
-well-formed<br>
- <strong>Returns:</strong> <code>distribution().min()</code>
- <pre>
- result_type max() const
-</pre><strong>Precondition:</strong> <code>distribution().max()</code> is
-well-formed<br>
- <strong>Returns:</strong> <code>distribution().max()</code>
-
- <h3>Random number engine class templates</h3>Except where specified
- otherwise, the complexity of all functions specified in the following
- sections is constant. No function described in this section except the
- constructor and seed functions taking an iterator range [it1,it2) throws an
- exception.
-
- <p>The class templates specified in this section satisfy all the
- requirements of a pseudo-random number engine (given in tables in section
- x.x), except where specified otherwise. Descriptions are provided here only
- for operations on the engines that are not described in one of these tables
- or for operations where there is additional semantic information.</p>
-
- <p>All members declared <code>static const</code> in any of the following
- class templates shall be defined in such a way that they are usable as
- integral constant expressions.</p>
-
- <h4>Class template <code>linear_congruential</code></h4>A
- <code>linear_congruential</code> engine produces random numbers using a
- linear function x(i+1) := (a * x(i) + c) mod m.
- <pre>
-namespace std {
- template<class IntType, IntType a, IntType c, IntType m>
- class linear_congruential
- {
- public:
- // <em>types</em>
- typedef IntType result_type;
-
- // <em>parameter values</em>
- static const IntType multiplier = a;
- static const IntType increment = c;
- static const IntType modulus = m;
-
- // <em> constructors and member function</em>
- explicit linear_congruential(IntType x0 = 1);
- template<class In> linear_congruential(In& first, In last);
- void seed(IntType x0 = 1);
- template<class In> void seed(In& first, In last);
- result_type min() const;
- result_type max() const;
- result_type operator()();
- };
-
- template<class IntType, IntType a, IntType c, IntType m>
- bool operator==(const linear_congruential<IntType, a, c, m>& x,
- const linear_congruential<IntType, a, c, m>& y);
- template<class IntType, IntType a, IntType c, IntType m>
- bool operator!=(const linear_congruential<IntType, a, c, m>& x,
- const linear_congruential<IntType, a, c, m>& y);
-
- template<class CharT, class traits,
- class IntType, IntType a, IntType c, IntType m>
- basic_ostream<CharT, traits>& operator<<(basic_ostream<CharT, traits>& os,
- const linear_congruential<IntType, a, c, m>& x);
- template<class CharT, class traits,
- class IntType, IntType a, IntType c, IntType m>
- basic_istream<CharT, traits>& operator>>(basic_istream<CharT, traits>& is,
- linear_congruential<IntType, a, c, m>& x);
-}
-</pre>The template parameter <code>IntType</code> shall denote an integral
-type large enough to store values up to (m-1). If the template parameter
-<code>m</code> is 0, the behaviour is implementation-defined. Otherwise, the
-template parameters <code>a</code> and <code>c</code> shall be less than m.
-
- <p>The size of the state x(i) is 1.</p>
- <pre>
- explicit linear_congruential(IntType x0 = 1)
-</pre><strong>Requires:</strong> <code>c > 0 || (x0 % m) > 0</code><br>
-
- <strong>Effects:</strong> Constructs a <code>linear_congruential</code>
- engine with state x(0) := <code>x0</code> mod m.
- <pre>
- void seed(IntType x0 = 1)
-</pre><strong>Requires:</strong> <code>c > 0 || (x0 % m) > 0</code><br>
-
- <strong>Effects:</strong> Sets the state x(i) of the engine to
- <code>x0</code> mod m.
- <pre>
- template<class In> linear_congruential(In& first, In last)
-</pre><strong>Requires:</strong> <code>c > 0 || *first > 0</code><br>
- <strong>Effects:</strong> Sets the state x(i) of the engine to
- <code>*first</code> mod m.<br>
- <strong>Complexity:</strong> Exactly one dereference of
- <code>*first</code>.
- <pre>
- template<class CharT, class traits,
- class IntType, IntType a, IntType c, IntType m>
- basic_ostream<CharT, traits>& operator<<(basic_ostream<CharT, traits>& os,
- const linear_congruential<IntType, a, c, m>& x);
-</pre><strong>Effects:</strong> Writes x(i) to <code>os</code>.
-
- <h4>Class template <code>mersenne_twister</code></h4>A
- <code>mersenne_twister</code> engine produces random numbers o(x(i)) using
- the following computation, performed modulo 2<sup>w</sup>. <code>um</code>
- is a value with only the upper <code>w-r</code> bits set in its binary
- representation. <code>lm</code> is a value with only its lower
- <code>r</code> bits set in its binary representation. <em>rshift</em> is a
- bitwise right shift with zero-valued bits appearing in the high bits of the
- result. <em>lshift</em> is a bitwise left shift with zero-valued bits
- appearing in the low bits of the result.
-
- <ul>
- <li>y(i) = (x(i-n) <em>bitand</em> um) | (x(i-(n-1)) <em>bitand</em>
- lm)</li>
-
- <li>If the lowest bit of the binary representation of y(i) is set, x(i) =
- x(i-(n-m)) <em>xor</em> (y(i) <em>rshift</em> 1) <em>xor</em> a;
- otherwise x(i) = x(i-(n-m)) <em>xor</em> (y(i) <em>rshift</em> 1).</li>
-
- <li>z1(i) = x(i) <em>xor</em> ( x(i) <em>rshift</em> u )</li>
-
- <li>z2(i) = z1(i) <em>xor</em> ( (z1(i) <em>lshift</em> s)
- <em>bitand</em> b )</li>
-
- <li>z3(i) = z2(i) <em>xor</em> ( (z2(i) <em>lshift</em> t)
- <em>bitand</em> c )</li>
-
- <li>o(x(i)) = z3(i) <em>xor</em> ( z3(i) <em>rshift</em> l )</li>
- </ul>
- <pre>
-namespace std {
- template<class UIntType, int w, int n, int m, int r, UIntType a, int u,
- int s, UIntType b, int t, UIntType c, int l>
- class mersenne_twister
- {
- public:
- // <em>types</em>
- typedef UIntType result_type;
-
- // <em>parameter values</em>
- static const int word_size = w;
- static const int state_size = n;
- static const int shift_size = m;
- static const int mask_bits = r;
- static const UIntType parameter_a = a;
- static const int output_u = u;
- static const int output_s = s;
- static const UIntType output_b = b;
- static const int output_t = t;
- static const UIntType output_c = c;
- static const int output_l = l;
-
- // <em> constructors and member function</em>
- mersenne_twister();
- explicit mersenne_twister(UIntType value);
- template<class In> mersenne_twister(In& first, In last);
- void seed();
- void seed(UIntType value);
- template<class In> void seed(In& first, In last);
- result_type min() const;
- result_type max() const;
- result_type operator()();
- };
-
- template<class UIntType, int w, int n, int m, int r, UIntType a, int u,
- int s, UIntType b, int t, UIntType c, int l>
- bool operator==(const mersenne_twister<UIntType, w, n, m, r, a, u, s, b, t, c, l>& y,
- const mersenne_twister<UIntType, w, n, m, r, a, u, s, b, t, c, l>& x);
- template<class UIntType, int w, int n, int m, int r, UIntType a, int u,
- int s, UIntType b, int t, UIntType c, int l>
- bool operator!=(const mersenne_twister<UIntType, w, n, m, r, a, u, s, b, t, c, l>& y,
- const mersenne_twister<UIntType, w, n, m, r, a, u, s, b, t, c, l>& x);
-
- template<class CharT, class traits,
- class UIntType, int w, int n, int m, int r, UIntType a, int u,
- int s, UIntType b, int t, UIntType c, int l>
- basic_ostream<CharT, traits>& operator<<(basic_ostream<CharT, traits>& os,
- const mersenne_twister<UIntType, w, n, m, r, a, u, s, b, t, c, l>& x);
- template<class CharT, class traits,
- class UIntType, int w, int n, int m, int r, UIntType a, int u,
- int s, UIntType b, int t, UIntType c, int l>
- basic_istream<CharT, traits>& operator>>(basic_istream<CharT, traits>& is,
- mersenne_twister<UIntType, w, n, m, r, a, u, s, b, t, c, l>& x);
-}
-</pre>The template parameter <code>UIntType</code> shall denote an unsigned
-integral type large enough to store values up to 2<sup>w</sup>-1. Also, the
-following relations shall hold: 1<=m<=n. 0<=r,u,s,t,l<=w.
-0<=a,b,c<=2<sup>w</sup>-1.
-
- <p>The size of the state x(i) is <code>n</code>.</p>
- <pre>
- mersenne_twister()
-</pre><strong>Effects:</strong> Constructs a <code>mersenne_twister</code>
-engine and invokes <code>seed()</code>.
- <pre>
- explicit mersenne_twister(result_type value)
-</pre><strong>Effects:</strong> Constructs a <code>mersenne_twister</code>
-engine and invokes <code>seed(value)</code>.
- <pre>
- template<class In> mersenne_twister(In& first, In last)
-</pre><strong>Effects:</strong> Constructs a <code>mersenne_twister</code>
-engine and invokes <code>seed(first, last)</code>.
- <pre>
- void seed()
-</pre><strong>Effects:</strong> Invokes <code>seed(4357)</code>.
- <pre>
- void seed(result_type value)
-</pre><strong>Requires:</strong> <code>value > 0</code><br>
- <strong>Effects:</strong> With a linear congruential generator l(i) having
- parameters m<sub>l</sub> = 2<sup>32</sup>, a<sub>l</sub> = 69069,
- c<sub>l</sub> = 0, and l(0) = <code>value</code>, sets x(-n) ... x(-1) to
- l(1) ... l(n), respectively.<br>
- <strong>Complexity:</strong> O(n)
- <pre>
- template<class In> void seed(In& first, In last)
-</pre><strong>Effects:</strong> Given the values z<sub>0</sub> ...
-z<sub>n-1</sub> obtained by dereferencing [first, first+n), sets x(-n) ...
-x(-1) to z<sub>0</sub> mod 2<sup>w</sup> ... z<sub>n-1</sub> mod
-2<sup>w</sup>.<br>
- <strong>Complexity:</strong> Exactly <code>n</code> dereferences of
- <code>first</code>.
- <pre>
- template<class UIntType, int w, int n, int m, int r, UIntType a, int u,
- int s, UIntType b, int t, UIntType c, int l>
- bool operator==(const mersenne_twister<UIntType, w, n, m, r, a, u, s, b, t, c, l>& y,
- const mersenne_twister<UIntType, w, n, m, r, a, u, s, b, t, c, l>& x)
-</pre><strong>Returns:</strong> x(i-n) == y(j-n) and ... and x(i-1) ==
-y(j-1)<br>
- <strong>Notes:</strong> Assumes the next output of <code>x</code> is
- o(x(i)) and the next output of <code>y</code> is o(y(j)).<br>
- <strong>Complexity:</strong> O(n)
- <pre>
- template<class CharT, class traits,
- class UIntType, int w, int n, int m, int r, UIntType a, int u,
- int s, UIntType b, int t, UIntType c, int l>
- basic_ostream<CharT, traits>& operator<<(basic_ostream<CharT, traits>& os,
- const mersenne_twister<UIntType, w, n, m, r, a, u, s, b, t, c, l>& x)
-</pre><strong>Effects:</strong> Writes x(i-n), ... x(i-1) to <code>os</code>,
-in that order.<br>
- <strong>Complexity:</strong> O(n)
-
- <h4>Class template <code>subtract_with_carry</code></h4>A
- <code>subtract_with_carry</code> engine produces integer random numbers
- using x(i) = (x(i-s) - x(i-r) - carry(i-1)) mod m; carry(i) = 1 if x(i-s) -
- x(i-r) - carry(i-1) < 0, else carry(i) = 0.
- <pre>
-namespace std {
- template<class IntType, IntType m, int s, int r>
- class subtract_with_carry
- {
- public:
- // <em>types</em>
- typedef IntType result_type;
-
- // <em>parameter values</em>
- static const IntType modulus = m;
- static const int long_lag = r;
- static const int short_lag = s;
-
- // <em> constructors and member function</em>
- subtract_with_carry();
- explicit subtract_with_carry(IntType value);
- template<class In> subtract_with_carry(In& first, In last);
- void seed(IntType value = 19780503);
- template<class In> void seed(In& first, In last);
- result_type min() const;
- result_type max() const;
- result_type operator()();
- };
- template<class IntType, IntType m, int s, int r>
- bool operator==(const subtract_with_carry<IntType, m, s, r> & x,
- const subtract_with_carry<IntType, m, s, r> & y);
-
- template<class IntType, IntType m, int s, int r>
- bool operator!=(const subtract_with_carry<IntType, m, s, r> & x,
- const subtract_with_carry<IntType, m, s, r> & y);
-
- template<class CharT, class Traits,
- class IntType, IntType m, int s, int r>
- std::basic_ostream<CharT,Traits>& operator<<(std::basic_ostream<CharT,Traits>& os,
- const subtract_with_carry<IntType, m, s, r>& f);
-
- template<class CharT, class Traits,
- class IntType, IntType m, int s, int r>
- std::basic_istream<CharT,Traits>& operator>>(std::basic_istream<CharT,Traits>& is,
- subtract_with_carry<IntType, m, s, r>& f);
-}
-</pre>The template parameter <code>IntType</code> shall denote a signed
-integral type large enough to store values up to m-1. The following relation
-shall hold: 0<s<r. Let w the number of bits in the binary
-representation of m.
-
- <p>The size of the state is <code>r</code>.</p>
- <pre>
- subtract_with_carry()
-</pre><strong>Effects:</strong> Constructs a <code>subtract_with_carry</code>
-engine and invokes <code>seed()</code>.
- <pre>
- explicit subtract_with_carry(IntType value)
-</pre><strong>Effects:</strong> Constructs a <code>subtract_with_carry</code>
-engine and invokes <code>seed(value)</code>.
- <pre>
- template<class In> subtract_with_carry(In& first, In last)
-</pre><strong>Effects:</strong> Constructs a <code>subtract_with_carry</code>
-engine and invokes <code>seed(first, last)</code>.
- <pre>
- void seed(IntType value = 19780503)
-</pre><strong>Requires:</strong> <code>value > 0</code><br>
- <strong>Effects:</strong> With a linear congruential generator l(i) having
- parameters m<sub>l</sub> = 2147483563, a<sub>l</sub> = 40014, c<sub>l</sub>
- = 0, and l(0) = <code>value</code>, sets x(-r) ... x(-1) to l(1) mod m ...
- l(r) mod m, respectively. If x(-1) == 0, sets carry(-1) = 1, else sets
- carry(-1) = 0.<br>
- <strong>Complexity:</strong> O(r)
- <pre>
- template<class In> void seed(In& first, In last)
-</pre><strong>Effects:</strong> With n=w/32+1 (rounded downward) and given
-the values z<sub>0</sub> ... z<sub>n*r-1</sub> obtained by dereferencing
-[first, first+n*r), sets x(-r) ... x(-1) to (z<sub>0</sub> * 2<sup>32</sup> +
-... + z<sub>n-1</sub> * 2<sup>32*(n-1)</sup>) mod m ... (z<sub>(r-1)*n</sub>
-* 2<sup>32</sup> + ... + z<sub>r-1</sub> * 2<sup>32*(n-1)</sup>) mod m. If
-x(-1) == 0, sets carry(-1) = 1, else sets carry(-1) = 0.<br>
- <strong>Complexity:</strong> Exactly <code>r*n</code> dereferences of
- <code>first</code>.
- <pre>
- template<class IntType, IntType m, int s, int r>
- bool operator==(const subtract_with_carry<IntType, m, s, r> & x,
- const subtract_with_carry<IntType, m, s, r> & y)
-</pre><strong>Returns:</strong> x(i-r) == y(j-r) and ... and x(i-1) ==
-y(j-1).<br>
- <strong>Notes:</strong> Assumes the next output of <code>x</code> is x(i)
- and the next output of <code>y</code> is y(j).<br>
- <strong>Complexity:</strong> O(r)
- <pre>
- template<class CharT, class Traits,
- class IntType, IntType m, int s, int r>
- std::basic_ostream<CharT,Traits>& operator<<(std::basic_ostream<CharT,Traits>& os,
- const subtract_with_carry<IntType, m, s, r>& f)
-</pre><strong>Effects:</strong> Writes x(i-r) ... x(i-1), carry(i-1) to
-<code>os</code>, in that order.<br>
- <strong>Complexity:</strong> O(r)
-
- <h4>Class template <code>subtract_with_carry_01</code></h4>A
- <code>subtract_with_carry_01</code> engine produces floating-point random
- numbers using x(i) = (x(i-s) - x(i-r) - carry(i-1)) mod 1; carry(i) =
- 2<sup>-w</sup> if x(i-s) - x(i-r) - carry(i-1) < 0, else carry(i) = 0.
- <pre>
-namespace std {
- template<class RealType, int w, int s, int r>
- class subtract_with_carry_01
- {
- public:
- // <em>types</em>
- typedef RealType result_type;
-
- // <em>parameter values</em>
- static const int word_size = w;
- static const int long_lag = r;
- static const int short_lag = s;
-
- // <em> constructors and member function</em>
- subtract_with_carry_01();
- explicit subtract_with_carry_01(unsigned int value);
- template<class In> subtract_with_carry_01(In& first, In last);
- void seed(unsigned int value = 19780503);
- template<class In> void seed(In& first, In last);
- result_type min() const;
- result_type max() const;
- result_type operator()();
- };
- template<class RealType, int w, int s, int r>
- bool operator==(const subtract_with_carry_01<RealType, w, s, r> x,
- const subtract_with_carry_01<RealType, w, s, r> y);
-
- template<class RealType, int w, int s, int r>
- bool operator!=(const subtract_with_carry_01<RealType, w, s, r> x,
- const subtract_with_carry_01<RealType, w, s, r> y);
-
- template<class CharT, class Traits,
- class RealType, int w, int s, int r>
- std::basic_ostream<CharT,Traits>& operator<<(std::basic_ostream<CharT,Traits>& os,
- const subtract_with_carry_01<RealType, w, s, r>& f);
-
- template<class CharT, class Traits,
- class RealType, int w, int s, int r>
- std::basic_istream<CharT,Traits>& operator>>(std::basic_istream<CharT,Traits>& is,
- subtract_with_carry_01<RealType, w, s, r>& f);
-}
-</pre>The following relation shall hold: 0<s<r.
-
- <p>The size of the state is <code>r</code>.</p>
- <pre>
- subtract_with_carry_01()
-</pre><strong>Effects:</strong> Constructs a
-<code>subtract_with_carry_01</code> engine and invokes <code>seed()</code>.
- <pre>
- explicit subtract_with_carry_01(unsigned int value)
-</pre><strong>Effects:</strong> Constructs a
-<code>subtract_with_carry_01</code> engine and invokes
-<code>seed(value)</code>.
- <pre>
- template<class In> subtract_with_carry_01(In& first, In last)
-</pre><strong>Effects:</strong> Constructs a
-<code>subtract_with_carry_01</code> engine and invokes <code>seed(first,
-last)</code>.
- <pre>
- void seed(unsigned int value = 19780503)
-</pre><strong>Effects:</strong> With a linear congruential generator l(i)
-having parameters m = 2147483563, a = 40014, c = 0, and l(0) =
-<code>value</code>, sets x(-r) ... x(-1) to (l(1)*2<sup>-w</sup>) mod 1 ...
-(l(r)*2<sup>-w</sup>) mod 1, respectively. If x(-1) == 0, sets carry(-1) =
-2<sup>-w</sup>, else sets carry(-1) = 0.<br>
- <strong>Complexity:</strong> O(r)
- <pre>
- template<class In> void seed(In& first, In last)
-</pre><strong>Effects:</strong> With n=w/32+1 (rounded downward) and given
-the values z<sub>0</sub> ... z<sub>n*r-1</sub> obtained by dereferencing
-[first, first+n*r), sets x(-r) ... x(-1) to (z<sub>0</sub> * 2<sup>32</sup> +
-... + z<sub>n-1</sub> * 2<sup>32*(n-1)</sup>) * 2<sup>-w</sup> mod 1 ...
-(z<sub>(r-1)*n</sub> * 2<sup>32</sup> + ... + z<sub>r-1</sub> *
-2<sup>32*(n-1)</sup>) * 2<sup>-w</sup> mod 1. If x(-1) == 0, sets carry(-1) =
-2<sup>-w</sup>, else sets carry(-1) = 0.<br>
- <strong>Complexity:</strong> O(r*n)
- <pre>
- template<class RealType, int w, int s, int r>
- bool operator==(const subtract_with_carry<RealType, w, s, r> x,
- const subtract_with_carry<RealType, w, s, r> y);
-</pre><strong>Returns:</strong> true, if and only if x(i-r) == y(j-r) and ...
-and x(i-1) == y(j-1).<br>
- <strong>Complexity:</strong> O(r)
- <pre>
- template<class CharT, class Traits,
- class RealType, int w, int s, int r>
- std::basic_ostream<CharT,Traits>& operator<<(std::basic_ostream<CharT,Traits>& os,
- const subtract_with_carry<RealType, w, s, r>& f);
-</pre><strong>Effects:</strong> Write x(i-r)*2<sup>w</sup> ...
-x(i-1)*2<sup>w</sup>, carry(i-1)*2<sup>w</sup> to <code>os</code>, in that
-order.<br>
- <strong>Complexity:</strong> O(r)
-
- <h4>Class template <code>discard_block</code></h4>A
- <code>discard_block</code> engine produces random numbers from some base
- engine by discarding blocks of data.
- <pre>
-namespace std {
- template<class UniformRandomNumberGenerator, int p, int r>
- class discard_block
- {
- public:
- // <em>types</em>
- typedef UniformRandomNumberGenerator base_type;
- typedef typename base_type::result_type result_type;
-
- // <em>parameter values</em>
- static const int block_size = p;
- static const int used_block = r;
-
- // <em> constructors and member function</em>
- discard_block();
- explicit discard_block(const base_type & rng);
- template<class In> discard_block(In& first, In last);
- void seed();
- template<class In> void seed(In& first, In last);
- const base_type& base() const;
- result_type min() const;
- result_type max() const;
- result_type operator()();
- private:
- // base_type b; <em>exposition only</em>
- // int n; <em>exposition only</em>
- };
- template<class UniformRandomNumberGenerator, int p, int r>
- bool operator==(const discard_block<UniformRandomNumberGenerator,p,r> & x,
- (const discard_block<UniformRandomNumberGenerator,p,r> & y);
- template<class UniformRandomNumberGenerator, int p, int r,
- typename UniformRandomNumberGenerator::result_type val>
- bool operator!=(const discard_block<UniformRandomNumberGenerator,p,r> & x,
- (const discard_block<UniformRandomNumberGenerator,p,r> & y);
-
- template<class CharT, class traits,
- class UniformRandomNumberGenerator, int p, int r>
- basic_ostream<CharT, traits>& operator<<(basic_ostream<CharT, traits>& os,
- const discard_block<UniformRandomNumberGenerator,p,r> & x);
- template<class CharT, class traits,
- class UniformRandomNumberGenerator, int p, int r>
- basic_istream<CharT, traits>& operator>>(basic_istream<CharT, traits>& is,
- discard_block<UniformRandomNumberGenerator,p,r> & x);
-
-}
-</pre>The template parameter <code>UniformRandomNumberGenerator</code> shall
-denote a class that satisfies all the requirements of a uniform random number
-generator, given in tables in section x.x. r <= p. The size of the state
-is the size of <code><em>b</em></code> plus 1.
- <pre>
- discard_block()
-</pre><strong>Effects:</strong> Constructs a <code>discard_block</code>
-engine. To construct the subobject <em>b</em>, invokes its default
-constructor. Sets <code>n = 0</code>.
- <pre>
- explicit discard_block(const base_type & rng)
-</pre><strong>Effects:</strong> Constructs a <code>discard_block</code>
-engine. Initializes <em>b</em> with a copy of <code>rng</code>. Sets <code>n
-= 0</code>.
- <pre>
- template<class In> discard_block(In& first, In last)
-</pre><strong>Effects:</strong> Constructs a <code>discard_block</code>
-engine. To construct the subobject <em>b</em>, invokes the <code>b(first,
-last)</code> constructor. Sets <code>n = 0</code>.
- <pre>
- void seed()
-</pre><strong>Effects:</strong> Invokes <code><em>b</em>.seed()</code> and
-sets <code>n = 0</code>.
- <pre>
- template<class In> void seed(In& first, In last)
-</pre><strong>Effects:</strong> Invokes <code><em>b</em>.seed(first,
-last)</code> and sets <code>n = 0</code>.
- <pre>
- const base_type& base() const
-</pre><strong>Returns:</strong> <em>b</em>
- <pre>
- result_type operator()()
-</pre><strong>Effects:</strong> If <em>n</em> >= r, invokes
-<code><em>b</em></code> (p-r) times, discards the values returned, and sets
-<code>n = 0</code>. In any case, then increments <code>n</code> and returns
-<code><em>b()</em></code>.
- <pre>
- template<class CharT, class traits,
- class UniformRandomNumberGenerator, int p, int r>
- basic_ostream<CharT, traits>& operator<<(basic_ostream<CharT, traits>& os,
- const discard_block<UniformRandomNumberGenerator,p,r> & x);
-</pre><strong>Effects:</strong> Writes <code><em>b</em></code>, then
-<code><em>n</em></code> to <code>os</code>.
-
- <h4>Class template <code>xor_combine</code></h4>A <code>xor_combine</code>
- engine produces random numbers from two integer base engines by merging
- their random values with bitwise exclusive-or.
- <pre>
-namespace std {
- template<class UniformRandomNumberGenerator1, int s1,
- class UniformRandomNumberGenerator2, int s2>
- class xor_combine
- {
- public:
- // <em>types</em>
- typedef UniformRandomNumberGenerator1 base1_type;
- typedef UniformRandomNumberGenerator2 base2_type;
- typedef typename base_type::result_type result_type;
-
- // <em>parameter values</em>
- static const int shift1 = s1;
- static const int shift2 = s2;
-
- // <em> constructors and member function</em>
- xor_combine();
- xor_combine(const base1_type & rng1, const base2_type & rng2);
- template<class In> xor_combine(In& first, In last);
- void seed();
- template<class In> void seed(In& first, In last);
- const base1_type& base1() const;
- const base2_type& base2() const;
- result_type min() const;
- result_type max() const;
- result_type operator()();
- private:
- // base1_type b1; <em>exposition only</em>
- // base2_type b2; <em>exposition only</em>
- };
- template<class UniformRandomNumberGenerator1, int s1,
- class UniformRandomNumberGenerator2, int s2>
- bool operator==(const xor_combine<UniformRandomNumberGenerator1, s1,
- UniformRandomNumberGenerator2, s2> & x,
- (const xor_combine<UniformRandomNumberGenerator1, s1,
- UniformRandomNumberGenerator2, s2> & y);
- template<class UniformRandomNumberGenerator1, int s1,
- class UniformRandomNumberGenerator2, int s2>
- bool operator!=(const xor_combine<UniformRandomNumberGenerator1, s1,
- UniformRandomNumberGenerator2, s2> & x,
- (const xor_combine<UniformRandomNumberGenerator1, s1,
- UniformRandomNumberGenerator2, s2> & y);
-
- template<class CharT, class traits,
- class UniformRandomNumberGenerator1, int s1,
- class UniformRandomNumberGenerator2, int s2>
- basic_ostream<CharT, traits>& operator<<(basic_ostream<CharT, traits>& os,
- const xor_combine<UniformRandomNumberGenerator1, s1,
- UniformRandomNumberGenerator2, s2> & x);
- template<class CharT, class traits,
- class UniformRandomNumberGenerator1, int s1,
- class UniformRandomNumberGenerator2, int s2>
- basic_istream<CharT, traits>& operator>>(basic_istream<CharT, traits>& is,
- xor_combine<UniformRandomNumberGenerator1, s1,
- UniformRandomNumberGenerator2, s2> & x);
-
-}
-</pre>The template parameters <code>UniformRandomNumberGenerator1</code> and
-<code>UniformRandomNumberGenerator1</code> shall denote classes that satisfy
-all the requirements of a uniform random number generator, given in tables in
-section x.x . The size of the state is the size of <code><em>b1</em></code>
-plus the size of <code><em>b2</em></code>.
- <pre>
- xor_combine()
-</pre><strong>Effects:</strong> Constructs a <code>xor_combine</code> engine.
-To construct each of the subobjects <em>b1</em> and <em>b2</em>, invokes
-their respective default constructors.
- <pre>
- xor_combine(const base1_type & rng1, const base2_type & rng2)
-</pre><strong>Effects:</strong> Constructs a <code>xor_combine</code> engine.
-Initializes <em>b1</em> with a copy of <code>rng1</code> and <em>b2</em> with
-a copy of <code>rng2</code>.
- <pre>
- template<class In> xor_combine(In& first, In last)
-</pre><strong>Effects:</strong> Constructs a <code>xor_combine</code> engine.
-To construct the subobject <em>b1</em>, invokes the <code>b1(first,
-last)</code> constructor. Then, to construct the subobject <em>b2</em>,
-invokes the <code>b2(first, last)</code> constructor.
- <pre>
- void seed()
-</pre><strong>Effects:</strong> Invokes <code><em>b1</em>.seed()</code> and
-<code><em>b2</em>.seed()</code>.
- <pre>
- template<class In> void seed(In& first, In last)
-</pre><strong>Effects:</strong> Invokes <code><em>b1</em>.seed(first,
-last)</code>, then invokes <code><em>b2</em>.seed(first, last)</code>.
- <pre>
- const base1_type& base1() const
-</pre><strong>Returns:</strong> <em>b1</em>
- <pre>
- const base2_type& base2() const
-</pre><strong>Returns:</strong> <em>b2</em>
- <pre>
- result_type operator()()
-</pre><strong>Returns:</strong> (<code><em>b1</em>() << s1) ^
-(<em>b2</em>() << s2)</code>.
- <pre>
- template<class CharT, class traits,
- class UniformRandomNumberGenerator1, int s1,
- class UniformRandomNumberGenerator2, int s2>
- basic_ostream<CharT, traits>& operator<<(basic_ostream<CharT, traits>& os,
- const xor_combine<UniformRandomNumberGenerator1, s1,
- UniformRandomNumberGenerator2, s2> & x);
-</pre><strong>Effects:</strong> Writes <code><em>b1</em></code>, then <code>
- <em>b2</em></code> to <code>os</code>.
-
- <h3>Engines with predefined parameters</h3>
- <pre>
-namespace std {
- typedef linear_congruential</* <em>implementation defined</em> */, 16807, 0, 2147483647> minstd_rand0;
- typedef linear_congruential</* <em>implementation defined</em> */, 48271, 0, 2147483647> minstd_rand;
-
- typedef mersenne_twister</* <em>implementation defined</em> */,32,624,397,31,0x9908b0df,11,7,0x9d2c5680,15,0xefc60000,18> mt19937;
-
- typedef subtract_with_carry_01<float, 24, 10, 24> ranlux_base_01;
- typedef subtract_with_carry_01<double, 48, 10, 24> ranlux64_base_01;
-
- typedef discard_block<subtract_with_carry</* <em>implementation defined</em> */, (1<<24), 10, 24>, 223, 24> ranlux3;
- typedef discard_block<subtract_with_carry</* <em>implementation defined</em> */, (1<<24), 10, 24>, 389, 24> ranlux4;
-
- typedef discard_block<subtract_with_carry_01<float, 24, 10, 24>, 223, 24> ranlux3_01;
- typedef discard_block<subtract_with_carry_01<float, 24, 10, 24>, 389, 24> ranlux4_01;
-}
-</pre>For a default-constructed <code>minstd_rand0</code> object, x(10000) =
-1043618065. For a default-constructed <code>minstd_rand</code> object,
-x(10000) = 399268537.
-
- <p>For a default-constructed <code>mt19937</code> object, x(10000) =
- 3346425566.</p>
-
- <p>For a default-constructed <code>ranlux3</code> object, x(10000) =
- 5957620. For a default-constructed <code>ranlux4</code> object, x(10000) =
- 8587295. For a default-constructed <code>ranlux3_01</code> object, x(10000)
- = 5957620 * 2<sup>-24</sup>. For a default-constructed
- <code>ranlux4_01</code> object, x(10000) = 8587295 * 2<sup>-24</sup>.</p>
-
- <h3>Class <code>random_device</code></h3>A <code>random_device</code>
- produces non-deterministic random numbers. It satisfies all the
- requirements of a uniform random number generator (given in tables in
- section x.x). Descriptions are provided here only for operations on the
- engines that are not described in one of these tables or for operations
- where there is additional semantic information.
-
- <p>If implementation limitations prevent generating non-deterministic
- random numbers, the implementation can employ a pseudo-random number
- engine.</p>
- <pre>
-namespace std {
- class random_device
- {
- public:
- // <em>types</em>
- typedef unsigned int result_type;
-
- // <em>constructors, destructors and member functions</em>
- explicit random_device(const std::string& token = /* <em>implementation-defined</em> */);
- result_type min() const;
- result_type max() const;
- double entropy() const;
- result_type operator()();
-
- private:
- random_device(const random_device& );
- void operator=(const random_device& );
- };
-}
-</pre>
- <pre>
- explicit random_device(const std::string& token = /* <em>implementation-defined</em> */)
-</pre><strong>Effects:</strong> Constructs a <code>random_device</code>
-non-deterministic random number engine. The semantics and default value of
-the <code>token</code> parameter are implementation-defined. [Footnote: The
-parameter is intended to allow an implementation to differentiate between
-different sources of randomness.]<br>
- <strong>Throws:</strong> A value of some type derived from
- <code>exception</code> if the <code>random_device</code> could not be
- initialized.
- <pre>
- result_type min() const
-</pre><strong>Returns:</strong>
-<code>numeric_limits<result_type>::min()</code>
- <pre>
- result_type max() const
-</pre><strong>Returns:</strong>
-<code>numeric_limits<result_type>::max()</code>
- <pre>
- double entropy() const
-</pre><strong>Returns:</strong> An entropy estimate for the random numbers
-returned by operator(), in the range <code>min()</code> to log<sub>2</sub>(
-<code>max()</code>+1). A deterministic random number generator (e.g. a
-pseudo-random number engine) has entropy 0.<br>
- <strong>Throws:</strong> Nothing.
- <pre>
- result_type operator()()
-</pre><strong>Returns:</strong> A non-deterministic random value, uniformly
-distributed between <code>min()</code> and <code>max()</code>, inclusive. It
-is implementation-defined how these values are generated.<br>
- <strong>Throws:</strong> A value of some type derived from
- <code>exception</code> if a random number could not be obtained.
-
- <h3>Random distribution class templates</h3>The class templates specified
- in this section satisfy all the requirements of a random distribution
- (given in tables in section x.x). Descriptions are provided here only for
- operations on the distributions that are not described in one of these
- tables or for operations where there is additional semantic information.
-
- <p>A template parameter named <code>IntType</code> shall denote a type that
- represents an integer number. This type shall meet the requirements for a
- numeric type (26.1 [lib.numeric.requirements]), the binary operators +, -,
- *, /, % shall be applicable to it, and a conversion from <code>int</code>
- shall exist. <em>[Footnote: The built-in types <code>int</code> and
- <code>long</code> meet these requirements.]</em></p>
-
- <p>Given an object whose type is specified in this subclause, if the
- lifetime of the uniform random number generator referred to in the
- constructor invocation for that object has ended, any use of that object is
- undefined.</p>
-
- <p>No function described in this section throws an exception, unless an
- operation on values of <code>IntType</code> or <code>RealType</code> throws
- an exception. <em>[Note: Then, the effects are undefined, see
- [lib.numeric.requirements]. ]</em></p>
-
- <p>The algorithms for producing each of the specified distributions are
- implementation-defined.</p>
-
- <h4>Class template <code>uniform_int</code></h4>A <code>uniform_int</code>
- random distribution produces integer random numbers x in the range min
- <= x <= max, with equal probability. min and max are the parameters
- of the distribution.
-
- <p>A <code>uniform_int</code> random distribution satisfies all the
- requirements of a uniform random number generator (given in tables in
- section x.x).</p>
- <pre>
-namespace std {
- template<class IntType = int>
- class uniform_int
- {
- public:
- // <em>types</em>
- typedef IntType input_type;
- typedef IntType result_type;
-
- // <em> constructors and member function</em>
- explicit uniform_int(IntType min = 0, IntType max = 9);
- result_type min() const;
- result_type max() const;
- void reset();
- template<class UniformRandomNumberGenerator>
- result_type operator()(UniformRandomNumberGenerator& urng);
- template<class UniformRandomNumberGenerator>
- result_type operator()(UniformRandomNumberGenerator& urng, result_type n);
- };
-}
-</pre>
- <pre>
- uniform_int(IntType min = 0, IntType max = 9)
-</pre><strong>Requires:</strong> min <= max<br>
- <strong>Effects:</strong> Constructs a <code>uniform_int</code> object.
- <code>min</code> and <code>max</code> are the parameters of the
- distribution.
- <pre>
- result_type min() const
-</pre><strong>Returns:</strong> The "min" parameter of the distribution.
- <pre>
- result_type max() const
-</pre><strong>Returns:</strong> The "max" parameter of the distribution.
- <pre>
- result_type operator()(UniformRandomNumberGenerator& urng, result_type n)
-</pre><strong>Returns:</strong> A uniform random number x in the range 0
-<= x < n. <em>[Note: This allows a <code>variate_generator</code>
-object with a <code>uniform_int</code> distribution to be used with
-std::random_shuffe, see [lib.alg.random.shuffle]. ]</em>
-
- <h4>Class template <code>bernoulli_distribution</code></h4>A
- <code>bernoulli_distribution</code> random distribution produces
- <code>bool</code> values distributed with probabilities p(true) = p and
- p(false) = 1-p. p is the parameter of the distribution.
- <pre>
-namespace std {
- template<class RealType = double>
- class bernoulli_distribution
- {
- public:
- // <em>types</em>
- typedef int input_type;
- typedef bool result_type;
-
- // <em> constructors and member function</em>
- explicit bernoulli_distribution(const RealType& p = RealType(0.5));
- RealType p() const;
- void reset();
- template<class UniformRandomNumberGenerator>
- result_type operator()(UniformRandomNumberGenerator& urng);
- };
-}
-</pre>
- <pre>
- bernoulli_distribution(const RealType& p = RealType(0.5))
-</pre><strong>Requires:</strong> 0 <= p <= 1<br>
- <strong>Effects:</strong> Constructs a <code>bernoulli_distribution</code>
- object. <code>p</code> is the parameter of the distribution.
- <pre>
- RealType p() const
-</pre><strong>Returns:</strong> The "p" parameter of the distribution.
-
- <h4>Class template <code>geometric_distribution</code></h4>A
- <code>geometric_distribution</code> random distribution produces integer
- values <em>i</em> >= 1 with p(i) = (1-p) * p<sup>i-1</sup>. p is the
- parameter of the distribution.
- <pre>
-namespace std {
- template<class IntType = int, class RealType = double>
- class geometric_distribution
- {
- public:
- // <em>types</em>
- typedef RealType input_type;
- typedef IntType result_type;
-
- // <em> constructors and member function</em>
- explicit geometric_distribution(const RealType& p = RealType(0.5));
- RealType p() const;
- void reset();
- template<class UniformRandomNumberGenerator>
- result_type operator()(UniformRandomNumberGenerator& urng);
- };
-}
-</pre>
- <pre>
- geometric_distribution(const RealType& p = RealType(0.5))
-</pre><strong>Requires:</strong> 0 < p < 1<br>
- <strong>Effects:</strong> Constructs a <code>geometric_distribution</code>
- object; <code>p</code> is the parameter of the distribution.
- <pre>
- RealType p() const
-</pre><strong>Returns:</strong> The "p" parameter of the distribution.
-
- <h4>Class template <code>poisson_distribution</code></h4>A
- <code>poisson_distribution</code> random distribution produces integer
- values <em>i</em> >= 0 with p(i) = exp(-mean) * mean<sup>i</sup> / i!.
- mean is the parameter of the distribution.
- <pre>
-namespace std {
- template<class IntType = int, class RealType = double>
- class poisson_distribution
- {
- public:
- // <em>types</em>
- typedef RealType input_type;
- typedef IntType result_type;
-
- // <em> constructors and member function</em>
- explicit poisson_distribution(const RealType& mean = RealType(1));
- RealType mean() const;
- void reset();
- template<class UniformRandomNumberGenerator>
- result_type operator()(UniformRandomNumberGenerator& urng);
- };
-}
-</pre>
- <pre>
- poisson_distribution(const RealType& mean = RealType(1))
-</pre><strong>Requires:</strong> mean > 0<br>
- <strong>Effects:</strong> Constructs a <code>poisson_distribution</code>
- object; <code>mean</code> is the parameter of the distribution.
- <pre>
- RealType mean() const
-</pre><strong>Returns:</strong> The "mean" parameter of the distribution.
-
- <h4>Class template <code>binomial_distribution</code></h4>A
- <code>binomial_distribution</code> random distribution produces integer
- values <em>i</em> >= 0 with p(i) = (n over i) * p<sup>i</sup> *
- (1-p)<sup>t-i</sup>. t and p are the parameters of the distribution.
- <pre>
-namespace std {
- template<class IntType = int, class RealType = double>
- class binomial_distribution
- {
- public:
- // <em>types</em>
- typedef /* <em>implementation-defined</em> */ input_type;
- typedef IntType result_type;
-
- // <em> constructors and member function</em>
- explicit binomial_distribution(IntType t = 1, const RealType& p = RealType(0.5));
- IntType t() const;
- RealType p() const;
- void reset();
- template<class UniformRandomNumberGenerator>
- result_type operator()(UniformRandomNumberGenerator& urng);
- };
-}
-</pre>
- <pre>
- binomial_distribution(IntType t = 1, const RealType& p = RealType(0.5))
-</pre><strong>Requires:</strong> 0 <= p <= 1 and t >= 0<br>
- <strong>Effects:</strong> Constructs a <code>binomial_distribution</code>
- object; <code>t</code> and <code>p</code> are the parameters of the
- distribution.
- <pre>
- IntType t() const
-</pre><strong>Returns:</strong> The "t" parameter of the distribution.
- <pre>
- RealType p() const
-</pre><strong>Returns:</strong> The "p" parameter of the distribution.
-
- <h4>Class template <code>uniform_real</code></h4>A
- <code>uniform_real</code> random distribution produces floating-point
- random numbers x in the range min <= x <= max, with equal
- probability. min and max are the parameters of the distribution.
-
- <p>A <code>uniform_real</code> random distribution satisfies all the
- requirements of a uniform random number generator (given in tables in
- section x.x).</p>
- <pre>
-namespace std {
- template<class RealType = double>
- class uniform_real
- {
- public:
- // <em>types</em>
- typedef RealType input_type;
- typedef RealType result_type;
-
- // <em> constructors and member function</em>
- explicit uniform_real(RealType min = RealType(0), RealType max = RealType(1));
- result_type min() const;
- result_type max() const;
- void reset();
- template<class UniformRandomNumberGenerator>
- result_type operator()(UniformRandomNumberGenerator& urng);
- };
-}
-</pre>
- <pre>
- uniform_real(RealType min = RealType(0), RealType max = RealType(1))
-</pre><strong>Requires:</strong> min <= max<br>
- <strong>Effects:</strong> Constructs a <code>uniform_real</code> object;
- <code>min</code> and <code>max</code> are the parameters of the
- distribution.
- <pre>
- result_type min() const
-</pre><strong>Returns:</strong> The "min" parameter of the distribution.
- <pre>
- result_type max() const
-</pre><strong>Returns:</strong> The "max" parameter of the distribution.
-
- <h4>Class template <code>exponential_distribution</code></h4>An
- <code>exponential_distribution</code> random distribution produces random
- numbers x > 0 distributed with probability density function p(x) =
- lambda * exp(-lambda * x), where lambda is the parameter of the
- distribution.
- <pre>
-namespace std {
- template<class RealType = double>
- class exponential_distribution
- {
- public:
- // <em>types</em>
- typedef RealType input_type;
- typedef RealType result_type;
-
- // <em> constructors and member function</em>
- explicit exponential_distribution(const result_type& lambda = result_type(1));
- RealType lambda() const;
- void reset();
- template<class UniformRandomNumberGenerator>
- result_type operator()(UniformRandomNumberGenerator& urng);
- };
-}
-</pre>
- <pre>
- exponential_distribution(const result_type& lambda = result_type(1))
-</pre><strong>Requires:</strong> lambda > 0<br>
- <strong>Effects:</strong> Constructs an
- <code>exponential_distribution</code> object with <code>rng</code> as the
- reference to the underlying source of random numbers. <code>lambda</code>
- is the parameter for the distribution.
- <pre>
- RealType lambda() const
-</pre><strong>Returns:</strong> The "lambda" parameter of the distribution.
-
- <h4>Class template <code>normal_distribution</code></h4>A
- <code>normal_distribution</code> random distribution produces random
- numbers x distributed with probability density function p(x) =
- 1/sqrt(2*pi*sigma) * exp(- (x-mean)<sup>2</sup> / (2*sigma<sup>2</sup>) ),
- where mean and sigma are the parameters of the distribution.
- <pre>
-namespace std {
- template<class RealType = double>
- class normal_distribution
- {
- public:
- // <em>types</em>
- typedef RealType input_type;
- typedef RealType result_type;
-
- // <em> constructors and member function</em>
- explicit normal_distribution(base_type & rng, const result_type& mean = 0,
- const result_type& sigma = 1);
- RealType mean() const;
- RealType sigma() const;
- void reset();
- template<class UniformRandomNumberGenerator>
- result_type operator()(UniformRandomNumberGenerator& urng);
- };
-}
-</pre>
- <pre>
- explicit normal_distribution( const result_type& mean = 0,
- const result_type& sigma = 1);
-</pre><strong>Requires:</strong> sigma > 0<br>
- <strong>Effects:</strong> Constructs a <code>normal_distribution</code>
- object; <code>mean</code> and <code>sigma</code> are the parameters for the
- distribution.
- <pre>
- RealType mean() const
-</pre><strong>Returns:</strong> The "mean" parameter of the distribution.
- <pre>
- RealType sigma() const
-</pre><strong>Returns:</strong> The "sigma" parameter of the distribution.
-
- <h4>Class template <code>gamma_distribution</code></h4>A
- <code>gamma_distribution</code> random distribution produces random numbers
- x distributed with probability density function p(x) = 1/Gamma(alpha) *
- x<sup>alpha-1</sup> * exp(-x), where alpha is the parameter of the
- distribution.
- <pre>
-namespace std {
- template<class RealType = double>
- class gamma_distribution
- {
- public:
- // <em>types</em>
- typedef RealType input_type;
- typedef RealType result_type;
-
- // <em> constructors and member function</em>
- explicit gamma_distribution(const result_type& alpha = result_type(1));
- RealType alpha() const;
- void reset();
- template<class UniformRandomNumberGenerator>
- result_type operator()(UniformRandomNumberGenerator& urng);
- };
-}
-</pre>
- <pre>
- explicit gamma_distribution(const result_type& alpha = result_type(1));
-</pre><strong>Requires:</strong> alpha > 0<br>
- <strong>Effects:</strong> Constructs a <code>gamma_distribution</code>
- object; <code>alpha</code> is the parameter for the distribution.
- <pre>
- RealType alpha() const
-</pre><strong>Returns:</strong> The "alpha" parameter of the distribution.
-
- <h2>V. Acknowledgements</h2>
-
- <ul>
- <li>Thanks to Walter Brown, Mark Fischler and Marc Paterno from Fermilab
- for input about the requirements of high-energy physics.</li>
-
- <li>Thanks to David Abrahams for additional comments on the design.</li>
-
- <li>Thanks to the Boost community for a platform for
- experimentation.</li>
- </ul>
-
- <h2>VI. References</h2>
-
- <ul>
- <li>William H. Press, Saul A. Teukolsky, William A. Vetterling, Brian P.
- Flannery, "Numerical Recipes in C: The art of scientific computing", 2nd
- ed., 1992, pp. 274-328</li>
-
- <li>Bruce Schneier, "Applied Cryptography", 2nd ed., 1996, ch. 16-17. [I
- haven't read this myself. Yet.]</li>
-
- <li>D. H. Lehmer, "Mathematical methods in large-scale computing units",
- Proc. 2nd Symposium on Large-Scale Digital Calculating Machines, Harvard
- University Press, 1951, pp. 141-146</li>
-
- <li>P.A. Lewis, A.S. Goodman, J.M. Miller, "A pseudo-random number
- generator for the System/360", IBM Systems Journal, Vol. 8, No. 2, 1969,
- pp. 136-146</li>
-
- <li>Stephen K. Park and Keith W. Miller, "Random Number Generators: Good
- ones are hard to find", Communications of the ACM, Vol. 31, No. 10,
- October 1988, pp. 1192-1201</li>
-
- <li>Makoto Matsumoto and Takuji Nishimura, "Mersenne Twister: A
- 623-dimensionally equidistributed uniform pseudo-random number
- generator", 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.>
-
- <li>Donald E. Knuth, "The Art of Computer Programming, Vol. 2", 3rd ed.,
- 1997, pp. 1-193.</li>
-
- <li>Carter Bays and S.D. Durham, "Improving a poor random number
- generator", ACM Transactions on Mathematical Software, Vol. 2, 1979, pp.
- 59-64.</li>
-
- <li>Martin Lüscher, "A portable high-quality random number generator
- for lattice field theory simulations.", Computer Physics Communications,
- Vol. 79, 1994, pp. 100-110.</li>
-
- <li>William J. Hurd, "Efficient Generation of Statistically Good
- Pseudonoise by Linearly Interconnected Shift Registers", Technical Report
- 32-1526, Volume XI, The Deep Space Network Progress Report for July and
- August 1972, NASA Jet Propulsion Laboratory, 1972 and IEEE Transactions
- on Computers Vol. 23, 1974.</li>
-
- <li>Pierre L'Ecuyer, "Efficient and Portable Combined Random Number
- Generators", Communications of the ACM, Vol. 31, pp. 742-749+774,
- 1988.</li>
-
- <li>Pierre L'Ecuyer, "Maximally equidistributed combined Tausworthe
- generators", Mathematics of Computation Vol. 65, pp. 203-213, 1996.</li>
-
- <li>Pierre L'Ecuyer, "Good parameters and implementations for combined
- multple recursive random number generators", Operations Research Vol. 47,
- pp. 159-164, 1999.</li>
-
- <li>S. Kirkpatrick and E. Stoll, "A very fast shift-register sequence
- random number generator", Journal of Computational Physics, Vol. 40, pp.
- 517-526, 1981.</li>
-
- <li>R. C. Tausworthe, "Random numbers generated by iinear recurrence
- modulo two", Mathematics of Computation, Vol. 19, pp. 201-209, 1965.</li>
-
- <li>George Marsaglia and Arif Zaman, "A New Class of Random Number
- Generators", Annals of Applied Probability, Vol. 1, No. 3, 1991.</li>
- </ul>
- <hr>
-
- <p><a href="http://validator.w3.org/check?uri=referer"><img border="0" src=
- "../../doc/images/valid-html401.png" alt="Valid HTML 4.01 Transitional"
- height="31" width="88"></a></p>
-
- <p>Revised
- <!--webbot bot="Timestamp" s-type="EDITED" s-format="%d %B, %Y" startspan -->05 December, 2006<!--webbot bot="Timestamp" endspan i-checksum="38516" --></p>
-
- <p><i>Copyright © 2002 <a href=
- "http://www.boost.org/people/jens_maurer.htm">Jens Maurer</a></i></p>
-
- <p><i>Distributed under the Boost Software License, Version 1.0. (See
- accompanying file LICENSE_1_0.txt or
- copy at <a href=
- "http://www.boost.org/LICENSE_1_0.txt">http://www.boost.org/LICENSE_1_0.txt>)</i></p>
-</body>
-</html>
Modified: branches/release/status/explicit-failures-markup.xml
==============================================================================
--- branches/release/status/explicit-failures-markup.xml (original)
+++ branches/release/status/explicit-failures-markup.xml 2010-03-21 20:45:06 EDT (Sun, 21 Mar 2010)
@@ -4294,6 +4294,27 @@
</note>
</mark-failure>
</test>
+ <mark-expected-failures>
+ <test name="test_ecuyer1988"/>
+ <test name="test_hellekalek1995"/>
+ <test name="test_rand48"/>
+ <test name="test_minstd_rand0"/>
+ <test name="test_minstd_rand"/>
+ <test name="test_kreutzer1986"/>
+ <test name="test_mt11213b"/>
+ <test name="test_mt19937"/>
+ <test name="test_lagged_fibonacci"/>
+ <test name="test_lagged_fibonacci607"/>
+ <test name="test_ranlux3"/>
+ <test name="test_ranlux4"/>
+ <test name="test_ranlux3_01"/>
+ <test name="test_ranlux4_01"/>
+ <test name="test_ranlux64_3_01"/>
+ <test name="test_ranlux64_4_01"/>
+ <test name="test_taus88"/>
+ <toolset name="gcc-mingw-4.3.3"/>
+ <note refid="5" author="Steven Watanabe"/>
+ </mark-expected-failures>
</library>
<!-- range -->
Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk