Boost logo

Boost-Commit :

Subject: [Boost-commit] svn:boost r68410 - in trunk: boost/random libs/random/doc libs/random/test
From: steven_at_[hidden]
Date: 2011-01-24 01:29:09


Author: steven_watanabe
Date: 2011-01-24 01:28:59 EST (Mon, 24 Jan 2011)
New Revision: 68410
URL: http://svn.boost.org/trac/boost/changeset/68410

Log:
Update geometric_distribution to match C++0x.
Added:
   trunk/libs/random/test/test_geometric.cpp (contents, props changed)
   trunk/libs/random/test/test_geometric_distribution.cpp (contents, props changed)
Text files modified:
   trunk/boost/random/geometric_distribution.hpp | 285 ++++++++++++++++++++++++++++++---------
   trunk/libs/random/doc/Jamfile.v2 | 2
   trunk/libs/random/test/Jamfile.v2 | 2
   trunk/libs/random/test/test_real_distribution.ipp | 38 ++++
   4 files changed, 254 insertions(+), 73 deletions(-)

Modified: trunk/boost/random/geometric_distribution.hpp
==============================================================================
--- trunk/boost/random/geometric_distribution.hpp (original)
+++ trunk/boost/random/geometric_distribution.hpp 2011-01-24 01:28:59 EST (Mon, 24 Jan 2011)
@@ -1,6 +1,7 @@
 /* boost random/geometric_distribution.hpp header file
  *
  * Copyright Jens Maurer 2000-2001
+ * Copyright Steven Watanabe 2011
  * 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)
@@ -18,17 +19,14 @@
 
 #include <boost/config/no_tr1/cmath.hpp> // std::log
 #include <cassert>
-#include <iostream>
+#include <iosfwd>
+#include <ios>
 #include <boost/random/detail/config.hpp>
+#include <boost/random/detail/operators.hpp>
 #include <boost/random/uniform_01.hpp>
 
 namespace boost {
-
-#if defined(__GNUC__) && (__GNUC__ < 3)
-// Special gcc workaround: gcc 2.95.x ignores using-declarations
-// in template classes (confirmed by gcc author Martin v. Loewis)
- using std::log;
-#endif
+namespace random {
 
 /**
  * An instantiation of the class template @c geometric_distribution models
@@ -36,83 +34,230 @@
  * integers which are the number of bernoulli trials
  * with probability @c p required to get one that fails.
  *
- * For the geometric distribution, \f$p(i) = (1-p) p^{i-1}\f$.
+ * For the geometric distribution, \f$p(i) = p(1-p)^{i}\f$.
+ *
+ * @xmlwarning
+ * This distribution has been updated to match the C++ standard.
+ * Its behavior has changed from the original
+ * boost::geometric_distribution. A backwards compatible
+ * wrapper is provided in namespace boost.
+ * @endxmlwarning
  */
 template<class IntType = int, class RealType = double>
 class geometric_distribution
 {
 public:
- typedef RealType input_type;
- typedef IntType result_type;
+ typedef RealType input_type;
+ typedef IntType result_type;
 
- /**
- * Contructs a new geometric_distribution with the paramter @c p.
- *
- * Requires: 0 < p < 1
- */
- explicit geometric_distribution(const RealType& p = RealType(0.5))
- : _p(p)
- {
- assert(RealType(0) < _p && _p < RealType(1));
- init();
- }
-
- // compiler-generated copy ctor and assignment operator are fine
-
- /**
- * Returns: the distribution parameter @c p
- */
- RealType p() const { return _p; }
- void reset() { }
-
- template<class Engine>
- result_type operator()(Engine& eng)
- {
-#ifndef BOOST_NO_STDC_NAMESPACE
- using std::log;
- using std::floor;
-#endif
- return IntType(floor(log(RealType(1)-eng()) / _log_p)) + IntType(1);
- }
-
-#ifndef BOOST_RANDOM_NO_STREAM_OPERATORS
- template<class CharT, class Traits>
- friend std::basic_ostream<CharT,Traits>&
- operator<<(std::basic_ostream<CharT,Traits>& os, const geometric_distribution& gd)
- {
- os << gd._p;
- return os;
- }
-
- template<class CharT, class Traits>
- friend std::basic_istream<CharT,Traits>&
- operator>>(std::basic_istream<CharT,Traits>& is, geometric_distribution& gd)
- {
- is >> std::ws >> gd._p;
- gd.init();
- return is;
- }
-#endif
+ class param_type
+ {
+ public:
+
+ typedef geometric_distribution distribution_type;
+
+ /** Constructs the parameters with p. */
+ explicit param_type(RealType p_arg = RealType(0.5))
+ : _p(p_arg)
+ {
+ assert(RealType(0) < _p && _p < RealType(1));
+ }
+
+ /** Returns the p parameter of the distribution. */
+ RealType p() const { return _p; }
+
+ /** Writes the parameters to a std::ostream. */
+ BOOST_RANDOM_DETAIL_OSTREAM_OPERATOR(os, param_type, parm)
+ {
+ os << parm._p;
+ return os;
+ }
+
+ /** Reads the parameters from a std::istream. */
+ BOOST_RANDOM_DETAIL_ISTREAM_OPERATOR(is, param_type, parm)
+ {
+ double p_in;
+ if(is >> p_in) {
+ if(p_in > RealType(0) && p_in < RealType(1)) {
+ parm._p = p_in;
+ } else {
+ is.setstate(std::ios_base::failbit);
+ }
+ }
+ return is;
+ }
+
+ /** Returns true if the two sets of parameters are equal. */
+ BOOST_RANDOM_DETAIL_EQUALITY_OPERATOR(param_type, lhs, rhs)
+ { return lhs._p == rhs._p; }
+
+ /** Returns true if the two sets of parameters are different. */
+ BOOST_RANDOM_DETAIL_INEQUALITY_OPERATOR(param_type)
+
+
+ private:
+ RealType _p;
+ };
+
+ /**
+ * Contructs a new geometric_distribution with the paramter @c p.
+ *
+ * Requires: 0 < p < 1
+ */
+ explicit geometric_distribution(const RealType& p = RealType(0.5))
+ : _p(p)
+ {
+ assert(RealType(0) < _p && _p < RealType(1));
+ init();
+ }
+
+ /** Constructs a new geometric_distribution from its parameters. */
+ explicit geometric_distribution(const param_type& parm)
+ : _p(parm.p())
+ {
+ init();
+ }
+
+ // compiler-generated copy ctor and assignment operator are fine
+
+ /** Returns: the distribution parameter @c p */
+ RealType p() const { return _p; }
+
+ /** Returns the smallest value that the distribution can produce. */
+ IntType min BOOST_PREVENT_MACRO_SUBSTITUTION () const { return IntType(1); }
+
+ /** Returns the largest value that the distribution can produce. */
+ IntType max BOOST_PREVENT_MACRO_SUBSTITUTION () const
+ { return (std::numeric_limits<IntType>::max)(); }
+
+ /** Returns the parameters of the distribution. */
+ param_type param() const { return param_type(_p); }
+
+ /** Sets the parameters of the distribution. */
+ void param(const param_type& parm)
+ {
+ _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() { }
+
+ /**
+ * Returns a random variate distributed according to the
+ * geometric_distribution.
+ */
+ template<class Engine>
+ result_type operator()(Engine& eng) const
+ {
+ using std::log;
+ using std::floor;
+ RealType x = RealType(1) - boost::uniform_01<RealType>()(eng);
+ return IntType(floor(log(x) / _log_1mp));
+ }
+
+ /**
+ * Returns a random variate distributed according to the
+ * geometric distribution with parameters specified by param.
+ */
+ template<class Engine>
+ result_type operator()(Engine& eng, const param_type& parm) const
+ { return geometric_distribution(parm)(eng); }
+
+ /** Writes the distribution to a @c std::ostream. */
+ BOOST_RANDOM_DETAIL_OSTREAM_OPERATOR(os, geometric_distribution, gd)
+ {
+ os << gd._p;
+ return os;
+ }
+
+ /** Reads the distribution from a @c std::istream. */
+ BOOST_RANDOM_DETAIL_ISTREAM_OPERATOR(is, geometric_distribution, gd)
+ {
+ param_type parm;
+ if(is >> parm) {
+ gd.param(parm);
+ }
+ return is;
+ }
+
+ /**
+ * Returns true if the two distributions will produce identical
+ * sequences of values given equal generators.
+ */
+ BOOST_RANDOM_DETAIL_EQUALITY_OPERATOR(geometric_distribution, lhs, rhs)
+ { return lhs._p == rhs._p; }
+
+ /**
+ * Returns true if the two distributions may produce different
+ * sequences of values given equal generators.
+ */
+ BOOST_RANDOM_DETAIL_INEQUALITY_OPERATOR(geometric_distribution)
 
 private:
 
- /// \cond hide_private_functions
+ /// \cond
 
- void init()
- {
-#ifndef BOOST_NO_STDC_NAMESPACE
- using std::log;
-#endif
- _log_p = log(_p);
- }
+ void init()
+ {
+ using std::log;
+ _log_1mp = log(1 - _p);
+ }
 
- /// \endcond
+ RealType _p;
+ RealType _log_1mp;
 
- RealType _p;
- RealType _log_p;
+ /// \endcond
+};
+
+} // namespace random
+
+/**
+ * Provided for backwards compatibility. This class is
+ * deprecated. It provides the old behavior of geometric_distribution
+ * with \f$p(i) = (1-p) p^{i-1}\f$.
+ */
+template<class IntType = int, class RealType = double>
+class geometric_distribution
+{
+public:
+ typedef RealType input_type;
+ typedef IntType result_type;
+
+ explicit geometric_distribution(RealType p_arg = RealType(0.5))
+ : _impl(1 - p_arg) {}
+
+ RealType p() const { return 1 - _impl.p(); }
+
+ void reset() {}
+
+ template<class Engine>
+ IntType operator()(Engine& eng) const { return _impl(eng) + IntType(1); }
+
+ BOOST_RANDOM_DETAIL_OSTREAM_OPERATOR(os, geometric_distribution, gd)
+ {
+ os << gd.p();
+ return os;
+ }
+
+ BOOST_RANDOM_DETAIL_ISTREAM_OPERATOR(is, geometric_distribution, gd)
+ {
+ RealType val;
+ if(is >> val) {
+ typename impl_type::param_type impl_param(1 - val);
+ gd._impl.param(impl_param);
+ }
+ return is;
+ }
+
+private:
+ typedef random::geometric_distribution<IntType, RealType> impl_type;
+ impl_type _impl;
 };
 
 } // namespace boost
 
 #endif // BOOST_RANDOM_GEOMETRIC_DISTRIBUTION_HPP
-

Modified: trunk/libs/random/doc/Jamfile.v2
==============================================================================
--- trunk/libs/random/doc/Jamfile.v2 (original)
+++ trunk/libs/random/doc/Jamfile.v2 2011-01-24 01:28:59 EST (Mon, 24 Jan 2011)
@@ -69,6 +69,8 @@
     <doxygen:param>"ALIASES= \\
         xmlnote=\"@xmlonly <note><para> @endxmlonly\" \\
         endxmlnote=\"@xmlonly </para></note> @endxmlonly\" \\
+ xmlwarning=\"@xmlonly <warning><para> @endxmlonly\" \\
+ endxmlwarning=\"@xmlonly </para></warning> @endxmlonly\" \\
         blockquote=\"@xmlonly <blockquote><para> @endxmlonly\" \\
         endblockquote=\"@xmlonly </para></blockquote> @endxmlonly\" \\
         boost=\"$(BOOST_ROOT)\" \\

Modified: trunk/libs/random/test/Jamfile.v2
==============================================================================
--- trunk/libs/random/test/Jamfile.v2 (original)
+++ trunk/libs/random/test/Jamfile.v2 2011-01-24 01:28:59 EST (Mon, 24 Jan 2011)
@@ -79,6 +79,8 @@
 run test_bernoulli_distribution.cpp /boost//unit_test_framework ;
 run test_cauchy.cpp ;
 run test_cauchy_distribution.cpp /boost//unit_test_framework ;
+run test_geometric.cpp ;
+run test_geometric_distribution.cpp /boost//unit_test_framework ;
 
 # run nondet_random_speed.cpp ;
 # run random_device.cpp ;

Added: trunk/libs/random/test/test_geometric.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/random/test/test_geometric.cpp 2011-01-24 01:28:59 EST (Mon, 24 Jan 2011)
@@ -0,0 +1,25 @@
+/* test_geometric.cpp
+ *
+ * Copyright Steven Watanabe 2011
+ * 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/geometric_distribution.hpp>
+#include <boost/random/uniform_real.hpp>
+#include <boost/math/distributions/geometric.hpp>
+
+#define BOOST_RANDOM_DISTRIBUTION boost::random::geometric_distribution<>
+#define BOOST_RANDOM_DISTRIBUTION_NAME geometric
+#define BOOST_MATH_DISTRIBUTION boost::math::geometric
+#define BOOST_RANDOM_ARG1_TYPE double
+#define BOOST_RANDOM_ARG1_NAME p
+#define BOOST_RANDOM_ARG1_DEFAULT 0.5
+#define BOOST_RANDOM_ARG1_DISTRIBUTION(n) boost::uniform_real<>(0.0001, 0.9999)
+#define BOOST_RANDOM_DISTRIBUTION_MAX (-5 / std::log(1-p))
+
+#include "test_real_distribution.ipp"

Added: trunk/libs/random/test/test_geometric_distribution.cpp
==============================================================================
--- (empty file)
+++ trunk/libs/random/test/test_geometric_distribution.cpp 2011-01-24 01:28:59 EST (Mon, 24 Jan 2011)
@@ -0,0 +1,31 @@
+/* test_geometric_distribution.cpp
+ *
+ * Copyright Steven Watanabe 2011
+ * 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/geometric_distribution.hpp>
+
+#define BOOST_RANDOM_DISTRIBUTION boost::random::geometric_distribution<>
+#define BOOST_RANDOM_ARG1 p
+#define BOOST_RANDOM_ARG1_DEFAULT 0.5
+#define BOOST_RANDOM_ARG1_VALUE 0.25
+
+#define BOOST_RANDOM_DIST0_MIN 1
+#define BOOST_RANDOM_DIST0_MAX (std::numeric_limits<int>::max)()
+#define BOOST_RANDOM_DIST1_MIN 1
+#define BOOST_RANDOM_DIST1_MAX (std::numeric_limits<int>::max)()
+
+#define BOOST_RANDOM_TEST1_PARAMS (0.9999)
+#define BOOST_RANDOM_TEST1_MIN 0
+#define BOOST_RANDOM_TEST1_MAX 0
+
+#define BOOST_RANDOM_TEST2_PARAMS (0.0001)
+#define BOOST_RANDOM_TEST2_MIN 1
+
+#include "test_distribution.ipp"

Modified: trunk/libs/random/test/test_real_distribution.ipp
==============================================================================
--- trunk/libs/random/test/test_real_distribution.ipp (original)
+++ trunk/libs/random/test/test_real_distribution.ipp 2011-01-24 01:28:59 EST (Mon, 24 Jan 2011)
@@ -22,14 +22,17 @@
 #include <boost/exception/diagnostic_information.hpp>
 #include <boost/preprocessor/stringize.hpp>
 #include <iostream>
+#include <numeric>
+#include <vector>
 
 #include "statistic_tests.hpp"
+#include "chi_squared_test.hpp"
 
 bool do_test(BOOST_RANDOM_ARG1_TYPE BOOST_RANDOM_ARG1_NAME,
 #ifdef BOOST_RANDOM_ARG2_TYPE
              BOOST_RANDOM_ARG2_TYPE BOOST_RANDOM_ARG2_NAME,
 #endif
- int max) {
+ long long max) {
     std::cout << "running " BOOST_PP_STRINGIZE(BOOST_RANDOM_DISTRIBUTION_NAME) "("
         << BOOST_RANDOM_ARG1_NAME;
 #ifdef BOOST_RANDOM_ARG2_NAME
@@ -45,11 +48,40 @@
 #endif
         );
     boost::mt19937 gen;
+
+#ifdef BOOST_RANDOM_DISTRIBUTION_MAX
+
+ BOOST_RANDOM_DISTRIBUTION::result_type max_value = BOOST_RANDOM_DISTRIBUTION_MAX;
+
+ std::vector<double> expected_counts(max_value+1);
+ {
+ for(int i = 0; i <= max_value; ++i) {
+ expected_counts[i] = pdf(expected, i);
+ }
+ expected_counts.back() += 1 - cdf(expected, max_value);
+ }
+
+ std::vector<long long> results(max_value + 1);
+ for(long long i = 0; i < max; ++i) {
+ ++results[std::min(dist(gen), max_value)];
+ }
+
+ long long sum = std::accumulate(results.begin(), results.end(), 0ll);
+ if(sum != max) {
+ std::cout << "*** Failed: incorrect total: " << sum << " ***" << std::endl;
+ return false;
+ }
+ double prob = chi_squared_test(results, expected_counts, max);
+
+#else
+
     kolmogorov_experiment test(max);
     boost::variate_generator<boost::mt19937&, BOOST_RANDOM_DISTRIBUTION > vgen(gen, dist);
 
     double prob = test.probability(test.run(vgen, expected));
 
+#endif
+
     bool result = prob < 0.99;
     const char* err = result? "" : "*";
     std::cout << std::setprecision(17) << prob << err << std::endl;
@@ -68,7 +100,7 @@
 #ifdef BOOST_RANDOM_ARG2_NAME
               Dist2 d2,
 #endif
- int trials) {
+ long long trials) {
     boost::mt19937 gen;
     int errors = 0;
     for(int i = 0; i < repeat; ++i) {
@@ -117,7 +149,7 @@
 #ifdef BOOST_RANDOM_ARG2_TYPE
     BOOST_RANDOM_ARG2_TYPE max_arg2 = BOOST_RANDOM_ARG2_DEFAULT;
 #endif
- int trials = 1000000;
+ long long trials = 1000000;
 
     if(argc > 0) {
         --argc;


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