1 /* boost random/negative_binomial_distribution.hpp header file 2 * 3 * Copyright Steven Watanabe 2010 4 * Distributed under the Boost Software License, Version 1.0. (See 5 * accompanying file LICENSE_1_0.txt or copy at 6 * http://www.boost.org/LICENSE_1_0.txt) 7 * 8 * See http://www.boost.org for most recent version including documentation. 9 * 10 * $Id$ 11 */ 12 13 #ifndef BOOST_RANDOM_NEGATIVE_BINOMIAL_DISTRIBUTION_HPP_INCLUDED 14 #define BOOST_RANDOM_NEGATIVE_BINOMIAL_DISTRIBUTION_HPP_INCLUDED 15 16 #include <iosfwd> 17 18 #include <boost/limits.hpp> 19 #include <boost/random/detail/config.hpp> 20 #include <boost/random/gamma_distribution.hpp> 21 #include <boost/random/poisson_distribution.hpp> 22 23 namespace boost { 24 namespace random { 25 26 /** 27 * The negative binomial distribution is an integer valued 28 * distribution with two parameters, @c k and @c p. The 29 * distribution produces non-negative values. 30 * 31 * The distribution function is 32 * \f$\displaystyle P(i) = {k+i-1\choose i}p^k(1-p)^i\f$. 33 * 34 * This implementation uses a gamma-poisson mixture. 35 */ 36 template<class IntType = int, class RealType = double> 37 class negative_binomial_distribution { 38 public: 39 typedef IntType result_type; 40 typedef RealType input_type; 41 42 class param_type { 43 public: 44 typedef negative_binomial_distribution distribution_type; 45 /** 46 * Construct a param_type object. @c k and @c p 47 * are the parameters of the distribution. 48 * 49 * Requires: k >=0 && 0 <= p <= 1 50 */ param_type(IntType k_arg=1,RealType p_arg=RealType (0.5))51 explicit param_type(IntType k_arg = 1, RealType p_arg = RealType (0.5)) 52 : _k(k_arg), _p(p_arg) 53 {} 54 /** Returns the @c k parameter of the distribution. */ k() const55 IntType k() const { return _k; } 56 /** Returns the @c p parameter of the distribution. */ p() const57 RealType p() const { return _p; } 58 #ifndef BOOST_RANDOM_NO_STREAM_OPERATORS 59 /** Writes the parameters of the distribution to a @c std::ostream. */ 60 template<class CharT, class Traits> 61 friend std::basic_ostream<CharT,Traits>& operator <<(std::basic_ostream<CharT,Traits> & os,const param_type & parm)62 operator<<(std::basic_ostream<CharT,Traits>& os, 63 const param_type& parm) 64 { 65 os << parm._p << " " << parm._k; 66 return os; 67 } 68 69 /** Reads the parameters of the distribution from a @c std::istream. */ 70 template<class CharT, class Traits> 71 friend std::basic_istream<CharT,Traits>& operator >>(std::basic_istream<CharT,Traits> & is,param_type & parm)72 operator>>(std::basic_istream<CharT,Traits>& is, param_type& parm) 73 { 74 is >> parm._p >> std::ws >> parm._k; 75 return is; 76 } 77 #endif 78 /** Returns true if the parameters have the same values. */ operator ==(const param_type & lhs,const param_type & rhs)79 friend bool operator==(const param_type& lhs, const param_type& rhs) 80 { 81 return lhs._k == rhs._k && lhs._p == rhs._p; 82 } 83 /** Returns true if the parameters have different values. */ operator !=(const param_type & lhs,const param_type & rhs)84 friend bool operator!=(const param_type& lhs, const param_type& rhs) 85 { 86 return !(lhs == rhs); 87 } 88 private: 89 IntType _k; 90 RealType _p; 91 }; 92 93 /** 94 * Construct a @c negative_binomial_distribution object. @c k and @c p 95 * are the parameters of the distribution. 96 * 97 * Requires: k >=0 && 0 <= p <= 1 98 */ negative_binomial_distribution(IntType k_arg=1,RealType p_arg=RealType (0.5))99 explicit negative_binomial_distribution(IntType k_arg = 1, 100 RealType p_arg = RealType(0.5)) 101 : _k(k_arg), _p(p_arg) 102 {} 103 104 /** 105 * Construct an @c negative_binomial_distribution object from the 106 * parameters. 107 */ negative_binomial_distribution(const param_type & parm)108 explicit negative_binomial_distribution(const param_type& parm) 109 : _k(parm.k()), _p(parm.p()) 110 {} 111 112 /** 113 * Returns a random variate distributed according to the 114 * negative binomial distribution. 115 */ 116 template<class URNG> operator ()(URNG & urng) const117 IntType operator()(URNG& urng) const 118 { 119 gamma_distribution<RealType> gamma(_k, (1-_p)/_p); 120 poisson_distribution<IntType, RealType> poisson(gamma(urng)); 121 return poisson(urng); 122 } 123 124 /** 125 * Returns a random variate distributed according to the negative 126 * binomial distribution with parameters specified by @c param. 127 */ 128 template<class URNG> operator ()(URNG & urng,const param_type & parm) const129 IntType operator()(URNG& urng, const param_type& parm) const 130 { 131 return negative_binomial_distribution(parm)(urng); 132 } 133 134 /** Returns the @c k parameter of the distribution. */ k() const135 IntType k() const { return _k; } 136 /** Returns the @c p parameter of the distribution. */ p() const137 RealType p() const { return _p; } 138 139 /** Returns the smallest value that the distribution can produce. */ BOOST_PREVENT_MACRO_SUBSTITUTION() const140 IntType min BOOST_PREVENT_MACRO_SUBSTITUTION() const { return 0; } 141 /** Returns the largest value that the distribution can produce. */ BOOST_PREVENT_MACRO_SUBSTITUTION() const142 IntType max BOOST_PREVENT_MACRO_SUBSTITUTION() const 143 { return (std::numeric_limits<IntType>::max)(); } 144 145 /** Returns the parameters of the distribution. */ param() const146 param_type param() const { return param_type(_k, _p); } 147 /** Sets parameters of the distribution. */ param(const param_type & parm)148 void param(const param_type& parm) 149 { 150 _k = parm.k(); 151 _p = parm.p(); 152 } 153 154 /** 155 * Effects: Subsequent uses of the distribution do not depend 156 * on values produced by any engine prior to invoking reset. 157 */ reset()158 void reset() { } 159 160 #ifndef BOOST_RANDOM_NO_STREAM_OPERATORS 161 /** Writes the parameters of the distribution to a @c std::ostream. */ 162 template<class CharT, class Traits> 163 friend std::basic_ostream<CharT,Traits>& operator <<(std::basic_ostream<CharT,Traits> & os,const negative_binomial_distribution & bd)164 operator<<(std::basic_ostream<CharT,Traits>& os, 165 const negative_binomial_distribution& bd) 166 { 167 os << bd.param(); 168 return os; 169 } 170 171 /** Reads the parameters of the distribution from a @c std::istream. */ 172 template<class CharT, class Traits> 173 friend std::basic_istream<CharT,Traits>& operator >>(std::basic_istream<CharT,Traits> & is,negative_binomial_distribution & bd)174 operator>>(std::basic_istream<CharT,Traits>& is, 175 negative_binomial_distribution& bd) 176 { 177 bd.read(is); 178 return is; 179 } 180 #endif 181 182 /** Returns true if the two distributions will produce the same 183 sequence of values, given equal generators. */ operator ==(const negative_binomial_distribution & lhs,const negative_binomial_distribution & rhs)184 friend bool operator==(const negative_binomial_distribution& lhs, 185 const negative_binomial_distribution& rhs) 186 { 187 return lhs._k == rhs._k && lhs._p == rhs._p; 188 } 189 /** Returns true if the two distributions could produce different 190 sequences of values, given equal generators. */ operator !=(const negative_binomial_distribution & lhs,const negative_binomial_distribution & rhs)191 friend bool operator!=(const negative_binomial_distribution& lhs, 192 const negative_binomial_distribution& rhs) 193 { 194 return !(lhs == rhs); 195 } 196 197 private: 198 199 /// @cond \show_private 200 201 template<class CharT, class Traits> read(std::basic_istream<CharT,Traits> & is)202 void read(std::basic_istream<CharT, Traits>& is) { 203 param_type parm; 204 if(is >> parm) { 205 param(parm); 206 } 207 } 208 209 // parameters 210 IntType _k; 211 RealType _p; 212 213 /// @endcond 214 }; 215 216 } 217 218 } 219 220 #endif 221