Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r63088 - in trunk: boost/random libs/random/doc libs/random/test
From: steven_at_[hidden]
Date: 2010-06-18 18:05:16


Author: steven_watanabe
Date: 2010-06-18 18:05:11 EDT (Fri, 18 Jun 2010)
New Revision: 63088
URL: http://svn.boost.org/trac/boost/changeset/63088

Log:
Reimplement binomial_distribution.
Added:
   trunk/libs/random/test/chi_squared_test.hpp (contents, props changed)
   trunk/libs/random/test/test_binomial.cpp (contents, props changed)
   trunk/libs/random/test/test_binomial_distribution.cpp (contents, props changed)
Text files modified:
   trunk/boost/random/binomial_distribution.hpp | 455 +++++++++++++++++++++++++++++++++------
   trunk/libs/random/doc/random.qbk | 2
   trunk/libs/random/test/Jamfile.v2 | 3
   3 files changed, 381 insertions(+), 79 deletions(-)

Modified: trunk/boost/random/binomial_distribution.hpp
==============================================================================
--- trunk/boost/random/binomial_distribution.hpp (original)
+++ trunk/boost/random/binomial_distribution.hpp 2010-06-18 18:05:11 EDT (Fri, 18 Jun 2010)
@@ -1,6 +1,6 @@
 /* boost random/binomial_distribution.hpp header file
  *
- * Copyright Jens Maurer 2002
+ * Copyright Steven Watanabe 2010
  * Distributed under the Boost Software License, Version 1.0. (See
  * accompanying file LICENSE_1_0.txt or copy at
  * http://www.boost.org/LICENSE_1_0.txt)
@@ -8,104 +8,403 @@
  * See http://www.boost.org for most recent version including documentation.
  *
  * $Id$
- *
  */
 
-#ifndef BOOST_RANDOM_BINOMIAL_DISTRIBUTION_HPP
-#define BOOST_RANDOM_BINOMIAL_DISTRIBUTION_HPP
+#ifndef BOOST_RANDOM_BINOMIAL_DISTRIBUTION_HPP_INCLUDED
+#define BOOST_RANDOM_BINOMIAL_DISTRIBUTION_HPP_INCLUDED
+
+#include <cmath>
+#include <cstdlib>
+#include <iosfwd>
 
-#include <boost/config/no_tr1/cmath.hpp>
-#include <cassert>
 #include <boost/random/detail/config.hpp>
-#include <boost/random/bernoulli_distribution.hpp>
+#include <boost/random/uniform_01.hpp>
 
 namespace boost {
+namespace random {
+
+namespace detail {
+
+template<class RealType>
+struct binomial_table {
+ static const RealType table[10];
+};
+
+template<class RealType>
+const RealType binomial_table<RealType>::table[10] = {
+ 0.08106146679532726,
+ 0.04134069595540929,
+ 0.02767792568499834,
+ 0.02079067210376509,
+ 0.01664469118982119,
+ 0.01387612882307075,
+ 0.01189670994589177,
+ 0.01041126526197209,
+ 0.009255462182712733,
+ 0.008330563433362871
+};
+
+}
 
 /**
  * The binomial distribution is an integer valued distribution with
  * two parameters, @c t and @c p. The values of the distribution
  * are within the range [0,t].
  *
- * The probability that the distribution produces a value k is
- * \f${t \choose k}p^k(1-p)^{t-k}\f$.
+ * The distribution function is \f$P(k) = {t \choose k}p^k(1-p)^{t-k}\f$.
+ *
+ * The algorithm used is the BTRD algorithm described in
+ *
+ * @blockquote
+ * "The generation of binomial random variates", Wolfgang Hormann,
+ * Journal of Statistical Computation and Simulation, Volume 46,
+ * Issue 1 & 2 April 1993 , pages 101 - 110
+ * @endblockquote
  */
 template<class IntType = int, class RealType = double>
-class binomial_distribution
-{
+class binomial_distribution {
 public:
- typedef typename bernoulli_distribution<RealType>::input_type input_type;
- typedef IntType result_type;
+ typedef IntType result_type;
+ typedef RealType input_type;
 
- /**
- * Construct an @c binomial_distribution object. @c t and @c p
- * are the parameters of the distribution.
- *
- * Requires: t >=0 && 0 <= p <= 1
- */
- explicit binomial_distribution(IntType t = 1,
- const RealType& p = RealType(0.5))
- : _bernoulli(p), _t(t)
- {
- assert(_t >= 0);
- assert(RealType(0) <= p && p <= RealType(1));
- }
-
- // compiler-generated copy ctor and assignment operator are fine
-
- /** Returns: the @c t parameter of the distribution */
- IntType t() const { return _t; }
- /** Returns: the @c p parameter of the distribution */
- RealType p() const { return _bernoulli.p(); }
- /**
- * Effects: Subsequent uses of the distribution do not depend
- * on values produced by any engine prior to invoking reset.
- */
- void reset() { }
-
- /**
- * Returns: a random variate distributed according to the
- * binomial distribution.
- */
- template<class Engine>
- result_type operator()(Engine& eng)
- {
- // TODO: This is O(_t), but it should be O(log(_t)) for large _t
- result_type n = 0;
- for(IntType i = 0; i < _t; ++i)
- if(_bernoulli(eng))
- ++n;
- return n;
- }
+ class param_type {
+ public:
+ typedef binomial_distribution distribution_type;
+ /**
+ * Construct a param_type object. @c t and @c p
+ * are the parameters of the distribution.
+ *
+ * Requires: t >=0 && 0 <= p <= 1
+ */
+ explicit param_type(IntType t = 1, RealType p = RealType (0.5))
+ : _t(t), _p(p)
+ {}
+ /** Returns the @c t parameter of the distribution. */
+ IntType t() const { return _t; }
+ /** Returns the @c p parameter of the distribution. */
+ RealType p() const { return _p; }
+#ifndef BOOST_RANDOM_NO_STREAM_OPERATORS
+ /** Writes the parameters of the distribution to a @c std::ostream. */
+ template<class CharT, class Traits>
+ friend std::basic_ostream<CharT,Traits>&
+ operator<<(std::basic_ostream<CharT,Traits>& os,
+ const param_type& parm)
+ {
+ os << parm._p << " " << parm._t;
+ return os;
+ }
+
+ /** Reads the parameters of the distribution from a @c std::istream. */
+ template<class CharT, class Traits>
+ friend std::basic_istream<CharT,Traits>&
+ operator>>(std::basic_istream<CharT,Traits>& is, param_type& parm)
+ {
+ is >> parm._p >> std::ws >> parm._t;
+ return is;
+ }
+#endif
+ /** Returns true if the parameters have the same values. */
+ friend bool operator==(const param_type& lhs, const param_type& rhs)
+ {
+ return lhs._t == rhs._t && lhs._p == rhs._p;
+ }
+ /** Returns true if the parameters have different values. */
+ friend bool operator!=(const param_type& lhs, const param_type& rhs)
+ {
+ return !(lhs == rhs);
+ }
+ private:
+ IntType _t;
+ RealType _p;
+ };
+
+ /**
+ * Construct a @c binomial_distribution object. @c t and @c p
+ * are the parameters of the distribution.
+ *
+ * Requires: t >=0 && 0 <= p <= 1
+ */
+ explicit binomial_distribution(IntType t = 1, RealType p = RealType(0.5))
+ : _t(t), _p(p)
+ {
+ init();
+ }
+
+ /**
+ * Construct an @c binomial_distribution object from the
+ * parameters.
+ *
+ * Requires: @c parm is the result of calling @c param() on
+ * another @c binomial_distribution object.
+ */
+ explicit binomial_distribution(const param_type& parm)
+ : _t(parm.t()), _p(parm.p())
+ {
+ init();
+ }
+
+ /**
+ * Returns a random variate distributed according to the
+ * binomial distribution.
+ */
+ template<class URNG>
+ IntType operator()(URNG& urng) const
+ {
+ if(use_inversion()) {
+ if(0.5 < _p) {
+ return _t - invert(_t, 1-_p, urng);
+ } else {
+ return invert(_t, _p, urng);
+ }
+ } else if(0.5 < _p) {
+ return _t - generate(urng);
+ } else {
+ return generate(urng);
+ }
+ }
+
+ /**
+ * Returns a random variate distributed according to the
+ * binomial distribution with parameters specified by parm.
+ */
+ template<class URNG>
+ IntType operator()(URNG& urng, const param_type& parm) const
+ {
+ return binomial_distribution(parm)(urng);
+ }
+
+ /** Returns the @c t parameter of the distribution. */
+ IntType t() const { return _t; }
+ /** Returns the @c p parameter of the distribution. */
+ RealType p() const { return _p; }
+
+ /** Returns the smallest value that the distribution can produce. */
+ IntType min BOOST_PREVENT_MACRO_SUBSTITUTION() const { return 0; }
+ /** Returns the largest value that the distribution can produce. */
+ IntType max BOOST_PREVENT_MACRO_SUBSTITUTION() const { return _t; }
+
+ /** Returns the parameters of the distribution. */
+ param_type param() const { return param_type(_t, _p); }
+ /** Sets parameters of the distribution. */
+ void param(const param_type& parm)
+ {
+ _t = parm.t();
+ _p = parm.p();
+ init();
+ }
+
+ /**
+ * Effects: Subsequent uses of the distribution do not depend
+ * on values produced by any engine prior to invoking reset.
+ */
+ void reset() { }
 
 #ifndef BOOST_RANDOM_NO_STREAM_OPERATORS
- /**
- * Writes the parameters of the distribution to a @c std::ostream.
- */
- template<class CharT, class Traits>
- friend std::basic_ostream<CharT,Traits>&
- operator<<(std::basic_ostream<CharT,Traits>& os, const binomial_distribution& bd)
- {
- os << bd._bernoulli << " " << bd._t;
- return os;
- }
-
- /**
- * Reads the parameters of the distribution from a @c std::istream.
- */
- template<class CharT, class Traits>
- friend std::basic_istream<CharT,Traits>&
- operator>>(std::basic_istream<CharT,Traits>& is, binomial_distribution& bd)
- {
- is >> std::ws >> bd._bernoulli >> std::ws >> bd._t;
- return is;
- }
+ /** Writes the parameters of the distribution to a @c std::ostream. */
+ template<class CharT, class Traits>
+ friend std::basic_ostream<CharT,Traits>&
+ operator<<(std::basic_ostream<CharT,Traits>& os,
+ const binomial_distribution& bd)
+ {
+ os << bd.param();
+ return os;
+ }
+
+ /** Reads the parameters of the distribution from a @c std::istream. */
+ template<class CharT, class Traits>
+ friend std::basic_istream<CharT,Traits>&
+ operator>>(std::basic_istream<CharT,Traits>& is, binomial_distribution& bd)
+ {
+ param_type parm;
+ if(is >> parm) {
+ bd.param(parm);
+ }
+ return is;
+ }
 #endif
 
+ /** Returns true if the two distributions will produce the same
+ sequence of values, given equal generators. */
+ friend bool operator==(const binomial_distribution& lhs,
+ const binomial_distribution& rhs)
+ {
+ return lhs._t == rhs._t && lhs._p == rhs._p;
+ }
+ /** Returns true if the two distributions could produce different
+ sequences of values, given equal generators. */
+ friend bool operator!=(const binomial_distribution& lhs,
+ const binomial_distribution& rhs)
+ {
+ return !(lhs == rhs);
+ }
+
 private:
- bernoulli_distribution<RealType> _bernoulli;
- IntType _t;
+
+ /// @cond
+
+ bool use_inversion() const
+ {
+ // According to the paper, 11 should be safe,
+ // but I was having undiagnosed accuracy problems.
+ // A value of 20 should be safe
+ return m < 20;
+ }
+
+ // computes the correction factor for the Stirling approximation
+ // for log(k!)
+ static RealType fc(IntType k)
+ {
+ if(k < 10) return detail::binomial_table<RealType>::table[k];
+ else return (1./12 - (1./360 - 1./1260/((k+1)*(k+1)))/((k+1)*(k+1)))/(k+1);
+ }
+
+ void init()
+ {
+ using std::sqrt;
+ using std::pow;
+
+ RealType p = (0.5 < _p)? (1 - _p) : _p;
+ IntType t = _t;
+
+ m = static_cast<IntType>((t+1)*p);
+
+ if(use_inversion()) {
+ q_n = pow((1 - p), static_cast<RealType>(t));
+ } else {
+ btrd.r = p/(1-p);
+ btrd.nr = (t+1)*btrd.r;
+ btrd.npq = t*p*(1-p);
+ RealType sqrt_npq = sqrt(btrd.npq);
+ btrd.b = 1.15 + 2.53 * sqrt_npq;
+ btrd.a = -0.0873 + 0.0248*btrd.b + 0.01*p;
+ btrd.c = t*p + 0.5;
+ btrd.alpha = (2.83 + 5.1/btrd.b) * sqrt_npq;
+ btrd.v_r = 0.92 - 4.2/btrd.b;
+ btrd.u_rv_r = 0.86*btrd.v_r;
+ }
+ }
+
+ template<class URNG>
+ result_type generate(URNG& urng) const
+ {
+ using std::floor;
+ using std::abs;
+
+ while(true) {
+ RealType u;
+ RealType v = uniform_01<RealType>()(urng);
+ if(v <= btrd.u_rv_r) {
+ RealType u = v/btrd.v_r - 0.43;
+ return static_cast<IntType>(
+ (2*btrd.a/(0.5 - abs(u)) + btrd.b)*u + btrd.c);
+ }
+
+ if(v >= btrd.v_r) {
+ u = uniform_01<RealType>()(urng) - 0.5;
+ } else {
+ u = v/btrd.v_r - 0.93;
+ u = ((u < 0)? -0.5 : 0.5) - u;
+ v = uniform_01<RealType>()(urng) * btrd.v_r;
+ }
+
+ RealType us = 0.5 - abs(u);
+ IntType k = static_cast<IntType>((2*btrd.a/us + btrd.b)*u + btrd.c);
+ if(k < 0 || k > _t) continue;
+ v = v*btrd.alpha/(btrd.a/(us*us) + btrd.b);
+ IntType km = abs(k - m);
+ if(km <= 15) {
+ RealType f = 1;
+ if(m < k) {
+ IntType i = m;
+ do {
+ ++i;
+ f = f*(btrd.nr/i - btrd.r);
+ } while(i != k);
+ } else if(m > k) {
+ IntType i = k;
+ do {
+ ++i;
+ v = v*(btrd.nr/i - btrd.r);
+ } while(i != m);
+ }
+ if(v <= f) return k;
+ else continue;
+ } else {
+ // final acceptance/rejection
+ v = log(v);
+ RealType rho =
+ (km/btrd.npq)*(((km/3. + 0.625)*km + 1./6)/btrd.npq + 0.5);
+ RealType t = -km*km/(2*btrd.npq);
+ if(v < t - rho) return k;
+ if(v > t + rho) continue;
+
+ IntType nm = _t - m + 1;
+ RealType h = (m + 0.5)*log((m + 1)/(btrd.r*nm))
+ + fc(m) + fc(_t - m);
+
+ IntType nk = _t - k + 1;
+ if(v <= h + (_t+1)*log(static_cast<RealType>(nm)/nk)
+ + (k + 0.5)*log(nk*btrd.r/(k+1))
+ - fc(k)
+ - fc(_t - k))
+ {
+ return k;
+ } else {
+ continue;
+ }
+ }
+ }
+ }
+
+ template<class URNG>
+ IntType invert(IntType t, RealType p, URNG& urng) const
+ {
+ RealType q = 1 - p;
+ RealType s = p / q;
+ RealType a = (t + 1) * s;
+ RealType r = q_n;
+ RealType u = uniform_01<RealType>()(urng);
+ IntType x = 0;
+ while(u > r) {
+ u = u - r;
+ ++x;
+ r = ((a/x) - s) * r;
+ }
+ return x;
+ }
+
+ // parameters
+ IntType _t;
+ RealType _p;
+
+ // common data
+ IntType m;
+
+ union {
+ // for btrd
+ struct {
+ RealType r;
+ RealType nr;
+ RealType npq;
+ RealType b;
+ RealType a;
+ RealType c;
+ RealType alpha;
+ RealType v_r;
+ RealType u_rv_r;
+ } btrd;
+ // for inversion
+ RealType q_n;
+ };
+
+ /// @endcond
 };
 
-} // namespace boost
+}
+
+// backwards compatibility
+using random::binomial_distribution;
 
-#endif // BOOST_RANDOM_BINOMIAL_DISTRIBUTION_HPP
+}
+
+#endif

Modified: trunk/libs/random/doc/random.qbk
==============================================================================
--- trunk/libs/random/doc/random.qbk (original)
+++ trunk/libs/random/doc/random.qbk 2010-06-18 18:05:11 EDT (Fri, 18 Jun 2010)
@@ -62,7 +62,7 @@
 [def __uniform_01 [classref boost::uniform_01 uniform_01]]
 [def __uniform_real [classref boost::uniform_real uniform_real]]
 [def __bernoulli_distribution [classref boost::bernoulli_distribution bernoulli_distribution]]
-[def __binomial_distribution [classref boost::binomial_distribution binomial_distribution]]
+[def __binomial_distribution [classref boost::random::binomial_distribution binomial_distribution]]
 [def __cauchy_distribution [classref boost::cauchy_distribution cauchy_distribution]]
 [def __gamma_distribution [classref boost::gamma_distribution gamma_distribution]]
 [def __poisson_distribution [classref boost::poisson_distribution poisson_distribution]]

Modified: trunk/libs/random/test/Jamfile.v2
==============================================================================
--- trunk/libs/random/test/Jamfile.v2 (original)
+++ trunk/libs/random/test/Jamfile.v2 2010-06-18 18:05:11 EDT (Fri, 18 Jun 2010)
@@ -41,6 +41,9 @@
     run instantiate.cpp : : : <define>BOOST_RANDOM_URNG_TEST=$(urng) : test_$(urng) ;
 }
 
+run test_binomial.cpp ;
+run test_binomial_distribution.cpp /boost//unit_test_framework ;
+
 # run nondet_random_speed.cpp ;
 # run random_device.cpp ;
 # run random_speed.cpp ;

Added: trunk/libs/random/test/chi_squared_test.hpp
==============================================================================
--- (empty file)
+++ trunk/libs/random/test/chi_squared_test.hpp 2010-06-18 18:05:11 EDT (Fri, 18 Jun 2010)
@@ -0,0 +1,92 @@
+/* chi_squared_test.hpp header file
+ *
+ * Copyright Steven Watanabe 2010
+ * Distributed under the Boost Software License, Version 1.0. (See
+ * accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ *
+ * $Id$
+ *
+ */
+
+#ifndef BOOST_RANDOM_TEST_CHI_SQUARED_TEST_HPP_INCLUDED
+#define BOOST_RANDOM_TEST_CHI_SQUARED_TEST_HPP_INCLUDED
+
+#include <vector>
+
+#include <boost/math/special_functions/pow.hpp>
+#include <boost/math/distributions/chi_squared.hpp>
+
+// This only works for discrete distributions with fixed
+// upper and lower bounds.
+
+template<class IntType>
+struct chi_squared_collector {
+
+ static const IntType cutoff = 5;
+
+ chi_squared_collector()
+ : chi_squared(0),
+ variables(0),
+ prev_actual(0),
+ prev_expected(0),
+ current_actual(0),
+ current_expected(0)
+ {}
+
+ void operator()(IntType actual, double expected) {
+ current_actual += actual;
+ current_expected += expected;
+
+ if(expected >= cutoff) {
+ if(prev_expected != 0) {
+ update(prev_actual, prev_expected);
+ }
+ prev_actual = current_actual;
+ prev_expected = current_expected;
+
+ current_actual = 0;
+ current_expected = 0;
+ }
+ }
+
+ void update(IntType actual, double expected) {
+ chi_squared += boost::math::pow<2>(actual - expected) / expected;
+ ++variables;
+ }
+
+ double cdf() {
+ if(prev_expected != 0) {
+ update(prev_actual + current_actual, prev_expected + current_expected);
+ prev_actual = 0;
+ prev_expected = 0;
+ current_actual = 0;
+ current_expected = 0;
+ }
+ if(variables <= 1) {
+ return 0;
+ } else {
+ return boost::math::cdf(boost::math::chi_squared(variables - 1), chi_squared);
+ }
+ }
+
+ double chi_squared;
+ std::size_t variables;
+
+ IntType prev_actual;
+ double prev_expected;
+
+ IntType current_actual;
+ double current_expected;
+};
+
+template<class IntType>
+double chi_squared_test(const std::vector<IntType>& results, const std::vector<double>& probabilities, IntType iterations) {
+ chi_squared_collector<IntType> calc;
+ for(std::size_t i = 0; i < results.size(); ++i) {
+ calc(results[i], iterations * probabilities[i]);
+ }
+ return calc.cdf();
+}
+
+#endif

Added: trunk/libs/random/test/test_binomial.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/random/test/test_binomial.cpp 2010-06-18 18:05:11 EDT (Fri, 18 Jun 2010)
@@ -0,0 +1,116 @@
+/* test_binomial.cpp
+ *
+ * Copyright Steven Watanabe 2010
+ * Distributed under the Boost Software License, Version 1.0. (See
+ * accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ *
+ * $Id$
+ *
+ */
+
+#include <boost/random/binomial_distribution.hpp>
+#include <boost/random/uniform_int.hpp>
+#include <boost/random/uniform_01.hpp>
+#include <boost/random/mersenne_twister.hpp>
+#include <boost/math/distributions/binomial.hpp>
+#include <boost/lexical_cast.hpp>
+#include <vector>
+#include <iostream>
+#include <numeric>
+
+#include "chi_squared_test.hpp"
+
+bool do_test(int n, double p, long long max) {
+ std::cout << "running binomial(" << n << ", " << p << ")" << " " << max << " times: " << std::flush;
+
+ std::vector<double> expected(n+1);
+ {
+ boost::math::binomial dist(n, p);
+ for(int i = 0; i <= n; ++i) {
+ expected[i] = pdf(dist, i);
+ }
+ }
+
+ boost::random::binomial_distribution<int, double> dist(n, p);
+ boost::mt19937 gen;
+ std::vector<long long> results(n + 1);
+ for(long long i = 0; i < max; ++i) {
+ ++results[dist(gen)];
+ }
+
+ long long sum = std::accumulate(results.begin(), results.end(), 0ll);
+ if(sum != max) {
+ std::cout << "*** Failed: incorrect total: " << sum << " ***" << std::endl;
+ return false;
+ }
+ double chsqr = chi_squared_test(results, expected, max);
+
+ bool result = chsqr < 0.99;
+ const char* err = result? "" : "*";
+ std::cout << std::setprecision(17) << chsqr << err << std::endl;
+
+ std::cout << std::setprecision(6);
+
+ return result;
+}
+
+bool do_tests(int repeat, int max_n, long long trials) {
+ boost::mt19937 gen;
+ boost::uniform_int<> idist(0, max_n);
+ boost::uniform_01<> rdist;
+ int errors = 0;
+ for(int i = 0; i < repeat; ++i) {
+ if(!do_test(idist(gen), rdist(gen), trials)) {
+ ++errors;
+ }
+ }
+ if(errors != 0) {
+ std::cout << "*** " << errors << " errors detected ***" << std::endl;
+ }
+ return errors == 0;
+}
+
+int usage() {
+ std::cerr << "Usage: test_binomial_distribution -r <repeat> -n <max n> -t <trials>" << std::endl;
+ return 2;
+}
+
+template<class T>
+bool handle_option(int& argc, char**& argv, char opt, T& value) {
+ if(argv[0][1] == opt && argc > 1) {
+ --argc;
+ ++argv;
+ value = boost::lexical_cast<T>(argv[0]);
+ return true;
+ } else {
+ return false;
+ }
+}
+
+int main(int argc, char** argv) {
+ int repeat = 10;
+ int max_n = 100000;
+ long long trials = 1000000ll;
+
+ if(argc > 0) {
+ --argc;
+ ++argv;
+ }
+ while(argc > 0) {
+ if(argv[0][0] != '-') return usage();
+ else if(!handle_option(argc, argv, 'r', repeat)
+ && !handle_option(argc, argv, 'n', max_n)
+ && !handle_option(argc, argv, 't', trials)) {
+ return usage();
+ }
+ --argc;
+ ++argv;
+ }
+
+ if(do_tests(repeat, max_n, trials)) {
+ return 0;
+ } else {
+ return EXIT_FAILURE;
+ }
+}

Added: trunk/libs/random/test/test_binomial_distribution.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/random/test/test_binomial_distribution.cpp 2010-06-18 18:05:11 EDT (Fri, 18 Jun 2010)
@@ -0,0 +1,133 @@
+/* test_binomial_distribution.cpp
+ *
+ * Copyright Steven Watanabe 2010
+ * Distributed under the Boost Software License, Version 1.0. (See
+ * accompanying file LICENSE_1_0.txt or copy at
+ * http://www.boost.org/LICENSE_1_0.txt)
+ *
+ * $Id$
+ *
+ */
+
+#include <boost/random/binomial_distribution.hpp>
+#include <boost/random/linear_congruential.hpp>
+#include <sstream>
+
+#define BOOST_TEST_MAIN
+#include <boost/test/unit_test.hpp>
+
+BOOST_AUTO_TEST_CASE(test_constructors) {
+ boost::random::binomial_distribution<> dist;
+ BOOST_CHECK_EQUAL(dist.t(), 1);
+ BOOST_CHECK_EQUAL(dist.p(), 0.5);
+ boost::random::binomial_distribution<> dist_one(10);
+ BOOST_CHECK_EQUAL(dist_one.t(), 10);
+ BOOST_CHECK_EQUAL(dist_one.p(), 0.5);
+ boost::random::binomial_distribution<> dist_two(10, 0.25);
+ BOOST_CHECK_EQUAL(dist_two.t(), 10);
+ BOOST_CHECK_EQUAL(dist_two.p(), 0.25);
+ boost::random::binomial_distribution<> copy(dist);
+ BOOST_CHECK_EQUAL(dist, copy);
+ boost::random::binomial_distribution<> copy_one(dist_one);
+ BOOST_CHECK_EQUAL(dist_one, copy_one);
+ boost::random::binomial_distribution<> copy_two(dist_two);
+ BOOST_CHECK_EQUAL(dist_two, copy_two);
+}
+
+BOOST_AUTO_TEST_CASE(test_copy_constructor) {
+ boost::random::binomial_distribution<> dist(10, 0.25);
+}
+
+BOOST_AUTO_TEST_CASE(test_param) {
+ boost::random::binomial_distribution<> dist(10, 0.25);
+ boost::random::binomial_distribution<>::param_type param = dist.param();
+ BOOST_CHECK_EQUAL(param.t(), 10);
+ BOOST_CHECK_EQUAL(param.p(), 0.25);
+ boost::random::binomial_distribution<> copy1(param);
+ BOOST_CHECK_EQUAL(dist, copy1);
+ boost::random::binomial_distribution<> copy2;
+ copy2.param(param);
+ BOOST_CHECK_EQUAL(dist, copy2);
+
+ boost::random::binomial_distribution<>::param_type param_copy = param;
+ BOOST_CHECK_EQUAL(param, param_copy);
+ BOOST_CHECK(param == param_copy);
+ BOOST_CHECK(!(param != param_copy));
+ boost::random::binomial_distribution<>::param_type param_default;
+ BOOST_CHECK_EQUAL(param_default.t(), 1);
+ BOOST_CHECK_EQUAL(param_default.p(), 0.5);
+ BOOST_CHECK(param != param_default);
+ BOOST_CHECK(!(param == param_default));
+ boost::random::binomial_distribution<>::param_type param_one(10);
+ BOOST_CHECK_EQUAL(param_one.t(), 10);
+ BOOST_CHECK_EQUAL(param_one.p(), 0.5);
+ BOOST_CHECK(param != param_one);
+ BOOST_CHECK(!(param == param_one));
+ BOOST_CHECK(param_default != param_one);
+ BOOST_CHECK(!(param_default == param_one));
+ boost::random::binomial_distribution<>::param_type param_two(10, 0.25);
+ BOOST_CHECK_EQUAL(param_two.t(), 10);
+ BOOST_CHECK_EQUAL(param_two.p(), 0.25);
+}
+
+BOOST_AUTO_TEST_CASE(test_min_max) {
+ boost::random::binomial_distribution<> dist;
+ BOOST_CHECK_EQUAL((dist.min)(), 0);
+ BOOST_CHECK_EQUAL((dist.max)(), 1);
+ boost::random::binomial_distribution<> dist_one(10);
+ BOOST_CHECK_EQUAL((dist_one.min)(), 0);
+ BOOST_CHECK_EQUAL((dist_one.max)(), 10);
+ boost::random::binomial_distribution<> dist_two(10, 0.25);
+ BOOST_CHECK_EQUAL((dist_two.min)(), 0);
+ BOOST_CHECK_EQUAL((dist_two.max)(), 10);
+}
+
+BOOST_AUTO_TEST_CASE(test_comparison) {
+ boost::random::binomial_distribution<> dist;
+ boost::random::binomial_distribution<> dist_copy(dist);
+ boost::random::binomial_distribution<> dist_one(10);
+ boost::random::binomial_distribution<> dist_one_copy(dist_one);
+ boost::random::binomial_distribution<> dist_two(10, 0.25);
+ boost::random::binomial_distribution<> dist_two_copy(dist_two);
+ BOOST_CHECK(dist == dist_copy);
+ BOOST_CHECK(!(dist != dist_copy));
+ BOOST_CHECK(dist_one == dist_one_copy);
+ BOOST_CHECK(!(dist_one != dist_one_copy));
+ BOOST_CHECK(dist_two == dist_two_copy);
+ BOOST_CHECK(!(dist_two != dist_two_copy));
+ BOOST_CHECK(dist != dist_one);
+ BOOST_CHECK(!(dist == dist_one));
+ BOOST_CHECK(dist != dist_two);
+ BOOST_CHECK(!(dist == dist_two));
+ BOOST_CHECK(dist_one != dist_two);
+ BOOST_CHECK(!(dist_one == dist_two));
+}
+
+BOOST_AUTO_TEST_CASE(test_streaming) {
+ boost::random::binomial_distribution<> dist(10, 0.25);
+ std::stringstream stream;
+ stream << dist;
+ boost::random::binomial_distribution<> restored_dist;
+ stream >> restored_dist;
+ BOOST_CHECK_EQUAL(dist, restored_dist);
+}
+
+BOOST_AUTO_TEST_CASE(test_generation) {
+ boost::minstd_rand0 gen;
+ boost::random::binomial_distribution<> dist;
+ boost::random::binomial_distribution<> dist_two(10, 0.25);
+ for(int i = 0; i < 10; ++i) {
+ int value = dist(gen);
+ BOOST_CHECK_GE(value, (dist.min)());
+ BOOST_CHECK_LE(value, (dist.max)());
+ int value_two = dist_two(gen);
+ BOOST_CHECK_GE(value_two, (dist_two.min)());
+ BOOST_CHECK_LE(value_two, (dist_two.max)());
+ int value_param = dist_two(gen, dist.param());
+ BOOST_CHECK_GE(value_param, (dist.min)());
+ BOOST_CHECK_LE(value_param, (dist.max)());
+ int value_two_param = dist(gen, dist_two.param());
+ BOOST_CHECK_GE(value_two_param, (dist_two.min)());
+ BOOST_CHECK_LE(value_two_param, (dist_two.max)());
+ }
+}


Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk