1 // Copyright 2008 Gautam Sewani 2 // 3 // Use, modification and distribution are subject to the 4 // Boost Software License, Version 1.0. 5 // (See accompanying file LICENSE_1_0.txt 6 // or copy at http://www.boost.org/LICENSE_1_0.txt) 7 8 #ifndef BOOST_MATH_DISTRIBUTIONS_LOGISTIC 9 #define BOOST_MATH_DISTRIBUTIONS_LOGISTIC 10 11 #include <boost/math/distributions/fwd.hpp> 12 #include <boost/math/distributions/detail/common_error_handling.hpp> 13 #include <boost/math/distributions/complement.hpp> 14 #include <boost/math/special_functions/log1p.hpp> 15 #include <boost/math/constants/constants.hpp> 16 #include <utility> 17 18 namespace boost { namespace math { 19 20 template <class RealType = double, class Policy = policies::policy<> > 21 class logistic_distribution 22 { 23 public: 24 typedef RealType value_type; 25 typedef Policy policy_type; 26 logistic_distribution(RealType l_location=0,RealType l_scale=1)27 logistic_distribution(RealType l_location=0, RealType l_scale=1) // Constructor. 28 : m_location(l_location), m_scale(l_scale) 29 { 30 static const char* function = "boost::math::logistic_distribution<%1%>::logistic_distribution"; 31 32 RealType result; 33 detail::check_scale(function, l_scale, &result, Policy()); 34 detail::check_location(function, l_location, &result, Policy()); 35 } 36 // Accessor functions. scale() const37 RealType scale()const 38 { 39 return m_scale; 40 } 41 location() const42 RealType location()const 43 { 44 return m_location; 45 } 46 private: 47 // Data members: 48 RealType m_location; // distribution location aka mu. 49 RealType m_scale; // distribution scale aka s. 50 }; // class logistic_distribution 51 52 53 typedef logistic_distribution<double> logistic; 54 55 template <class RealType, class Policy> range(const logistic_distribution<RealType,Policy> &)56 inline const std::pair<RealType, RealType> range(const logistic_distribution<RealType, Policy>& /* dist */) 57 { // Range of permissible values for random variable x. 58 using boost::math::tools::max_value; 59 return std::pair<RealType, RealType>( 60 std::numeric_limits<RealType>::has_infinity ? -std::numeric_limits<RealType>::infinity() : -max_value<RealType>(), 61 std::numeric_limits<RealType>::has_infinity ? std::numeric_limits<RealType>::infinity() : max_value<RealType>()); 62 } 63 64 template <class RealType, class Policy> support(const logistic_distribution<RealType,Policy> &)65 inline const std::pair<RealType, RealType> support(const logistic_distribution<RealType, Policy>& /* dist */) 66 { // Range of supported values for random variable x. 67 // This is range where cdf rises from 0 to 1, and outside it, the pdf is zero. 68 using boost::math::tools::max_value; 69 return std::pair<RealType, RealType>(-max_value<RealType>(), max_value<RealType>()); // - to + infinity 70 } 71 72 template <class RealType, class Policy> pdf(const logistic_distribution<RealType,Policy> & dist,const RealType & x)73 inline RealType pdf(const logistic_distribution<RealType, Policy>& dist, const RealType& x) 74 { 75 static const char* function = "boost::math::pdf(const logistic_distribution<%1%>&, %1%)"; 76 RealType scale = dist.scale(); 77 RealType location = dist.location(); 78 RealType result = 0; 79 80 if(false == detail::check_scale(function, scale , &result, Policy())) 81 { 82 return result; 83 } 84 if(false == detail::check_location(function, location, &result, Policy())) 85 { 86 return result; 87 } 88 89 if((boost::math::isinf)(x)) 90 { 91 return 0; // pdf + and - infinity is zero. 92 } 93 94 if(false == detail::check_x(function, x, &result, Policy())) 95 { 96 return result; 97 } 98 99 BOOST_MATH_STD_USING 100 RealType exp_term = (location - x) / scale; 101 if(fabs(exp_term) > tools::log_max_value<RealType>()) 102 return 0; 103 exp_term = exp(exp_term); 104 if((exp_term * scale > 1) && (exp_term > tools::max_value<RealType>() / (scale * exp_term))) 105 return 1 / (scale * exp_term); 106 return (exp_term) / (scale * (1 + exp_term) * (1 + exp_term)); 107 } 108 109 template <class RealType, class Policy> cdf(const logistic_distribution<RealType,Policy> & dist,const RealType & x)110 inline RealType cdf(const logistic_distribution<RealType, Policy>& dist, const RealType& x) 111 { 112 RealType scale = dist.scale(); 113 RealType location = dist.location(); 114 RealType result = 0; // of checks. 115 static const char* function = "boost::math::cdf(const logistic_distribution<%1%>&, %1%)"; 116 if(false == detail::check_scale(function, scale, &result, Policy())) 117 { 118 return result; 119 } 120 if(false == detail::check_location(function, location, &result, Policy())) 121 { 122 return result; 123 } 124 125 if((boost::math::isinf)(x)) 126 { 127 if(x < 0) return 0; // -infinity 128 return 1; // + infinity 129 } 130 131 if(false == detail::check_x(function, x, &result, Policy())) 132 { 133 return result; 134 } 135 BOOST_MATH_STD_USING 136 RealType power = (location - x) / scale; 137 if(power > tools::log_max_value<RealType>()) 138 return 0; 139 if(power < -tools::log_max_value<RealType>()) 140 return 1; 141 return 1 / (1 + exp(power)); 142 } 143 144 template <class RealType, class Policy> quantile(const logistic_distribution<RealType,Policy> & dist,const RealType & p)145 inline RealType quantile(const logistic_distribution<RealType, Policy>& dist, const RealType& p) 146 { 147 BOOST_MATH_STD_USING 148 RealType location = dist.location(); 149 RealType scale = dist.scale(); 150 151 static const char* function = "boost::math::quantile(const logistic_distribution<%1%>&, %1%)"; 152 153 RealType result = 0; 154 if(false == detail::check_scale(function, scale, &result, Policy())) 155 return result; 156 if(false == detail::check_location(function, location, &result, Policy())) 157 return result; 158 if(false == detail::check_probability(function, p, &result, Policy())) 159 return result; 160 161 if(p == 0) 162 { 163 return -policies::raise_overflow_error<RealType>(function,"probability argument is 0, must be >0 and <1",Policy()); 164 } 165 if(p == 1) 166 { 167 return policies::raise_overflow_error<RealType>(function,"probability argument is 1, must be >0 and <1",Policy()); 168 } 169 //Expressions to try 170 //return location+scale*log(p/(1-p)); 171 //return location+scale*log1p((2*p-1)/(1-p)); 172 173 //return location - scale*log( (1-p)/p); 174 //return location - scale*log1p((1-2*p)/p); 175 176 //return -scale*log(1/p-1) + location; 177 return location - scale * log((1 - p) / p); 178 } // RealType quantile(const logistic_distribution<RealType, Policy>& dist, const RealType& p) 179 180 template <class RealType, class Policy> cdf(const complemented2_type<logistic_distribution<RealType,Policy>,RealType> & c)181 inline RealType cdf(const complemented2_type<logistic_distribution<RealType, Policy>, RealType>& c) 182 { 183 BOOST_MATH_STD_USING 184 RealType location = c.dist.location(); 185 RealType scale = c.dist.scale(); 186 RealType x = c.param; 187 static const char* function = "boost::math::cdf(const complement(logistic_distribution<%1%>&), %1%)"; 188 189 RealType result = 0; 190 if(false == detail::check_scale(function, scale, &result, Policy())) 191 { 192 return result; 193 } 194 if(false == detail::check_location(function, location, &result, Policy())) 195 { 196 return result; 197 } 198 if((boost::math::isinf)(x)) 199 { 200 if(x < 0) return 1; // cdf complement -infinity is unity. 201 return 0; // cdf complement +infinity is zero. 202 } 203 if(false == detail::check_x(function, x, &result, Policy())) 204 { 205 return result; 206 } 207 RealType power = (x - location) / scale; 208 if(power > tools::log_max_value<RealType>()) 209 return 0; 210 if(power < -tools::log_max_value<RealType>()) 211 return 1; 212 return 1 / (1 + exp(power)); 213 } 214 215 template <class RealType, class Policy> quantile(const complemented2_type<logistic_distribution<RealType,Policy>,RealType> & c)216 inline RealType quantile(const complemented2_type<logistic_distribution<RealType, Policy>, RealType>& c) 217 { 218 BOOST_MATH_STD_USING 219 RealType scale = c.dist.scale(); 220 RealType location = c.dist.location(); 221 static const char* function = "boost::math::quantile(const complement(logistic_distribution<%1%>&), %1%)"; 222 RealType result = 0; 223 if(false == detail::check_scale(function, scale, &result, Policy())) 224 return result; 225 if(false == detail::check_location(function, location, &result, Policy())) 226 return result; 227 RealType q = c.param; 228 if(false == detail::check_probability(function, q, &result, Policy())) 229 return result; 230 using boost::math::tools::max_value; 231 232 if(q == 1) 233 { 234 return -policies::raise_overflow_error<RealType>(function,"probability argument is 1, but must be >0 and <1",Policy()); 235 } 236 if(q == 0) 237 { 238 return policies::raise_overflow_error<RealType>(function,"probability argument is 0, but must be >0 and <1",Policy()); 239 } 240 //Expressions to try 241 //return location+scale*log((1-q)/q); 242 return location + scale * log((1 - q) / q); 243 244 //return location-scale*log(q/(1-q)); 245 //return location-scale*log1p((2*q-1)/(1-q)); 246 247 //return location+scale*log(1/q-1); 248 //return location+scale*log1p(1/q-2); 249 } 250 251 template <class RealType, class Policy> mean(const logistic_distribution<RealType,Policy> & dist)252 inline RealType mean(const logistic_distribution<RealType, Policy>& dist) 253 { 254 return dist.location(); 255 } // RealType mean(const logistic_distribution<RealType, Policy>& dist) 256 257 template <class RealType, class Policy> variance(const logistic_distribution<RealType,Policy> & dist)258 inline RealType variance(const logistic_distribution<RealType, Policy>& dist) 259 { 260 BOOST_MATH_STD_USING 261 RealType scale = dist.scale(); 262 return boost::math::constants::pi<RealType>()*boost::math::constants::pi<RealType>()*scale*scale/3; 263 } // RealType variance(const logistic_distribution<RealType, Policy>& dist) 264 265 template <class RealType, class Policy> mode(const logistic_distribution<RealType,Policy> & dist)266 inline RealType mode(const logistic_distribution<RealType, Policy>& dist) 267 { 268 return dist.location(); 269 } 270 271 template <class RealType, class Policy> median(const logistic_distribution<RealType,Policy> & dist)272 inline RealType median(const logistic_distribution<RealType, Policy>& dist) 273 { 274 return dist.location(); 275 } 276 template <class RealType, class Policy> skewness(const logistic_distribution<RealType,Policy> &)277 inline RealType skewness(const logistic_distribution<RealType, Policy>& /*dist*/) 278 { 279 return 0; 280 } // RealType skewness(const logistic_distribution<RealType, Policy>& dist) 281 282 template <class RealType, class Policy> kurtosis_excess(const logistic_distribution<RealType,Policy> &)283 inline RealType kurtosis_excess(const logistic_distribution<RealType, Policy>& /*dist*/) 284 { 285 return static_cast<RealType>(6)/5; 286 } // RealType kurtosis_excess(const logistic_distribution<RealType, Policy>& dist) 287 288 template <class RealType, class Policy> kurtosis(const logistic_distribution<RealType,Policy> & dist)289 inline RealType kurtosis(const logistic_distribution<RealType, Policy>& dist) 290 { 291 return kurtosis_excess(dist) + 3; 292 } // RealType kurtosis_excess(const logistic_distribution<RealType, Policy>& dist) 293 294 template <class RealType, class Policy> entropy(const logistic_distribution<RealType,Policy> & dist)295 inline RealType entropy(const logistic_distribution<RealType, Policy>& dist) 296 { 297 using std::log; 298 return 2 + log(dist.scale()); 299 } 300 }} 301 302 303 // Must come at the end: 304 #include <boost/math/distributions/detail/derived_accessors.hpp> 305 306 #endif // BOOST_MATH_DISTRIBUTIONS_LOGISTIC 307