2
0
mirror of https://github.com/boostorg/random.git synced 2026-01-19 04:22:17 +00:00

This commit was manufactured by cvs2svn to create branch 'SPIRIT_1_6'.

[SVN r23968]
This commit is contained in:
nobody
2004-07-23 02:16:28 +00:00
parent 9febe9be3f
commit c2d8ffb6f6
20 changed files with 0 additions and 9396 deletions

View File

@@ -1,170 +0,0 @@
/* boost histogram.cpp graphical verification of distribution functions
*
* Copyright Jens Maurer 2000
* Permission to use, copy, modify, sell, and distribute this software
* is hereby granted without fee provided that the above copyright notice
* appears in all copies and that both that copyright notice and this
* permission notice appear in supporting documentation,
*
* Jens Maurer makes no representations about the suitability of this
* software for any purpose. It is provided "as is" without express or
* implied warranty.
*
* $Id$
*
* This test program allows to visibly examine the results of the
* distribution functions.
*/
#include <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>();
}

View File

@@ -1,161 +0,0 @@
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<title>Boost Random Number Library</title>
</head>
<body bgcolor="#FFFFFF" text="#000000">
<table border="1" bgcolor="#007F7F" cellpadding="2">
<tr>
<td bgcolor="#FFFFFF"><img src="../../c++boost.gif" alt="c++boost.gif (8819 bytes)" width="277" height="86"></td>
<td><a href="../../index.htm"><font face="Arial,Helvetica" color="#FFFFFF"><big>Home</big></font></a></td>
<td><a href="../libraries.htm"><font face="Arial,Helvetica" color="#FFFFFF"><big>Libraries</big></font></a></td>
<td><a href="../../people/people.htm"><font face="Arial,Helvetica" color="#FFFFFF"><big>People</big></font></a></td>
<td><a href="../../more/faq.htm"><font face="Arial,Helvetica" color="#FFFFFF"><big>FAQ</big></font></a></td>
<td><a href="../../more/index.htm"><font face="Arial,Helvetica" color="#FFFFFF"><big>More</big></font></a></td>
</tr>
</table>
<h1>Boost Random Number Library</h1>
Random numbers are useful in a variety of applications. The Boost
Random Number Library (Boost.Random for short) provides a vast variety
of generators and distributions to produce random numbers having
useful properties, such as uniform distribution.
<p>
You should read the
<a href="random-concepts.html">concepts documentation</a>
for an introduction and the definition of the basic concepts. For a
quick start, it may be sufficient to have a look at <a
href="random_demo.cpp">random_demo.cpp</a>.
<p>
For a very quick start, here's an example:
<pre>
boost::mt19937 rng; // produces randomness out of thin air
// see pseudo-random number generators
boost::uniform_int&lt;> six(1,6) // distribution that maps to 1..6
// see random number distributions
boost::variate_generator&lt;boost::mt19937, boost::uniform_int&lt;> >
die(rng, six); // glues randomness with mapping
int x = die(); // simulate rolling a die
</pre>
<h2>Library Organization</h2>
The library is separated into several header files, all within the
<code>boost/random/</code> directory. Additionally, a convenience
header file which includes all other headers in
<code>boost/random/</code> is available as
<code><a href="../../boost/random.hpp">boost/random.hpp</a></code>.
<p>
A front-end class template called <code>variate_generate</code> is
provided; please read the
<a href="random-variate.html">documentation</a> about it.
<ul>
<li><code><a href="../../boost/random/variate_generator.hpp">boost/random/variate_generator.hpp</a></code>
</ul>
Several random number generators are available in the following
header files; please read the
<a href="random-generators.html">documentation</a> about these.
<ul>
<li><code><a href="../../boost/random/linear_congruential.hpp">boost/random/linear_congruential.hpp</a></code>
<li><code><a href="../../boost/random/additive_combine.hpp">boost/random/additive_combine.hpp</a></code>
<li><code><a href="../../boost/random/inversive_congruential.hpp">boost/random/inversive_congruential.hpp</a></code>
<li><code><a href="../../boost/random/shuffle_output.hpp">boost/random/shuffle_output.hpp</a></code>
<li><code><a href="../../boost/random/mersenne_twister.hpp">boost/random/mersenne_twister.hpp</a></code>
<li><code><a href="../../boost/random/lagged_fibonacci.hpp">boost/random/lagged_fibonacci.hpp</a></code>
</ul>
Similarly, several random number distributions are available in the
following header files; please read the
<a href="random-distributions.html">documentation</a> about these.
<ul>
<li><code><a href="../../boost/random/uniform_smallint.hpp">boost/random/uniform_smallint.hpp</a></code>
<li><code><a href="../../boost/random/uniform_int.hpp">boost/random/uniform_int.hpp</a></code>
<li><code><a href="../../boost/random/uniform_01.hpp">boost/random/uniform_01.hpp</a></code>
<li><code><a href="../../boost/random/uniform_real.hpp">boost/random/uniform_real.hpp</a></code>
<li><code><a href="../../boost/random/triangle_distribution.hpp">boost/random/triangle_distribution.hpp</a></code>
<li><code><a href="../../boost/random/bernoulli_distribution.hpp">boost/random/bernoulli_distribution.hpp</a></code>
<li><code><a href="../../boost/random/cauchy_distribution.hpp">boost/random/cauchy_distribution.hpp</a></code>
<li><code><a href="../../boost/random/exponential_distribution.hpp">boost/random/exponential_distribution.hpp</a></code>
<li><code><a href="../../boost/random/geometric_distribution.hpp">boost/random/geometric_distribution.hpp</a></code>
<li><code><a href="../../boost/random/normal_distribution.hpp">boost/random/normal_distribution.hpp</a></code>
<li><code><a href="../../boost/random/lognormal_distribution.hpp">boost/random/lognormal_distribution.hpp</a></code>
<li><code><a href="../../boost/random/uniform_on_sphere.hpp">boost/random/uniform_on_sphere.hpp</a></code>
</ul>
Additionally, non-deterministic random number generators are available
in the header
<code><a href="../../boost/nondet_random.hpp">&lt;boost/nondet_random.hpp&gt;</a></code>.
<a href="nondet_random.html">Documentation</a> is also available.
<p>
In order to map the interface of the generators and distribution functions
to other concepts, some <a href="random-misc.html">decorators</a> are available.
<h2>Tests</h2>
An extensive test suite for the pseudo-random number generators and
distributions is available as
<a href="random_test.cpp">random_test.cpp</a>.
<p>
Some <a href="random-performance.html">performance results</a> obtained
using <a href="random_speed.cpp">random_speed.cpp</a> are also available.
<h2>Rationale</h2>
The methods for generating and evaluating deterministic and
non-deterministic random numbers differ radically. Furthermore, due
to the inherent deterministic design of present-day computers, it is
often difficult to implement non-deterministic random number
generation facilities. Thus, the random number library is split into
separate header files, mirroring the two different application
domains.
<h2>History and Acknowledgements</h2>
In November 1999, Jeet Sukumaran proposed a framework based on virtual
functions, and later sketched a template-based approach. Ed Brey
pointed out that Microsoft Visual C++ does not support in-class member
initializations and suggested the <code>enum</code> workaround. Dave
Abrahams highlighted quantization issues.
<p>
The first public release of this random number library materialized in
March 2000 after extensive discussions on the boost mailing list.
Many thanks to Beman Dawes for his original <code>min_rand</code>
class, portability fixes, documentation suggestions, and general
guidance. Harry Erwin sent a header file which provided additional
insight into the requirements. Ed Brey and Beman Dawes wanted an
iterator-like interface.
<p>
Beman Dawes managed the formal review, during which Matthias Troyer,
Csaba Szepesvari, and Thomas Holenstein gave detailed comments. The
reviewed version became an official part of boost on 17 June 2000.
<p>
Gary Powell contributed suggestions for code cleanliness. Dave
Abrahams and Howard Hinnant suggested to move the basic generator
templates from namespace <code>boost::detail</code> to
<code>boost::random</code>.
<p>
Ed Brey asked to remove superfluous warnings and helped with
<code>uint64_t</code> handling. Andreas Scherer tested with MSVC.
Matthias Troyer contributed a lagged Fibonacci generator. Michael
Stevens found a bug in the copy semantics of normal_distribution and
suggested documentation improvements.
<p>
<hr>
<a href="../../people/jens_maurer.htm">Jens Maurer</a>,
2001-08-31
</body>
</html>

View File

@@ -1,84 +0,0 @@
/* integrate.hpp header file
*
* Copyright Jens Maurer 2000
* Permission to use, copy, modify, sell, and distribute this software
* is hereby granted without fee provided that the above copyright notice
* appears in all copies and that both that copyright notice and this
* permission notice appear in supporting documentation,
*
* Jens Maurer makes no representations about the suitability of this
* software for any purpose. It is provided "as is" without express or
* implied warranty.
*
* $Id$
*
* Revision history
* 01 April 2001: Modified to use new <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 */

View File

@@ -1,131 +0,0 @@
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<title>Boost RNG Library - Non-Deterministic Random Number Generators</title>
</head>
<body bgcolor="#FFFFFF" text="#000000">
<h1><img src="../../c++boost.gif" alt="c++boost.gif (8819 bytes)"
align="center" width="277" height="86">Header
<a href="../../boost/nondet_random.hpp">&lt;boost/nondet_random.hpp&gt;</a></h1>
<ul>
<li><a href="#synopsis">Synopsis</a>
<li><a href="#random_device">Class <code>random_device</code></a>
<li><a href="#performance">Performance</a>
</ul>
<h2><a name="synopsis">Header</a><code>&lt;boost/nondet_random.hpp&gt;</code>
Synopsis</h2>
<pre>
namespace boost {
class random_device;
} // namespace boost
</pre>
<h2><a name="random_device">Class <code>random_device</code></a></h2>
<h3>Synopsis</h3>
<pre>
class random_device : noncopyable
{
public:
typedef unsigned int result_type;
static const bool has_fixed_range = true;
static const result_type min_value = /* implementation defined */;
static const result_type max_value = /* implementation defined */;
result_type min() const;
result_type max() const;
explicit random_device(const std::string& token = default_token);
~random_device();
double entropy() const;
unsigned int operator()();
};
</pre>
<h3>Description</h3>
Class <code>random_device</code> models a
<a href="random-concepts.html#nondet-rng">non-deterministic random number
generator</a>.
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 <code>random_device</code>
must not be implemented. See
<blockquote>
"Randomness Recommendations for Security", D. Eastlake, S.
Crocker, J. Schiller, Network Working Group, RFC 1750, December 1994
</blockquote>
for further discussions.
<p>
<em>Note:</em> 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.
<h3>Members</h3>
<pre>explicit random_device(const std::string& token = default_token)</pre>
<strong>Effects:</strong> Constructs a <code>random_device</code>,
optionally using the given <code>token</code> as an access
specification (for example, a URL) to some implementation-defined
service for monitoring a stochastic process.
<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.
<h3>Implementation Note for Linux</h3>
On the Linux operating system, <code>token</code> 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, <code>std::ios_base::failure</code> is
thrown. By default, <code>random_device</code> uses the
<code>/dev/urandom</code> pseudo-device to retrieve the random
numbers. Another option would be to specify the
<code>/dev/random</code> pseudo-device, which blocks on reads if the
entropy pool has no more random bits available.
<h2><a name="performance">Performance</a></h2>
The test program <a href="nondet_random_speed.cpp">nondet_random_speed.cpp</a>
measures the execution times of the
<a href="../../boost/nondet_random.hpp">nondet_random.hpp</a> 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.
<p>
<table border=1>
<tr><th>class</th><th>time per invocation [usec]</th></tr>
<tr><td>random_device</td><td>92.0</td></tr>
</table>
<p>
The measurement error is estimated at +/- 1 usec.
<p>
<hr>
Jens Maurer, 2000-06-19
</body>
</html>

View File

@@ -1,69 +0,0 @@
/* boost nondet_random_speed.cpp performance test
*
* Copyright Jens Maurer 2000
* Permission to use, copy, modify, sell, and distribute this software
* is hereby granted without fee provided that the above copyright notice
* appears in all copies and that both that copyright notice and this
* permission notice appear in supporting documentation,
*
* Jens Maurer makes no representations about the suitability of this
* software for any purpose. It is provided "as is" without express or
* implied warranty.
*
* $Id$
*
*/
#include <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;
}

View File

@@ -1,429 +0,0 @@
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<title>Boost Random Number Library Concepts</title>
</head>
<body bgcolor="#FFFFFF" text="#000000">
<h1>Random Number Generator Library Concepts</h1>
<h2>Introduction</h2>
Random numbers are required in a number of different problem domains,
such as
<ul>
<li>numerics (simulation, Monte-Carlo integration)
<li>games (non-deterministic enemy behavior)
<li>security (key generation)
<li>testing (random coverage in white-box tests)
</ul>
The Boost Random Number Generator Library provides a framework
for random number generators with well-defined properties so that the
generators can be used in the demanding numerics and security domains.
For a general introduction to random numbers in numerics, see
<blockquote>
"Numerical Recipes in C: The art of scientific computing", William
H. Press, Saul A. Teukolsky, William A. Vetterling, Brian P. Flannery,
2nd ed., 1992, pp. 274-328
</blockquote>
Depending on the requirements of the problem domain, different
variations of random number generators are appropriate:
<ul>
<li>non-deterministic random number generator
<li>pseudo-random number generator
<li>quasi-random number generator
</ul>
All variations have some properties in common, these concepts (in the
STL sense) are called NumberGenerator and
UniformRandomNumberGenerator. Each concept will be defined in a
subsequent section.
<p>
The goals for this library are the following:
<ul>
<li>allow easy integration of third-party random-number generators
<li>define a validation interface for the generators
<li>provide easy-to-use front-end classes which model popular
distributions
<li>provide maximum efficiency
<li>allow control on quantization effects in front-end processing
(not yet done)
</ul>
<h2><a name="number_generator">Number Generator</a></h2>
A number generator is a <em>function object</em> (std:20.3
[lib.function.objects]) that takes zero arguments. Each call to
<code>operator()</code> returns a number.
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 value of <code>X</code>.
<p>
<table border=1>
<tr><th colspan=3 align=center><code>NumberGenerator</code>
requirements</th></tr>
<tr><td>expression</td><td>return&nbsp;type</td>
<td>pre/post-condition</td></tr>
<tr><td><code>X::result_type</code></td><td>T</td>
<td><code>std::numeric_limits&lt;T&gt;::is_specialized</code> is true,
<code>T</code> is <code>LessThanComparable</code></td></tr>
<tr><td><code>u.operator()()</code></td><td>T</td><td>-</td></tr>
</table>
<p>
<em>Note:</em> The NumberGenerator requirements do not impose any
restrictions on the characteristics of the returned numbers.
<h2><a name="uniform-rng">Uniform Random Number Generator</a></h2>
A uniform random number generator is a NumberGenerator that provides a
sequence of random numbers uniformly distributed on a given range.
The range can be compile-time fixed or available (only) after run-time
construction of the object.
<p>
The <em>tight lower bound</em> of some (finite) set S is the (unique)
member l in S, so that for all v in S, l <= v holds. Likewise, the
<em>tight upper bound</em> of some (finite) set S is the (unique)
member u in S, so that for all v in S, v <= u holds.
<p>
In the following table, <code>X</code> denotes a number generator
class returning objects of type <code>T</code>, and <code>v</code> is
a const value of <code>X</code>.
<p>
<table border=1>
<tr><th colspan=3 align=center><code>UniformRandomNumberGenerator</code>
requirements</th></tr>
<tr><td>expression</td><td>return&nbsp;type</td>
<td>pre/post-condition</td></tr>
<tr><td><code>X::has_fixed_range</code></td><td><code>bool</code></td>
<td>compile-time constant; if <code>true</code>, the range on which
the random numbers are uniformly distributed is known at compile-time
and members <code>min_value</code> and <code>max_value</code>
exist. <em>Note:</em> This flag may also be <code>false</code> due to
compiler limitations.</td></tr>
<tr><td><code>X::min_value</code></td><td><code>T</code></td>
<td>compile-time constant; <code>min_value</code> is equal to
<code>v.min()</code></td></tr>
<tr><td><code>X::max_value</code></td><td><code>T</code></td>
<td>compile-time constant; <code>max_value</code> is equal to
<code>v.max()</code></td></tr>
<tr><td><code>v.min()</code></td><td><code>T</code></td>
<td>tight lower bound on the set of all values returned by
<code>operator()</code>. The return value of this function shall not
change during the lifetime of the object.</td></tr>
<tr><td><code>v.max()</code></td><td><code>T</code></td>
<td>if <code>std::numeric_limits&lt;T&gt;::is_integer</code>, tight
upper bound on the set of all values returned by
<code>operator()</code>, otherwise, the smallest representable number
larger than the tight upper bound on the set of all values returned by
<code>operator()</code>. In any case, the return value of this
function shall not change during the lifetime of the
object.</code></td></tr>
</table>
<p>
The member functions <code>min</code>, <code>max</code>, and
<code>operator()</code> shall have amortized constant time complexity.
<p>
<em>Note:</em> For integer generators (i.e. integer <code>T</code>),
the generated values <code>x</code> fulfill <code>min() <= x <=
max()</code>, for non-integer generators (i.e. non-integer
<code>T</code>), the generated values <code>x</code> fulfill
<code>min() <= x < max()</code>.
<br>
<em>Rationale:</em> The range description with <code>min</code> and
<code>max</code> serves two purposes. First, it allows scaling of the
values to some canonical range, such as [0..1). Second, it describes
the significant bits of the values, which may be relevant for further
processing.
<br>
The range is a closed interval [min,max] for integers, because the
underlying type may not be able to represent the half-open interval
[min,max+1). It is a half-open interval [min, max) for non-integers,
because this is much more practical for borderline cases of continuous
distributions.
<p>
<em>Note:</em> The UniformRandomNumberGenerator concept does not
require <code>operator()(long)</code> and thus it does not fulfill the
RandomNumberGenerator (std:25.2.11 [lib.alg.random.shuffle])
requirements. Use the
<a href="random-misc.html#random_number_generator"><code>random_number_generator</code></a>
adapter for that.
<br>
<em>Rationale:</em> <code>operator()(long)</code> is not provided,
because mapping the output of some generator with integer range to a
different integer range is not trivial.
<h2><a name="nondet-rng">Non-deterministic Uniform Random Number
Generator</a></h2>
A non-deterministic uniform random number generator is a
UniformRandomNumberGenerator that is based on some stochastic process.
Thus, it provides a sequence of truly-random numbers. Examples for
such processes are nuclear decay, noise of a Zehner diode, tunneling
of quantum particles, rolling a die, drawing from an urn, and tossing
a coin. Depending on the environment, inter-arrival times of network
packets or keyboard events may be close approximations of stochastic
processes.
<p>
The class
<code><a href="nondet_random.html#random_device">random_device</a></code>
is a model for a non-deterministic random number generator.
<p>
<em>Note:</em> This type of random-number generator is useful for
security applications, where it is important to prevent that an
outside attacker guesses the numbers and thus obtains your
encryption or authentication key. Thus, models of this concept should
be cautious not to leak any information, to the extent possible by the
environment. For example, it might be advisable to explicitly clear
any temporary storage as soon as it is no longer needed.
<h2><a name="pseudo-rng">Pseudo-Random Number Generator</a></h2>
A pseudo-random number generator is a UniformRandomNumberGenerator
which provides a deterministic sequence of pseudo-random numbers,
based on some algorithm and internal state. Linear congruential and
inversive congruential generators are examples of such pseudo-random
number generators. Often, these generators are very sensitive to
their parameters. In order to prevent wrong implementations from
being used, an external testsuite should check that the generated
sequence and the validation value provided do indeed match.
<p>
Donald E. Knuth gives an extensive overview on pseudo-random number
generation in his book "The Art of Computer Programming, Vol. 2, 3rd
edition, Addison-Wesley, 1997". The descriptions for the specific
generators contain additional references.
<p>
<em>Note:</em> Because the state of a pseudo-random number generator
is necessarily finite, the sequence of numbers returned by the
generator will loop eventually.
<p>
In addition to the UniformRandomNumberGenerator requirements, a
pseudo-random number generator has some additional requirements. In
the following table, <code>X</code> denotes a pseudo-random number
generator class returning objects of type <code>T</code>,
<code>x</code> is a value of <code>T</code>, <code>u</code> is a value
of <code>X</code>, and <code>v</code> is a <code>const</code> value of
<code>X</code>.
<p>
<table border=1>
<tr><th colspan=3 align=center><code>PseudoRandomNumberGenerator</code>
requirements</th></tr>
<tr><td>expression</td><td>return&nbsp;type</td>
<td>pre/post-condition</td></tr>
<tr><td><code>X()</code></td><td>-</td>
<td>creates a generator in some implementation-defined
state. <em>Note:</em> Several generators thusly created may possibly
produce dependent or identical sequences of random numbers.</td></tr>
<tr><td><code>explicit X(...)</code></td><td>-</td>
<td>creates a generator with user-provided state; the implementation
shall specify the constructor argument(s)</td></tr>
<tr><td><code>u.seed(...)</code></td><td>void</td>
<td>sets the current state according to the argument(s); at least
functions with the same signature as the non-default
constructor(s) shall be provided.
<tr><td><code>X::validation(x)</code></td><td><code>bool</code></td>
<td>compares the pre-computed and hardcoded 10001th element in the
generator's random number sequence with <code>x</code>. The generator
must have been constructed by its default constructor and
<code>seed</code> must not have been called for the validation to
be meaningful.
</table>
<p>
<em>Note:</em> The <code>seed</code> member function is similar to the
<code>assign</code> member function in STL containers. However, the
naming did not seem appropriate.
<p>
Classes which model a pseudo-random number generator shall also model
EqualityComparable, i.e. implement <code>operator==</code>. Two
pseudo-random number generators are defined to be <em>equivalent</em>
if they both return an identical sequence of numbers starting from a
given state.
<p>
Classes which model a pseudo-random number generator should also model
the Streamable concept, i.e. implement <code>operator&lt;&lt;</code>
and <code>operator&gt;&gt;</code>. If so,
<code>operator&lt;&lt;</code> writes all current state of the
pseudo-random number generator to the given <code>ostream</code> so
that <code>operator&gt;&gt;</code> can restore the state at a later
time. The state shall be written in a platform-independent manner,
but it is assumed that the <code>locale</code>s used for writing and
reading be the same.
The pseudo-random number generator with the restored state and the
original at the just-written state shall be equivalent.
<p>
Classes which model a pseudo-random number generator may also model
the CopyConstructible and Assignable concepts. However, note that the
sequences of the original and the copy are strongly correlated (in
fact, they are identical), which may make them unsuitable for some
problem domains. Thus, copying pseudo-random number generators is
discouraged; they should always be passed by (non-<code>const</code>)
reference.
<p>
The classes
<code><a href="random-generators.html#rand48">rand48</a></code>,
<code><a href="random-generators.html#linear_congruential">minstd_rand</a></code>,
and
<code><a href="random-generators.html#mersenne_twister">mt19937</a></code>
are models for a pseudo-random number generator.
<p>
<em>Note:</em> This type of random-number generator is useful for
numerics, games and testing. The non-zero arguments constructor(s)
and the <code>seed()</code> member function(s) allow for a
user-provided state to be installed in the generator. This is useful
for debugging Monte-Carlo algorithms and analyzing particular test
scenarios. The Streamable concept allows to save/restore the state of
the generator, for example to re-run a test suite at a later time.
<h2><a name="random-dist">Random Distribution</a></h2>
A radom distribution produces random numbers distributed according to
some distribution, given uniformly distributed random values as input.
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>
<tr>
<th colspan=4 align=center>Random distribution requirements
(in addition to number generator,
<code>CopyConstructible</code>, and <code>Assignable</code>)</th>
<tr><td>expression</td><td>return&nbsp;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 &lt;&lt; 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 &gt;&gt; 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&lt;&lt;</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 &lt;&lt; x</code> is invoked between any of the
invocations <code>x(e)</code>. If a textual representation
is written using <code>os &lt;&lt; x</code> and that representation
is restored into the same or a different object <code>y</code> of the
same type using <code>is &gt;&gt; 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>
<h2><a name="quasi-rng">Quasi-Random Number Generators</a></h2>
A quasi-random number generator is a Number Generator which provides a
deterministic sequence of numbers, based on some algorithm and
internal state. The numbers do not have any statistical properties
(such as uniform distribution or independence of successive values).
<p>
<em>Note:</em> Quasi-random number generators are useful for
Monte-Carlo integrations where specially crafted sequences of random
numbers will make the approximation converge faster.
<p>
<em>[Does anyone have a model?]</em>
<p>
<hr>
Jens Maurer, 2000-02-23
</body>
</html>

View File

@@ -1,796 +0,0 @@
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<title>Boost Random Number Library Distributions</title>
</head>
<body bgcolor="#FFFFFF" text="#000000">
<h1>Random Number Library Distributions</h1>
<ul>
<li><a href="#intro">Introduction</a>
<li><a href="#synopsis">Synopsis</a>
<li><a href="#uniform_smallint">Class template
<code>uniform_smallint</code></a>
<li><a href="#uniform_int">Class template <code>uniform_int</code></a>
<li><a href="#uniform_01">Class template <code>uniform_01</code></a>
<li><a href="#uniform_real">Class template
<code>uniform_real</code></a>
<li><a href="#bernoulli_distribution">Class template
<code>bernoulli_distribution</code></a>
<li><a href="#geometric_distribution">Class template
<code>geometric_distribution</code></a>
<li><a href="#triangle_distribution">Class template
<code>triangle_distribution</code></a>
<li><a href="#exponential_distribution">Class template
<code>exponential_distribution</code></a>
<li><a href="#normal_distribution">Class template
<code>normal_distribution</code></a>
<li><a href="#lognormal_distribution">Class template
<code>lognormal_distribution</code></a>
<li><a href="#uniform_on_sphere">Class template
<code>uniform_on_sphere</code></a>
</ul>
<h2><a name="intro">Introduction</a></h2>
In addition to the <a href="random-generators.html">random number
generators</a>, this library provides distribution functions which map
one distribution (often a uniform distribution provided by some
generator) to another.
<p>
Usually, there are several possible implementations of any given
mapping. Often, there is a choice between using more space, more
invocations of the underlying source of random numbers, or more
time-consuming arithmetic such as trigonometric functions. This
interface description does not mandate any specific implementation.
However, implementations which cannot reach certain values of the
specified distribution or otherwise do not converge statistically to
it are not acceptable.
<p>
<table border="1">
<tr><th>distribution</th><th>explanation</th><th>example</th></tr>
<tr>
<td><code><a href="#uniform_smallint">uniform_smallint</a></code></td>
<td>discrete uniform distribution on a small set of integers (much
smaller than the range of the underlying generator)</td>
<td>drawing from an urn</td>
</tr>
<tr>
<td><code><a href="#uniform_int">uniform_int</a></code></td>
<td>discrete uniform distribution on a set of integers; the underlying
generator may be called several times to gather enough randomness for
the output</td>
<td>drawing from an urn</td>
</tr>
<tr>
<td><code><a href="#uniform_01">uniform_01</a></code></td>
<td>continuous uniform distribution on the range [0,1); important
basis for other distributions</td>
<td>-</td>
</tr>
<tr>
<td><code><a href="#uniform_real">uniform_real</a></code></td>
<td>continuous uniform distribution on some range [min, max) of real
numbers</td>
<td>for the range [0, 2pi): randomly dropping a stick and measuring
its angle in radiants (assuming the angle is uniformly
distributed)</td>
</tr>
<tr>
<td><code><a href="#bernoulli_distribution">bernoulli_distribution</a></code></td>
<td>Bernoulli experiment: discrete boolean valued distribution with
configurable probability</td>
<td>tossing a coin (p=0.5)</td>
</tr>
<tr>
<td><code><a href="#geometric_distribution">geometric_distribution</a></code></td>
<td>measures distance between outcomes of repeated Bernoulli experiments</td>
<td>throwing a die several times and counting the number of tries
until a "6" appears for the first time</td>
</tr>
<tr>
<td><code><a href="#triangle_distribution">triangle_distribution</a></code></td>
<td>?</td>
<td>?</td>
</tr>
<tr>
<td><code><a href="#exponential_distribution">exponential_distribution</a></code></td>
<td>exponential distribution</td>
<td>measuring the inter-arrival time of alpha particles emitted by
radioactive matter</td>
</tr>
<tr>
<td><code><a href="#normal_distribution">normal_distribution</a></code></td>
<td>counts outcomes of (infinitely) repeated Bernoulli experiments</td>
<td>tossing a coin 10000 times and counting how many front sides are shown</td>
</tr>
<tr>
<td><code><a href="#lognormal_distribution">lognormal_distribution</a></code></td>
<td>lognormal distribution (sometimes used in simulations)</td>
<td>measuring the job completion time of an assembly line worker</td>
</tr>
<tr>
<td><code><a href="#uniform_on_sphere">uniform_on_sphere</a></code></td>
<td>uniform distribution on a unit sphere of arbitrary dimension</td>
<td>choosing a random point on Earth (assumed to be a sphere) where to
spend the next vacations</td>
</tr>
</table>
<p>
The template parameters of the distribution functions are always in
the order
<ul>
<li>Underlying source of random numbers
<li>If applicable, return type, with a default to a reasonable type.
</ul>
<p>
<em>The distribution functions no longer satisfy the input iterator
requirements (std:24.1.1 [lib.input.iterators]), because this is
redundant given the Generator interface and imposes a run-time
overhead on all users. Moreover, a Generator interface appeals to
random number generation as being more "natural". Use an
<a href="../utility/iterator_adaptors.htm">iterator adaptor</a>
if you need to wrap any of the generators in an input iterator
interface.</em>
<p>
All of the distribution functions described below store a non-const
reference to the underlying source of random numbers. Therefore, the
distribution functions are not Assignable. However, they are
CopyConstructible. Copying a distribution function will copy the
parameter values. Furthermore, both the copy and the original will
refer to the same underlying source of random numbers. Therefore,
both the copy and the original will obtain their underlying random
numbers from a single sequence.
<p>
In this description, I have refrained from documenting those members
in detail which are already defined in the
<a href="random-concepts.html">concept documentation</a>.
<h2><a name="synopsis">Synopsis of the distributions</a> available from header
<code>&lt;boost/random.hpp&gt;</code> </h2>
<pre>
namespace boost {
template&lt;class IntType = int&gt;
class uniform_smallint;
template&lt;class IntType = int&gt;
class uniform_int;
template&lt;class RealType = double&gt;
class uniform_01;
template&lt;class RealType = double&gt;
class uniform_real;
// discrete distributions
template&lt;class RealType = double&gt;
class bernoulli_distribution;
template&lt;class IntType = int&gt;
class geometric_distribution;
// continuous distributions
template&lt;class RealType = double&gt;
class triangle_distribution;
template&lt;class RealType = double&gt;
class exponential_distribution;
template&lt;class RealType = double&gt;
class normal_distribution;
template&lt;class RealType = double&gt;
class lognormal_distribution;
template&lt;class RealType = double,
class Cont = std::vector&lt;RealType&gt; &gt;
class uniform_on_sphere;
}
</pre>
<h2><a name="uniform_smallint">Class template
<code>uniform_smallint</code></a></h2>
<h3>Synopsis</h3>
<pre>
#include &lt;<a href="../../boost/random/uniform_smallint.hpp">boost/random/uniform_smallint.hpp</a>&gt;
template&lt;class IntType = int&gt;
class uniform_smallint
{
public:
typedef IntType input_type;
typedef IntType result_type;
static const bool has_fixed_range = false;
uniform_smallint(IntType min, IntType max);
result_type min() const;
result_type max() const;
void reset();
template&lt;class UniformRandomNumberGenerator&gt;
result_type operator()(UniformRandomNumberGenerator& urng);
};
</pre>
<h3>Description</h3>
The distribution function <code>uniform_smallint</code> models a
<a href="random-concepts.html#random-dist">random distribution</a>.
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.
<p>
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
<code>uniform_smallint</code>. 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>).
<p>
The template parameter <code>IntType</code> shall denote an
integer-like value type.
<p>
<em>Note:</em> 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 &lt; 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 &lt; 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.
<p>
<em>Note:</em> 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> &gt; 10*r<sub>out</sub><sup>2</sup> or
ensure that r<sub>base</sub> is divisible by r<sub>out</sub>.
<h3>Members</h3>
<pre>uniform_smallint(IntType min, IntType max)</pre>
<strong>Effects:</strong> Constructs a <code>uniform_smallint</code>
functor. <code>min</code> and <code>max</code> are the lower and upper
bounds of the output range, respectively.
<h2><a name="uniform_int">Class template <code>uniform_int</code></a></h2>
<h3>Synopsis</h3>
<pre>
#include &lt;<a href="../../boost/random/uniform_int.hpp">boost/random/uniform_int.hpp</a>&gt;
template&lt;class IntType = int&gt;
class uniform_int
{
public:
typedef IntType input_type;
typedef IntType result_type;
static const bool has_fixed_range = false;
explicit uniform_int(IntType min = 0, IntType max = 9);
result_type min() const;
result_type max() const;
void reset();
template&lt;class UniformRandomNumberGenerator&gt;
result_type operator()(UniformRandomNumberGenerator& urng);
template&lt;class UniformRandomNumberGenerator&gt;
result_type operator()(UniformRandomNumberGenerator& urng, result_type n);
};
</pre>
<h3>Description</h3>
The distribution function <code>uniform_int</code> models a
<a href="random-concepts.html#random-dist">random distribution</a>.
On each invocation, it returns a random integer
value uniformly distributed in the set of integer numbers
{min, min+1, min+2, ..., max}.
<p>
The template parameter <code>IntType</code> shall denote an
integer-like value type.
<h3>Members</h3>
<pre> uniform_int(IntType min = 0, IntType max = 9)</pre>
<strong>Requires:</strong> min &lt;= 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
&lt;= x &lt; 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>
<h2><a name="uniform_01">Class template <code>uniform_01</code></a></h2>
<h3>Synopsis</h3>
<pre>
#include &lt;<a href="../../boost/random/uniform_01.hpp">boost/random/uniform_01.hpp</a>&gt;
template&lt;class UniformRandomNumberGenerator, class RealType = double&gt;
class uniform_01
{
public:
typedef UniformRandomNumberGenerator base_type;
typedef RealType result_type;
static const bool has_fixed_range = false;
explicit uniform_01(base_type & rng);
result_type operator()();
result_type min() const;
result_type max() const;
};
</pre>
<h3>Description</h3>
The distribution function <code>uniform_01</code> models a
<a href="random-concepts.html#random-dist">random distribution</a>.
On each invocation, it returns a random floating-point value uniformly
distributed in the range [0..1).
The value is computed using
<code>std::numeric_limits&lt;RealType&gt;::digits</code> random binary
digits, i.e. the mantissa of the floating-point value is completely
filled with random bits. [<em>Note:</em> Should this be configurable?]
<p>
The template parameter <code>RealType</code> shall denote a float-like
value type with support for binary operators +, -, and /. It must be
large enough to hold floating-point numbers of value
<code>rng.max()-rng.min()+1</code>.
<p>
<code>base_type::result_type</code> must be a number-like value type,
it must support <code>static_cast&lt;&gt;</code> to
<code>RealType</code> and binary operator -.
<p>
<em>Note:</em> 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) <code>boost::bigfloat</code> class with random bits
efficiently. It's probably time for a traits class.
<h3>Members</h3>
<pre>explicit uniform_01(base_type & rng)</pre>
<strong>Effects:</strong> Constructs a <code>uniform_01</code> functor
with the given uniform random number generator as the underlying
source of random numbers.
<h2><a name="uniform_real">Class template <code>uniform_real</code></a></h2>
<h3>Synopsis</h3>
<pre>
#include &lt;<a href="../../boost/random/uniform_real.hpp">boost/random/uniform_real.hpp</a>&gt;
template&lt;class RealType = double&gt;
class uniform_real
{
public:
typedef RealType input_type;
typedef RealType result_type;
static const bool has_fixed_range = false;
uniform_real(RealType min = RealType(0), RealType max = RealType(1));
result_type min() const;
result_type max() const;
void reset();
template&lt;class UniformRandomNumberGenerator&gt;
result_type operator()(UniformRandomNumberGenerator& urng);
};
</pre>
<h3>Description</h3>
The distribution function <code>uniform_real</code> models a
<a href="random-concepts.html#random-dist">random distribution</a>.
On each invocation, it returns a random floating-point
value uniformly distributed in the range [min..max). The value is
computed using
<code>std::numeric_limits&lt;RealType&gt;::digits</code> random binary
digits, i.e. the mantissa of the floating-point value is completely
filled with random bits.
<p>
<em>Note:</em> The current implementation is buggy, because it may not
fill all of the mantissa with random bits.
<h3>Members</h3>
<pre> uniform_real(RealType min = RealType(0), RealType max = RealType(1))</pre>
<strong>Requires:</strong> min &lt;= 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.
<h2><a name="bernoulli_distribution">Class template
<code>bernoulli_distribution</code></a></h2>
<h3>Synopsis</h3>
<pre>
#include &lt;<a href="../../boost/random/bernoulli_distribution.hpp">boost/random/bernoulli_distribution.hpp</a>&gt;
template&lt;class RealType = double>
class bernoulli_distribution
{
public:
typedef int input_type;
typedef bool result_type;
explicit bernoulli_distribution(const RealType& p = RealType(0.5));
RealType p() const;
void reset();
template&lt;class UniformRandomNumberGenerator&gt;
result_type operator()(UniformRandomNumberGenerator& urng);
};
</pre>
<h3>Description</h3>
Instantiations of class template <code>bernoulli_distribution</code>
model a <a href="random-concepts.html#random-dist">random
distribution</a>. Such a 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.
<h3>Members</h3>
<pre> bernoulli_distribution(const RealType& p = RealType(0.5))</pre>
<strong>Requires:</strong> 0 &lt;= p &lt;= 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.
<h2><a name="geometric_distribution">Class template
<code>geometric_distribution</code></a></h2>
<h3>Synopsis</h3>
<pre>
#include &lt;<a href="../../boost/random/geometric_distribution.hpp">boost/random/geometric_distribution.hpp</a>&gt;
template&lt;class UniformRandomNumberGenerator, class IntType = int&gt;
class geometric_distribution
{
public:
typedef RealType input_type;
typedef IntType result_type;
explicit geometric_distribution(const RealType& p = RealType(0.5));
RealType p() const;
void reset();
template&lt;class UniformRandomNumberGenerator&gt;
result_type operator()(UniformRandomNumberGenerator& urng);
};
</pre>
<h3>Description</h3>
Instantiations of class template <code>geometric_distribution</code>
model a
<a href="random-concepts.html#random-dist">random distribution</a>.
A <code>geometric_distribution</code> random distribution produces
integer values <em>i</em> &gt;= 1 with p(i) = (1-p) * p<sup>i-1</sup>.
p is the parameter of the distribution.
<h3>Members</h3>
<pre> geometric_distribution(const RealType& p = RealType(0.5))</pre>
<strong>Requires:</strong> 0 &lt; p &lt; 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.
<h2><a name="triangle_distribution">Class template
<code>triangle_distribution</code></a></h2>
<h3>Synopsis</h3>
<pre>
#include &lt;<a href="../../boost/random/triangle_distribution.hpp">boost/random/triangle_distribution.hpp</a>&gt;
template&lt;class RealType = double&gt;
class triangle_distribution
{
public:
typedef RealType input_type;
typedef RealType result_type;
triangle_distribution(result_type a, result_type b, result_type c);
result_type a() const;
result_type b() const;
result_type c() const;
void reset();
template&lt;class UniformRandomNumberGenerator&gt;
result_type operator()(UniformRandomNumberGenerator& urng);
};
</pre>
<h3>Description</h3>
Instantiations of class template <code>triangle_distribution</code>
model a <a href="random-concepts.html#random-dist">random
distribution</a>. The returned floating-point values <code>x</code>
satisfy <code>a <= x <= c</code>; <code>x</code> has a triangle
distribution, where <code>b</code> is the most probable value for
<code>x</code>.
<h3>Members</h3>
<pre>triangle_distribution(result_type a, result_type b, result_type c)</pre>
<strong>Effects:</strong> Constructs a
<code>triangle_distribution</code> functor. <code>a, b, c</code> are
the parameters for the distribution.
<p>
<h2><a name="exponential_distribution">Class template
<code>exponential_distribution</code></a></h2>
<h3>Synopsis</h3>
<pre>
#include &lt;<a href="../../boost/random/exponential_distribution.hpp">boost/random/exponential_distribution.hpp</a>&gt;
template&lt;class RealType = double&gt;
class exponential_distribution
{
public:
typedef RealType input_type;
typedef RealType result_type;
explicit exponential_distribution(const result_type& lambda);
RealType lambda() const;
void reset();
template&lt;class UniformRandomNumberGenerator&gt;
result_type operator()(UniformRandomNumberGenerator& urng);
};
</pre>
<h3>Description</h3>
Instantiations of class template <code>exponential_distribution</code>
model a <a href="random-concepts.html#random-dist">random
distribution</a>. Such a distribution produces random numbers x &gt;
0 distributed with probability density function p(x) = lambda *
exp(-lambda * x), where lambda is the parameter of the distribution.
<h3>Members</h3>
<pre> exponential_distribution(const result_type& lambda = result_type(1))</pre>
<strong>Requires:</strong> lambda &gt; 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.
<h2><a name="normal_distribution">Class template
<code>normal_distribution</code></a></h2>
<h3>Synopsis</h3>
<pre>
#include &lt;<a href="../../boost/random/normal_distribution.hpp">boost/random/normal_distribution.hpp</a>&gt;
template&lt;class RealType = double&gt;
class normal_distribution
{
public:
typedef RealType input_type;
typedef RealType result_type;
explicit normal_distribution(const result_type& mean = 0,
const result_type& sigma = 1);
RealType mean() const;
RealType sigma() const;
void reset();
template&lt;class UniformRandomNumberGenerator&gt;
result_type operator()(UniformRandomNumberGenerator& urng);
};
</pre>
<h3>Description</h3>
Instantiations of class template <code>normal_distribution</code>
model a <a href="random-concepts.html#random-dist">random
distribution</a>. Such a 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.
<h3>Members</h3>
<pre>
explicit normal_distribution(const result_type& mean = 0,
const result_type& sigma = 1);
</pre>
<strong>Requires:</strong> sigma &gt; 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.
<h2><a name="lognormal_distribution">Class template
<code>lognormal_distribution</code></a></h2>
<h3>Synopsis</h3>
<pre>
#include &lt;<a href="../../boost/random/lognormal_distribution.hpp">boost/random/lognormal_distribution.hpp</a>&gt;
template&lt;class RealType = double&gt;
class lognormal_distribution
{
public:
typedef typename normal_distribution&lt;RealType&gt;::input_type
typedef RealType result_type;
explicit lognormal_distribution(const result_type& mean = 1.0,
const result_type& sigma = 1.0);
RealType& mean() const;
RealType& sigma() const;
void reset();
template&lt;class UniformRandomNumberGenerator&gt;
result_type operator()(UniformRandomNumberGenerator& urng);
};
</pre>
<h3>Description</h3>
Instantiations of class template <code>lognormal_distribution</code>
model a <a href="random-concepts.html#random-dist">random
distribution</a>. Such a distribution produces random numbers
with p(x) = 1/(x * normal_sigma * sqrt(2*pi)) * exp(
-(log(x)-normal_mean)<sup>2</sup> / (2*normal_sigma<sup>2</sup>) )
for x > 0,
where normal_mean = log(mean<sup>2</sup>/sqrt(sigma<sup>2</sup>
+ mean<sup>2</sup>))
and normal_sigma = sqrt(log(1 + sigma<sup>2</sup>/mean<sup>2</sup>)).
<h3>Members</h3>
<pre>lognormal_distribution(const result_type& mean,
const result_type& sigma)</pre>
<strong>Effects:</strong> Constructs a
<code>lognormal_distribution</code> functor. <code>mean</code> and
<code>sigma</code> are the mean and standard deviation of the
lognormal distribution.
<p>
<h2><a name="uniform_on_sphere">Class template
<code>uniform_on_sphere</code></a></h2>
<h3>Synopsis</h3>
<pre>
#include &lt;<a href="../../boost/random/uniform_on_sphere.hpp">boost/random/uniform_on_sphere.hpp</a>&gt;
template&lt;class RealType = double,
class Cont = std::vector&lt;RealType&gt; &gt;
class uniform_on_sphere
{
public:
typedef RealType input_type;
typedef Cont result_type;
explicit uniform_on_sphere(int dim = 2);
void reset();
template&lt;class UniformRandomNumberGenerator&gt;
const result_type & operator()(UniformRandomNumberGenerator& urng);
};
</pre>
<h3>Description</h3>
Instantiations of class template <code>uniform_on_sphere</code> model a
<a href="random-concepts.html#random-dist">random distribution</a>.
Such a distribution produces random numbers uniformly distributed on
the unit sphere of arbitrary dimension <code>dim</code>. The
<code>Cont</code> template parameter must be a STL-like container type
with <code>begin</code> and <code>end</code> operations returning
non-const ForwardIterators of type <code>Cont::iterator</code>.
<h3>Members</h3>
<pre>explicit uniform_on_sphere(int dim = 2)</pre>
<strong>Effects:</strong> Constructs a <code>uniform_on_sphere</code>
functor. <code>dim</code> is the dimension of the sphere.
<p>
<p>
<hr>
Jens Maurer, 2003-10-25
</body>
</html>

File diff suppressed because it is too large Load Diff

View File

@@ -1,93 +0,0 @@
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<title>Boost Random Number Generator Library (Miscellaneous)</title>
</head>
<body bgcolor="#FFFFFF" text="#000000">
<h1>Random Number Generator Library --- Miscellaneous Decorators</h1>
<ul>
<li><a href="#random_number_generator">Class template
<code>random_number_generator</code></a>
<li><a href="#generator_iterator">Class template
<code>generator_iterator</code></a>
</ul>
<h2>Introduction</h2>
These decorator class templates allow adaptation of the random number
generators and distribution functions to concepts found in the C++
Standard Library, in particular the RandomNumberGenerator and the
InputIterator concepts. The latter adaptation is useful, because the
the basic random number generators do not implement the InputIterator
requirements per se, in contrast to the distribution functions.
<h2><a name="synopsis">Synopsis</a> of miscellaneous decorators in
header <code>&lt;boost/random.hpp&gt;</code></h2>
<pre>
namespace boost {
template&lt;class UniformRandomNumberGenerator, class IntType = long&gt;
class random_number_generator;
template&lt;class Generator&gt;
class generator_iterator;
} // namespace boost
</pre>
<h2><a name="random_number_generator">Class template
<code>random_number_generator</code></a></h2>
<h3>Synopsis</h3>
<pre>
template&lt;class UniformRandomNumberGenerator, class IntType = long&gt;
class random_number_generator
{
public:
typedef UniformRandomNumberGenerator base_type;
typedef IntType argument_type;
typedef IntType result_type;
random_number_generator(base_type & rng);
result_type operator()(argument_type n);
};
</pre>
<h3>Description</h3>
Instantiations of class template <code>random_number_generator</code>
model a RandomNumberGenerator (std:25.2.11 [lib.alg.random.shuffle]).
On each invocation, it returns a uniformly distributed integer in
the range [0..<code>n</code>).
<p>
The template parameter <code>IntType</code> shall denote some
integer-like value type.
<p>
<em>Note:</em> I consider it unfortunate that the C++ Standard uses
the name RandomNumberGenerator for something rather specific.
<h3>Members</h3>
<pre>random_number_generator(base_type & rng)</pre>
<strong>Effects:</strong> Constructs a
<code>random_number_generator</code> functor with the given uniform
random number generator as the underlying source of random numbers.
<pre>result_type operator()(argument_type n)</pre>
<strong>Returns:</strong> The value of
<code>uniform_int&lt;base_type&gt;(rng, 0, n-1)()</code>.
<p>
<hr>
Jens Maurer, 2001-11-19
</body>
</html>

View File

@@ -1,241 +0,0 @@
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<title>Boost Random Number Library Performance</title>
</head>
<body bgcolor="#FFFFFF" text="#000000">
<h1>Random Number Library Performance</h1>
For some people, performance of random number generation is an
important consideration when choosing a random number generator or a
particular distribution function. This page provides numerous
performance tests with the wide variety of generators and
distributions available in the boost library.
<p>
The performance has been evaluated on a Pentium Pro 200 MHz with gcc
2.95.2, Linux 2.2.13, glibc 2.1.2. The speed is reported in million
random numbers per second (M rn/sec), generated in a tight loop.
<p>
<h2>Basic Generators</h2>
<table border="1">
<tr>
<th>generator</th>
<th>M rn/sec</th>
<th>time per random number [usec]</th>
<th>relative speed compared to fastest [percent]</th>
</tr>
<tr>
<td>rand48</td>
<td>5.38</td>
<td>0.183</td>
<td>61%</td>
</tr>
<tr>
<td>rand48 run-time configurable</td>
<td>1.48</td>
<td>0.677</td>
<td>17%</td>
</tr>
<tr>
<td>lrand48 glibc 2.1.2</td>
<td>1.19</td>
<td>0.843</td>
<td>13%</td>
</tr>
<tr>
<td>minstd_rand</td>
<td>2.39</td>
<td>0.318</td>
<td>35%</td>
</tr>
<tr>
<td>ecuyer1988</td>
<td>1.12</td>
<td>0.892</td>
<td>13%</td>
</tr>
<tr>
<td>kreutzer1986</td>
<td>3.87</td>
<td>0.258</td>
<td>43%</td>
</tr>
<tr>
<td>hellekalek1995 (inversive)</td>
<td>0.20</td>
<td>5.12</td>
<td>2%</td>
</tr>
<tr>
<td>mt11213b</td>
<td>6.07</td>
<td>0.165</td>
<td>68%</td>
</tr>
<tr>
<td>mt19937</td>
<td>6.06</td>
<td>0.165</td>
<td>68%</td>
</tr>
<tr>
<td>mt19937 original</td>
<td>5.33</td>
<td>0.188</td>
<td>60%</td>
</tr>
<tr>
<td>lagged_fibonacci607</td>
<td>8.90</td>
<td>0.112</td>
<td>100%</td>
</tr>
<tr>
<td>lagged_fibonacci4423</td>
<td>8.54</td>
<td>0.117</td>
<td>96%</td>
</tr>
<tr>
<td>lagged_fibonacci19937</td>
<td>7.49</td>
<td>0.133</td>
<td>84%</td>
</tr>
<tr>
<td>lagged_fibonacci23209</td>
<td>6.63</td>
<td>0.151</td>
<td>74%</td>
</tr>
<tr>
<td>lagged_fibonacci44497</td>
<td>4.01</td>
<td>0.250</td>
<td>45%</td>
</tr>
</table>
<p>
Note that the lagged Fibonacci generators produce floating-point
numbers, whereas all others produce integers.
<h2>Distributions</h2>
<table border="1">
<tr>
<th>[M rn/sec]</th>
<th>minstd_rand</th>
<th>kreutzer1986</th>
<th>mt19937</th>
<th>lagged_fibonacci607</th>
</tr>
<tr>
<th>uniform_smallint</th>
<td>1.26</td>
<td>1.55</td>
<td>1.93</td>
<td>-</td>
</tr>
<tr>
<th>uniform_01</th>
<td>1.79</td>
<td>1.88</td>
<td>3.03</td>
<td>7.74</td>
</tr>
<tr>
<th>uniform_real</th>
<td>1.74</td>
<td>1.56</td>
<td>2.34</td>
<td>6.62</td>
</tr>
<tr>
<th>geometric</th>
<td>0.593</td>
<td>0.629</td>
<td>0.753</td>
<td>0.916</td>
</tr>
<tr>
<th>triangle</th>
<td>0.97</td>
<td>1.02</td>
<td>1.35</td>
<td>1.31</td>
</tr>
<tr>
<th>exponential</th>
<td>0.849</td>
<td>0.828</td>
<td>0.887</td>
<td>1.53</td>
</tr>
<tr>
<th>normal (polar method)</th>
<td>0.608</td>
<td>0.626</td>
<td>0.738</td>
<td>0.755</td>
</tr>
<tr>
<th>lognormal</th>
<td>0.417</td>
<td>0.442</td>
<td>0.470</td>
<td>0.481</td>
</tr>
<tr>
<th>uniform_on_sphere</th>
<td>0.154</td>
<td>0.155</td>
<td>0.174</td>
<td>0.218</td>
</tr>
</table>
<p>
Note that the lagged Fibonacci generator is at least 2.5 times faster
than the Mersenne twister when generating uniformly distributed
floating-point numbers. For more sophisticated distributions, the
speed improvement is less. Note however that these distributions have
not been optimized for speed, yet.
<p>
<hr>
Jens Maurer, 2001-04-15
</body>
</html>

View File

@@ -1,144 +0,0 @@
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
<title>Boost Random Number Library Variate Generator</title>
</head>
<body bgcolor="#FFFFFF" text="#000000">
<h1>Boost Random Number Library Variate Generator</h1>
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
<a href="random-generators.html">generators</a>
as well as
<a href="random-distributions.html">distributions</a>
.
<h2><a name="variate_generator">Class template <code>variate_generator</code></h2>
<h3>Synopsis</h3>
<pre>
#include &lt;<a href="../../boost/random/variate_generator.hpp">boost/random/variate_generator.hpp</a>&gt;
template&lt;class Engine, class Distribution&gt;
class variate_generator
{
public:
typedef Engine engine_type;
typedef Distribution distribution_type;
typedef typename Distribution::result_type result_type;
variate_generator(Engine e, Distribution d);
result_type operator()();
template&lt;class T&gt;
result_type operator()(T value);
engine_value_type&amp; engine();
const engine_value_type&amp; engine() const;
result_type min() const;
result_type max() const;
};
</pre>
<h3>Description</h3>
Instantations of class template <code>variate_generator</code> model a
<a href="random-concepts.html#number_generator">number generator</a>.
<p>
The argument for the template parameter <code>Engine</code> shall be
of the form U, U&, or U*, where U models a uniform random number
generator. Then, the member <code>engine_value_type</code> names U
(not the pointer or reference to U).
<p>
Specializations of <code>variate_generator</code> satisfy the
requirements of CopyConstructible. They also satisfy the requirements
of Assignable unless the template parameter Engine is of the form U&amp;.
<p>
The complexity of all functions specified in this section is
constant. No function described in this section except the constructor
throws an exception.
<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&lt;<em>T</em>&gt;::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&lt;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>
<p>
<hr>
<a href="../../people/jens_maurer.htm">Jens Maurer</a>,
2003-10-25
</body>
</html>

View File

@@ -1,133 +0,0 @@
/* boost random_demo.cpp profane demo
*
* Copyright Jens Maurer 2000
* Permission to use, copy, modify, sell, and distribute this software
* is hereby granted without fee provided that the above copyright notice
* appears in all copies and that both that copyright notice and this
* permission notice appear in supporting documentation,
*
* Jens Maurer makes no representations about the suitability of this
* software for any purpose. It is provided "as is" without express or
* implied warranty.
*
* $Id$
*
* A short demo program how to use the random number library.
*/
#include <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;
}

View File

@@ -1,122 +0,0 @@
/* boost random_device.cpp implementation
*
* Copyright Jens Maurer 2000
* Permission to use, copy, modify, sell, and distribute this software
* is hereby granted without fee provided that the above copyright notice
* appears in all copies and that both that copyright notice and this
* permission notice appear in supporting documentation,
*
* Jens Maurer makes no representations about the suitability of this
* software for any purpose. It is provided "as is" without express or
* implied warranty.
*
* $Id$
*
*/
#include <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
#ifdef __linux__
// the default is the unlimited capacity device, using some secure hash
// try "/dev/random" for blocking when the entropy pool has drained
const char * const boost::random_device::default_token = "/dev/urandom";
/*
* This uses the POSIX interface for unbuffered reading.
* Using buffered std::istream would consume entropy which may
* not actually be used. Entropy is a precious good we avoid
* wasting.
*/
#if defined(__GNUC__) && defined(_CXXRT_STD_NAME)
// I have severe difficulty to get the POSIX includes to work with
// -fhonor-std and Dietmar Kühl's standard C++ library. Hack around that
// problem for now.
extern "C" {
static const int O_RDONLY = 0;
extern int open(const char *__file, int __oflag, ...);
extern int read(int __fd, __ptr_t __buf, size_t __nbytes);
extern int close(int __fd);
}
#else
#include <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__
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();
}

View File

@@ -1,371 +0,0 @@
/* boost random_speed.cpp performance measurements
*
* Copyright Jens Maurer 2000
* Permission to use, copy, modify, sell, and distribute this software
* is hereby granted without fee provided that the above copyright notice
* appears in all copies and that both that copyright notice and this
* permission notice appear in supporting documentation,
*
* Jens Maurer makes no representations about the suitability of this
* software for any purpose. It is provided "as is" without express or
* implied warranty.
*
* $Id$
*/
#include <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());
}

View File

@@ -1,539 +0,0 @@
/* boost random_test.cpp various tests
*
* Copyright Jens Maurer 2000
* Permission to use, copy, modify, sell, and distribute this software
* is hereby granted without fee provided that the above copyright notice
* appears in all copies and that both that copyright notice and this
* permission notice appear in supporting documentation,
*
* Jens Maurer makes no representations about the suitability of this
* software for any purpose. It is provided "as is" without express or
* implied warranty.
*
* $Id$
*/
#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 == 0xa37d3c92; }
// validation by experiment from mt19937.c
bool check(unsigned long x, const boost::mt19937&) { return x == 3346425566U; }
// 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_TEST(result);
}
void validate_all()
{
using namespace boost;
#if !defined(BOOST_NO_INT64_T) && !defined(BOOST_NO_INTEGRAL_INT64_T)
validate("rand48", rand48());
#endif
validate("minstd_rand", minstd_rand());
validate("minstd_rand0", minstd_rand0());
validate("ecuyer combined", ecuyer1988());
validate("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());
}
/*
* Check function signatures
*/
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);
#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(&copy, dist);
#endif
for(int i = 0; i < 1000; ++i) {
(void) gen();
(void) genref();
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
(void) genptr();
#endif
}
typename Dist::result_type g = gen();
BOOST_CHECK(std::abs(g - genref()) < 1e-6);
#ifndef BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION
BOOST_CHECK(std::abs(g - genptr()) < 1e-6);
#endif
(void) gen.engine();
gen.distribution().reset();
Dist d = dist; // copy ctor
d = dist; // copy assignment
#if !defined(BOOST_NO_OPERATORS_IN_NAMESPACE) && !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
{
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_NO_OPERATORS_IN_NAMESPACE
}
template<class URNG, class RealType>
void instantiate_real_dist(URNG& urng, RealType /* ignored */)
{
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 ResultType>
void instantiate_urng(const std::string & s, const URNG &, const ResultType &)
{
std::cout << "Basic tests for " << s;
URNG urng;
urng.seed(); // 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_TEST(urng == urng2); // operator==
BOOST_TEST(!(urng != urng2)); // operator!=
urng();
urng2 = urng; // copy assignment
BOOST_TEST(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_TEST(it != v.begin());
std::cout << "; seeding uses " << (it - v.begin()) << " words" << std::endl;
bool have_exception = false;
try {
// now check that exceptions are thrown
it = v.end();
urng3.seed(it, it_end);
} catch(std::invalid_argument& x) {
have_exception = true;
}
BOOST_TEST(have_exception);
// check for min/max members
ResultType min = (urng3.min)();
(void) &min;
ResultType max = (urng3.max)();
(void) &max;
#if !defined(BOOST_NO_OPERATORS_IN_NAMESPACE) && !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS)
// 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_TEST(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_TEST(urng == urng2);
#endif // BOOST_MSVC
}
#endif // BOOST_NO_STD_WSTREAMBUF, BOOST_NO_STD_WSTRING
#endif // BOOST_NO_OPERATORS_IN_NAMESPACE etc.
// 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
}
void instantiate_all()
{
using namespace boost;
#if !defined(BOOST_NO_INT64_T) && !defined(BOOST_NO_INTEGRAL_INT64_T)
instantiate_urng("rand48", rand48(), 0);
rand48 rnd(boost::int32_t(5));
rand48 rnd2(boost::uint64_t(0x80000000) * 42);
rnd.seed(boost::int32_t(17));
rnd2.seed(boost::uint64_t(0x80000000) * 49);
#endif
instantiate_urng("minstd_rand0", minstd_rand0(), 0);
instantiate_urng("minstd_rand", minstd_rand(), 0);
minstd_rand mstd(42);
mstd.seed(17);
instantiate_urng("ecuyer1988", ecuyer1988(), 0);
instantiate_urng("kreutzer1986", kreutzer1986(), 0);
instantiate_urng("hellekalek1995", hellekalek1995(), 0);
instantiate_urng("mt11213b", mt11213b(), 0u);
instantiate_urng("mt19937", mt19937(), 0u);
mt19937 mt(boost::uint32_t(17)); // needs to be an exact type match for MSVC
int i = 42;
mt.seed(boost::uint32_t(i));
mt19937 mt2(mstd);
mt2.seed(mstd);
random_number_generator<mt19937> std_rng(mt2);
(void) std_rng(10);
instantiate_urng("lagged_fibonacci",
boost::random::lagged_fibonacci<boost::uint32_t, 24, 607, 273>(),
0u);
instantiate_urng("lagged_fibonacci607", lagged_fibonacci607(), 0.0);
instantiate_urng("ranlux3", ranlux3(), 0u);
instantiate_urng("ranlux4", ranlux4(), 0u);
instantiate_urng("ranlux3_01", ranlux3_01(), 0.0f);
instantiate_urng("ranlux4_01", ranlux4_01(), 0.0f);
instantiate_urng("ranlux64_3_01", ranlux64_3_01(), 0.0);
instantiate_urng("ranlux64_4_01", ranlux64_4_01(), 0.0);
instantiate_urng("taus88", taus88(), 0u);
}
/*
* 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 threshold = 2*avg/std::sqrt(static_cast<double>(iter));
for(int i = 0; i < range; i++) {
if(std::fabs(bucket[i] - avg) > threshold) {
// 95% confidence interval
std::cout << " ... has bucket[" << i << "] = " << bucket[i]
<< " (distance " << (bucket[i] - avg) << ")"
<< std::endl;
}
}
}
template<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_TEST((uint12.distribution().min)() == 1);
BOOST_TEST((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);
// 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);
}
#if defined(BOOST_MSVC) && _MSC_VER <= 1200
// 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:
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)(); }
result_type operator()() { return (max)()-1; }
};
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
int test_main(int, char*[])
{
#if !defined(__INTEL_COMPILER) || !defined(_MSC_VER) || __INTEL_COMPILER > 700
instantiate_all();
validate_all();
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();
return 0;
#else
std::cout << "Intel 7.00 on Win32 loops, so the test is disabled\n";
return 1;
#endif
}

View File

@@ -1,669 +0,0 @@
/* statistic_tests.cpp file
*
* Copyright Jens Maurer 2000, 2002
* Permission to use, copy, modify, sell, and distribute this software
* is hereby granted without fee provided that the above copyright notice
* appears in all copies and that both that copyright notice and this
* permission notice appear in supporting documentation,
*
* Jens Maurer makes no representations about the suitability of this
* software for any purpose. It is provided "as is" without express or
* implied warranty.
*
* $Id$
*
* Revision history
*/
/*
* NOTE: This is not part of the official boost submission. It exists
* only as a collection of ideas.
*/
#include <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");
}

View File

@@ -1,643 +0,0 @@
/* statistic_tests.hpp header file
*
* Copyright Jens Maurer 2000
* Permission to use, copy, modify, sell, and distribute this software
* is hereby granted without fee provided that the above copyright notice
* appears in all copies and that both that copyright notice and this
* permission notice appear in supporting documentation,
*
* Jens Maurer makes no representations about the suitability of this
* software for any purpose. It is provided "as is" without express or
* implied warranty.
*
* $Id$
*
*/
#ifndef STATISTIC_TESTS_HPP
#define STATISTIC_TESTS_HPP
#include <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 */

View File

@@ -1,25 +0,0 @@
# Boost Random Library test Jamfile
subproject libs/random/test ;
# bring in rules for testing
import testing ;
# Make tests run by default.
DEPENDS all : test ;
{
# look in BOOST_ROOT for sources first, just in this Jamfile
local SEARCH_SOURCE = $(BOOST_ROOT) $(SEARCH_SOURCE) ;
test-suite "random"
:
[ run libs/random/random_test.cpp ]
[ run libs/random/random_demo.cpp ]
# [ run libs/random/nondet_random_speed.cpp ]
# [ run libs/random/random_device.cpp ]
# [ run libs/random/random_speed.cpp ]
# [ run libs/random/statistic_tests.cpp ]
;
}

View File

@@ -1,20 +0,0 @@
# Boost Random Library test Jamfile
# bring in rules for testing
import testing ;
project
: source-location $(BOOST_ROOT)
;
{
test-suite "random"
:
[ run libs/random/random_test.cpp ]
[ run libs/random/random_demo.cpp ]
# [ run libs/random/nondet_random_speed.cpp ]
# [ run libs/random/random_device.cpp ]
# [ run libs/random/random_speed.cpp ]
# [ run libs/random/statistic_tests.cpp ]
;
}

File diff suppressed because it is too large Load Diff