1 /* boost random/geometric_distribution.hpp header file 2 * 3 * Copyright Jens Maurer 2000-2001 4 * Copyright Steven Watanabe 2011 5 * Distributed under the Boost Software License, Version 1.0. (See 6 * accompanying file LICENSE_1_0.txt or copy at 7 * http://www.boost.org/LICENSE_1_0.txt) 8 * 9 * See http://www.boost.org for most recent version including documentation. 10 * 11 * $Id$ 12 * 13 * Revision history 14 * 2001-02-18 moved to individual header files 15 */ 16 17 #ifndef BOOST_RANDOM_GEOMETRIC_DISTRIBUTION_HPP 18 #define BOOST_RANDOM_GEOMETRIC_DISTRIBUTION_HPP 19 20 #include <boost/config/no_tr1/cmath.hpp> // std::log 21 #include <iosfwd> 22 #include <ios> 23 #include <boost/assert.hpp> 24 #include <boost/random/detail/config.hpp> 25 #include <boost/random/detail/operators.hpp> 26 #include <boost/random/uniform_01.hpp> 27 28 namespace boost { 29 namespace random { 30 31 /** 32 * An instantiation of the class template @c geometric_distribution models 33 * a \random_distribution. The distribution produces positive 34 * integers which are the number of bernoulli trials 35 * with probability @c p required to get one that fails. 36 * 37 * For the geometric distribution, \f$p(i) = p(1-p)^{i}\f$. 38 * 39 * @xmlwarning 40 * This distribution has been updated to match the C++ standard. 41 * Its behavior has changed from the original 42 * boost::geometric_distribution. A backwards compatible 43 * wrapper is provided in namespace boost. 44 * @endxmlwarning 45 */ 46 template<class IntType = int, class RealType = double> 47 class geometric_distribution 48 { 49 public: 50 typedef RealType input_type; 51 typedef IntType result_type; 52 53 class param_type 54 { 55 public: 56 57 typedef geometric_distribution distribution_type; 58 59 /** Constructs the parameters with p. */ param_type(RealType p_arg=RealType (0.5))60 explicit param_type(RealType p_arg = RealType(0.5)) 61 : _p(p_arg) 62 { 63 BOOST_ASSERT(RealType(0) < _p && _p < RealType(1)); 64 } 65 66 /** Returns the p parameter of the distribution. */ p() const67 RealType p() const { return _p; } 68 69 /** Writes the parameters to a std::ostream. */ BOOST_RANDOM_DETAIL_OSTREAM_OPERATOR(os,param_type,parm)70 BOOST_RANDOM_DETAIL_OSTREAM_OPERATOR(os, param_type, parm) 71 { 72 os << parm._p; 73 return os; 74 } 75 76 /** Reads the parameters from a std::istream. */ BOOST_RANDOM_DETAIL_ISTREAM_OPERATOR(is,param_type,parm)77 BOOST_RANDOM_DETAIL_ISTREAM_OPERATOR(is, param_type, parm) 78 { 79 double p_in; 80 if(is >> p_in) { 81 if(p_in > RealType(0) && p_in < RealType(1)) { 82 parm._p = p_in; 83 } else { 84 is.setstate(std::ios_base::failbit); 85 } 86 } 87 return is; 88 } 89 90 /** Returns true if the two sets of parameters are equal. */ BOOST_RANDOM_DETAIL_EQUALITY_OPERATOR(param_type,lhs,rhs)91 BOOST_RANDOM_DETAIL_EQUALITY_OPERATOR(param_type, lhs, rhs) 92 { return lhs._p == rhs._p; } 93 94 /** Returns true if the two sets of parameters are different. */ 95 BOOST_RANDOM_DETAIL_INEQUALITY_OPERATOR(param_type) 96 97 98 private: 99 RealType _p; 100 }; 101 102 /** 103 * Contructs a new geometric_distribution with the paramter @c p. 104 * 105 * Requires: 0 < p < 1 106 */ geometric_distribution(const RealType & p_arg=RealType (0.5))107 explicit geometric_distribution(const RealType& p_arg = RealType(0.5)) 108 : _p(p_arg) 109 { 110 BOOST_ASSERT(RealType(0) < _p && _p < RealType(1)); 111 init(); 112 } 113 114 /** Constructs a new geometric_distribution from its parameters. */ geometric_distribution(const param_type & parm)115 explicit geometric_distribution(const param_type& parm) 116 : _p(parm.p()) 117 { 118 init(); 119 } 120 121 // compiler-generated copy ctor and assignment operator are fine 122 123 /** Returns: the distribution parameter @c p */ p() const124 RealType p() const { return _p; } 125 126 /** Returns the smallest value that the distribution can produce. */ BOOST_PREVENT_MACRO_SUBSTITUTION() const127 IntType min BOOST_PREVENT_MACRO_SUBSTITUTION () const { return IntType(0); } 128 129 /** Returns the largest value that the distribution can produce. */ BOOST_PREVENT_MACRO_SUBSTITUTION() const130 IntType max BOOST_PREVENT_MACRO_SUBSTITUTION () const 131 { return (std::numeric_limits<IntType>::max)(); } 132 133 /** Returns the parameters of the distribution. */ param() const134 param_type param() const { return param_type(_p); } 135 136 /** Sets the parameters of the distribution. */ param(const param_type & parm)137 void param(const param_type& parm) 138 { 139 _p = parm.p(); 140 init(); 141 } 142 143 /** 144 * Effects: Subsequent uses of the distribution do not depend 145 * on values produced by any engine prior to invoking reset. 146 */ reset()147 void reset() { } 148 149 /** 150 * Returns a random variate distributed according to the 151 * geometric_distribution. 152 */ 153 template<class Engine> operator ()(Engine & eng) const154 result_type operator()(Engine& eng) const 155 { 156 using std::log; 157 using std::floor; 158 RealType x = RealType(1) - boost::uniform_01<RealType>()(eng); 159 return IntType(floor(log(x) / _log_1mp)); 160 } 161 162 /** 163 * Returns a random variate distributed according to the 164 * geometric distribution with parameters specified by param. 165 */ 166 template<class Engine> operator ()(Engine & eng,const param_type & parm) const167 result_type operator()(Engine& eng, const param_type& parm) const 168 { return geometric_distribution(parm)(eng); } 169 170 /** Writes the distribution to a @c std::ostream. */ BOOST_RANDOM_DETAIL_OSTREAM_OPERATOR(os,geometric_distribution,gd)171 BOOST_RANDOM_DETAIL_OSTREAM_OPERATOR(os, geometric_distribution, gd) 172 { 173 os << gd._p; 174 return os; 175 } 176 177 /** Reads the distribution from a @c std::istream. */ BOOST_RANDOM_DETAIL_ISTREAM_OPERATOR(is,geometric_distribution,gd)178 BOOST_RANDOM_DETAIL_ISTREAM_OPERATOR(is, geometric_distribution, gd) 179 { 180 param_type parm; 181 if(is >> parm) { 182 gd.param(parm); 183 } 184 return is; 185 } 186 187 /** 188 * Returns true if the two distributions will produce identical 189 * sequences of values given equal generators. 190 */ BOOST_RANDOM_DETAIL_EQUALITY_OPERATOR(geometric_distribution,lhs,rhs)191 BOOST_RANDOM_DETAIL_EQUALITY_OPERATOR(geometric_distribution, lhs, rhs) 192 { return lhs._p == rhs._p; } 193 194 /** 195 * Returns true if the two distributions may produce different 196 * sequences of values given equal generators. 197 */ 198 BOOST_RANDOM_DETAIL_INEQUALITY_OPERATOR(geometric_distribution) 199 200 private: 201 202 /// \cond show_private 203 init()204 void init() 205 { 206 using std::log; 207 _log_1mp = log(1 - _p); 208 } 209 210 RealType _p; 211 RealType _log_1mp; 212 213 /// \endcond 214 }; 215 216 } // namespace random 217 218 /// \cond show_deprecated 219 220 /** 221 * Provided for backwards compatibility. This class is 222 * deprecated. It provides the old behavior of geometric_distribution 223 * with \f$p(i) = (1-p) p^{i-1}\f$. 224 */ 225 template<class IntType = int, class RealType = double> 226 class geometric_distribution 227 { 228 public: 229 typedef RealType input_type; 230 typedef IntType result_type; 231 geometric_distribution(RealType p_arg=RealType (0.5))232 explicit geometric_distribution(RealType p_arg = RealType(0.5)) 233 : _impl(1 - p_arg) {} 234 p() const235 RealType p() const { return 1 - _impl.p(); } 236 reset()237 void reset() {} 238 239 template<class Engine> operator ()(Engine & eng) const240 IntType operator()(Engine& eng) const { return _impl(eng) + IntType(1); } 241 BOOST_RANDOM_DETAIL_OSTREAM_OPERATOR(os,geometric_distribution,gd)242 BOOST_RANDOM_DETAIL_OSTREAM_OPERATOR(os, geometric_distribution, gd) 243 { 244 os << gd.p(); 245 return os; 246 } 247 BOOST_RANDOM_DETAIL_ISTREAM_OPERATOR(is,geometric_distribution,gd)248 BOOST_RANDOM_DETAIL_ISTREAM_OPERATOR(is, geometric_distribution, gd) 249 { 250 RealType val; 251 if(is >> val) { 252 typename impl_type::param_type impl_param(1 - val); 253 gd._impl.param(impl_param); 254 } 255 return is; 256 } 257 258 private: 259 typedef random::geometric_distribution<IntType, RealType> impl_type; 260 impl_type _impl; 261 }; 262 263 /// \endcond 264 265 } // namespace boost 266 267 #endif // BOOST_RANDOM_GEOMETRIC_DISTRIBUTION_HPP 268