1 // Copyright John Maddock 2006. 2 // Copyright Paul A. Bristow 2006. 3 // Use, modification and distribution are subject to the 4 // Boost Software License, Version 1.0. (See accompanying file 5 // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) 6 7 // TODO deal with infinity as special better - or remove. 8 // 9 10 #ifndef BOOST_STATS_UNIFORM_HPP 11 #define BOOST_STATS_UNIFORM_HPP 12 13 // http://www.itl.nist.gov/div898/handbook/eda/section3/eda3668.htm 14 // http://mathworld.wolfram.com/UniformDistribution.html 15 // http://documents.wolfram.com/calculationcenter/v2/Functions/ListsMatrices/Statistics/UniformDistribution.html 16 // http://en.wikipedia.org/wiki/Uniform_distribution_%28continuous%29 17 18 #include <boost/math/distributions/fwd.hpp> 19 #include <boost/math/distributions/detail/common_error_handling.hpp> 20 #include <boost/math/distributions/complement.hpp> 21 22 #include <utility> 23 24 namespace boost{ namespace math 25 { 26 namespace detail 27 { 28 template <class RealType, class Policy> check_uniform_lower(const char * function,RealType lower,RealType * result,const Policy & pol)29 inline bool check_uniform_lower( 30 const char* function, 31 RealType lower, 32 RealType* result, const Policy& pol) 33 { 34 if((boost::math::isfinite)(lower)) 35 { // any finite value is OK. 36 return true; 37 } 38 else 39 { // Not finite. 40 *result = policies::raise_domain_error<RealType>( 41 function, 42 "Lower parameter is %1%, but must be finite!", lower, pol); 43 return false; 44 } 45 } // bool check_uniform_lower( 46 47 template <class RealType, class Policy> check_uniform_upper(const char * function,RealType upper,RealType * result,const Policy & pol)48 inline bool check_uniform_upper( 49 const char* function, 50 RealType upper, 51 RealType* result, const Policy& pol) 52 { 53 if((boost::math::isfinite)(upper)) 54 { // Any finite value is OK. 55 return true; 56 } 57 else 58 { // Not finite. 59 *result = policies::raise_domain_error<RealType>( 60 function, 61 "Upper parameter is %1%, but must be finite!", upper, pol); 62 return false; 63 } 64 } // bool check_uniform_upper( 65 66 template <class RealType, class Policy> check_uniform_x(const char * function,RealType const & x,RealType * result,const Policy & pol)67 inline bool check_uniform_x( 68 const char* function, 69 RealType const& x, 70 RealType* result, const Policy& pol) 71 { 72 if((boost::math::isfinite)(x)) 73 { // Any finite value is OK 74 return true; 75 } 76 else 77 { // Not finite.. 78 *result = policies::raise_domain_error<RealType>( 79 function, 80 "x parameter is %1%, but must be finite!", x, pol); 81 return false; 82 } 83 } // bool check_uniform_x 84 85 template <class RealType, class Policy> check_uniform(const char * function,RealType lower,RealType upper,RealType * result,const Policy & pol)86 inline bool check_uniform( 87 const char* function, 88 RealType lower, 89 RealType upper, 90 RealType* result, const Policy& pol) 91 { 92 if((check_uniform_lower(function, lower, result, pol) == false) 93 || (check_uniform_upper(function, upper, result, pol) == false)) 94 { 95 return false; 96 } 97 else if (lower >= upper) // If lower == upper then 1 / (upper-lower) = 1/0 = +infinity! 98 { // upper and lower have been checked before, so must be lower >= upper. 99 *result = policies::raise_domain_error<RealType>( 100 function, 101 "lower parameter is %1%, but must be less than upper!", lower, pol); 102 return false; 103 } 104 else 105 { // All OK, 106 return true; 107 } 108 } // bool check_uniform( 109 110 } // namespace detail 111 112 template <class RealType = double, class Policy = policies::policy<> > 113 class uniform_distribution 114 { 115 public: 116 typedef RealType value_type; 117 typedef Policy policy_type; 118 uniform_distribution(RealType l_lower=0,RealType l_upper=1)119 uniform_distribution(RealType l_lower = 0, RealType l_upper = 1) // Constructor. 120 : m_lower(l_lower), m_upper(l_upper) // Default is standard uniform distribution. 121 { 122 RealType result; 123 detail::check_uniform("boost::math::uniform_distribution<%1%>::uniform_distribution", l_lower, l_upper, &result, Policy()); 124 } 125 // Accessor functions. lower() const126 RealType lower()const 127 { 128 return m_lower; 129 } 130 upper() const131 RealType upper()const 132 { 133 return m_upper; 134 } 135 private: 136 // Data members: 137 RealType m_lower; // distribution lower aka a. 138 RealType m_upper; // distribution upper aka b. 139 }; // class uniform_distribution 140 141 typedef uniform_distribution<double> uniform; 142 143 template <class RealType, class Policy> range(const uniform_distribution<RealType,Policy> &)144 inline const std::pair<RealType, RealType> range(const uniform_distribution<RealType, Policy>& /* dist */) 145 { // Range of permissible values for random variable x. 146 using boost::math::tools::max_value; 147 return std::pair<RealType, RealType>(-max_value<RealType>(), max_value<RealType>()); // - to + 'infinity'. 148 // Note RealType infinity is NOT permitted, only max_value. 149 } 150 151 template <class RealType, class Policy> support(const uniform_distribution<RealType,Policy> & dist)152 inline const std::pair<RealType, RealType> support(const uniform_distribution<RealType, Policy>& dist) 153 { // Range of supported values for random variable x. 154 // This is range where cdf rises from 0 to 1, and outside it, the pdf is zero. 155 using boost::math::tools::max_value; 156 return std::pair<RealType, RealType>(dist.lower(), dist.upper()); 157 } 158 159 template <class RealType, class Policy> pdf(const uniform_distribution<RealType,Policy> & dist,const RealType & x)160 inline RealType pdf(const uniform_distribution<RealType, Policy>& dist, const RealType& x) 161 { 162 RealType lower = dist.lower(); 163 RealType upper = dist.upper(); 164 RealType result = 0; // of checks. 165 if(false == detail::check_uniform("boost::math::pdf(const uniform_distribution<%1%>&, %1%)", lower, upper, &result, Policy())) 166 { 167 return result; 168 } 169 if(false == detail::check_uniform_x("boost::math::pdf(const uniform_distribution<%1%>&, %1%)", x, &result, Policy())) 170 { 171 return result; 172 } 173 174 if((x < lower) || (x > upper) ) 175 { 176 return 0; 177 } 178 else 179 { 180 return 1 / (upper - lower); 181 } 182 } // RealType pdf(const uniform_distribution<RealType, Policy>& dist, const RealType& x) 183 184 template <class RealType, class Policy> cdf(const uniform_distribution<RealType,Policy> & dist,const RealType & x)185 inline RealType cdf(const uniform_distribution<RealType, Policy>& dist, const RealType& x) 186 { 187 RealType lower = dist.lower(); 188 RealType upper = dist.upper(); 189 RealType result = 0; // of checks. 190 if(false == detail::check_uniform("boost::math::cdf(const uniform_distribution<%1%>&, %1%)",lower, upper, &result, Policy())) 191 { 192 return result; 193 } 194 if(false == detail::check_uniform_x("boost::math::cdf(const uniform_distribution<%1%>&, %1%)", x, &result, Policy())) 195 { 196 return result; 197 } 198 if (x < lower) 199 { 200 return 0; 201 } 202 if (x > upper) 203 { 204 return 1; 205 } 206 return (x - lower) / (upper - lower); // lower <= x <= upper 207 } // RealType cdf(const uniform_distribution<RealType, Policy>& dist, const RealType& x) 208 209 template <class RealType, class Policy> quantile(const uniform_distribution<RealType,Policy> & dist,const RealType & p)210 inline RealType quantile(const uniform_distribution<RealType, Policy>& dist, const RealType& p) 211 { 212 RealType lower = dist.lower(); 213 RealType upper = dist.upper(); 214 RealType result = 0; // of checks 215 if(false == detail::check_uniform("boost::math::quantile(const uniform_distribution<%1%>&, %1%)",lower, upper, &result, Policy())) 216 { 217 return result; 218 } 219 if(false == detail::check_probability("boost::math::quantile(const uniform_distribution<%1%>&, %1%)", p, &result, Policy())) 220 { 221 return result; 222 } 223 if(p == 0) 224 { 225 return lower; 226 } 227 if(p == 1) 228 { 229 return upper; 230 } 231 return p * (upper - lower) + lower; 232 } // RealType quantile(const uniform_distribution<RealType, Policy>& dist, const RealType& p) 233 234 template <class RealType, class Policy> cdf(const complemented2_type<uniform_distribution<RealType,Policy>,RealType> & c)235 inline RealType cdf(const complemented2_type<uniform_distribution<RealType, Policy>, RealType>& c) 236 { 237 RealType lower = c.dist.lower(); 238 RealType upper = c.dist.upper(); 239 RealType x = c.param; 240 RealType result = 0; // of checks. 241 if(false == detail::check_uniform("boost::math::cdf(const uniform_distribution<%1%>&, %1%)", lower, upper, &result, Policy())) 242 { 243 return result; 244 } 245 if(false == detail::check_uniform_x("boost::math::cdf(const uniform_distribution<%1%>&, %1%)", x, &result, Policy())) 246 { 247 return result; 248 } 249 if (x < lower) 250 { 251 return 1; 252 } 253 if (x > upper) 254 { 255 return 0; 256 } 257 return (upper - x) / (upper - lower); 258 } // RealType cdf(const complemented2_type<uniform_distribution<RealType, Policy>, RealType>& c) 259 260 template <class RealType, class Policy> quantile(const complemented2_type<uniform_distribution<RealType,Policy>,RealType> & c)261 inline RealType quantile(const complemented2_type<uniform_distribution<RealType, Policy>, RealType>& c) 262 { 263 RealType lower = c.dist.lower(); 264 RealType upper = c.dist.upper(); 265 RealType q = c.param; 266 RealType result = 0; // of checks. 267 if(false == detail::check_uniform("boost::math::quantile(const uniform_distribution<%1%>&, %1%)", lower, upper, &result, Policy())) 268 { 269 return result; 270 } 271 if(false == detail::check_probability("boost::math::quantile(const uniform_distribution<%1%>&, %1%)", q, &result, Policy())) 272 { 273 return result; 274 } 275 if(q == 0) 276 { 277 return upper; 278 } 279 if(q == 1) 280 { 281 return lower; 282 } 283 return -q * (upper - lower) + upper; 284 } // RealType quantile(const complemented2_type<uniform_distribution<RealType, Policy>, RealType>& c) 285 286 template <class RealType, class Policy> mean(const uniform_distribution<RealType,Policy> & dist)287 inline RealType mean(const uniform_distribution<RealType, Policy>& dist) 288 { 289 RealType lower = dist.lower(); 290 RealType upper = dist.upper(); 291 RealType result = 0; // of checks. 292 if(false == detail::check_uniform("boost::math::mean(const uniform_distribution<%1%>&)", lower, upper, &result, Policy())) 293 { 294 return result; 295 } 296 return (lower + upper ) / 2; 297 } // RealType mean(const uniform_distribution<RealType, Policy>& dist) 298 299 template <class RealType, class Policy> variance(const uniform_distribution<RealType,Policy> & dist)300 inline RealType variance(const uniform_distribution<RealType, Policy>& dist) 301 { 302 RealType lower = dist.lower(); 303 RealType upper = dist.upper(); 304 RealType result = 0; // of checks. 305 if(false == detail::check_uniform("boost::math::variance(const uniform_distribution<%1%>&)", lower, upper, &result, Policy())) 306 { 307 return result; 308 } 309 return (upper - lower) * ( upper - lower) / 12; 310 // for standard uniform = 0.833333333333333333333333333333333333333333; 311 } // RealType variance(const uniform_distribution<RealType, Policy>& dist) 312 313 template <class RealType, class Policy> mode(const uniform_distribution<RealType,Policy> & dist)314 inline RealType mode(const uniform_distribution<RealType, Policy>& dist) 315 { 316 RealType lower = dist.lower(); 317 RealType upper = dist.upper(); 318 RealType result = 0; // of checks. 319 if(false == detail::check_uniform("boost::math::mode(const uniform_distribution<%1%>&)", lower, upper, &result, Policy())) 320 { 321 return result; 322 } 323 result = lower; // Any value [lower, upper] but arbitrarily choose lower. 324 return result; 325 } 326 327 template <class RealType, class Policy> median(const uniform_distribution<RealType,Policy> & dist)328 inline RealType median(const uniform_distribution<RealType, Policy>& dist) 329 { 330 RealType lower = dist.lower(); 331 RealType upper = dist.upper(); 332 RealType result = 0; // of checks. 333 if(false == detail::check_uniform("boost::math::median(const uniform_distribution<%1%>&)", lower, upper, &result, Policy())) 334 { 335 return result; 336 } 337 return (lower + upper) / 2; // 338 } 339 template <class RealType, class Policy> skewness(const uniform_distribution<RealType,Policy> & dist)340 inline RealType skewness(const uniform_distribution<RealType, Policy>& dist) 341 { 342 RealType lower = dist.lower(); 343 RealType upper = dist.upper(); 344 RealType result = 0; // of checks. 345 if(false == detail::check_uniform("boost::math::skewness(const uniform_distribution<%1%>&)",lower, upper, &result, Policy())) 346 { 347 return result; 348 } 349 return 0; 350 } // RealType skewness(const uniform_distribution<RealType, Policy>& dist) 351 352 template <class RealType, class Policy> kurtosis_excess(const uniform_distribution<RealType,Policy> & dist)353 inline RealType kurtosis_excess(const uniform_distribution<RealType, Policy>& dist) 354 { 355 RealType lower = dist.lower(); 356 RealType upper = dist.upper(); 357 RealType result = 0; // of checks. 358 if(false == detail::check_uniform("boost::math::kurtosis_execess(const uniform_distribution<%1%>&)", lower, upper, &result, Policy())) 359 { 360 return result; 361 } 362 return static_cast<RealType>(-6)/5; // -6/5 = -1.2; 363 } // RealType kurtosis_excess(const uniform_distribution<RealType, Policy>& dist) 364 365 template <class RealType, class Policy> kurtosis(const uniform_distribution<RealType,Policy> & dist)366 inline RealType kurtosis(const uniform_distribution<RealType, Policy>& dist) 367 { 368 return kurtosis_excess(dist) + 3; 369 } 370 371 template <class RealType, class Policy> entropy(const uniform_distribution<RealType,Policy> & dist)372 inline RealType entropy(const uniform_distribution<RealType, Policy>& dist) 373 { 374 using std::log; 375 return log(dist.upper() - dist.lower()); 376 } 377 378 } // namespace math 379 } // namespace boost 380 381 // This include must be at the end, *after* the accessors 382 // for this distribution have been defined, in order to 383 // keep compilers that support two-phase lookup happy. 384 #include <boost/math/distributions/detail/derived_accessors.hpp> 385 386 #endif // BOOST_STATS_UNIFORM_HPP 387 388 389 390