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 if(q == 0) 273 { 274 return lower; 275 } 276 if(q == 1) 277 { 278 return upper; 279 } 280 return -q * (upper - lower) + upper; 281 } // RealType quantile(const complemented2_type<uniform_distribution<RealType, Policy>, RealType>& c) 282 283 template <class RealType, class Policy> mean(const uniform_distribution<RealType,Policy> & dist)284 inline RealType mean(const uniform_distribution<RealType, Policy>& dist) 285 { 286 RealType lower = dist.lower(); 287 RealType upper = dist.upper(); 288 RealType result = 0; // of checks. 289 if(false == detail::check_uniform("boost::math::mean(const uniform_distribution<%1%>&)", lower, upper, &result, Policy())) 290 { 291 return result; 292 } 293 return (lower + upper ) / 2; 294 } // RealType mean(const uniform_distribution<RealType, Policy>& dist) 295 296 template <class RealType, class Policy> variance(const uniform_distribution<RealType,Policy> & dist)297 inline RealType variance(const uniform_distribution<RealType, Policy>& dist) 298 { 299 RealType lower = dist.lower(); 300 RealType upper = dist.upper(); 301 RealType result = 0; // of checks. 302 if(false == detail::check_uniform("boost::math::variance(const uniform_distribution<%1%>&)", lower, upper, &result, Policy())) 303 { 304 return result; 305 } 306 return (upper - lower) * ( upper - lower) / 12; 307 // for standard uniform = 0.833333333333333333333333333333333333333333; 308 } // RealType variance(const uniform_distribution<RealType, Policy>& dist) 309 310 template <class RealType, class Policy> mode(const uniform_distribution<RealType,Policy> & dist)311 inline RealType mode(const uniform_distribution<RealType, Policy>& dist) 312 { 313 RealType lower = dist.lower(); 314 RealType upper = dist.upper(); 315 RealType result = 0; // of checks. 316 if(false == detail::check_uniform("boost::math::mode(const uniform_distribution<%1%>&)", lower, upper, &result, Policy())) 317 { 318 return result; 319 } 320 result = lower; // Any value [lower, upper] but arbitrarily choose lower. 321 return result; 322 } 323 324 template <class RealType, class Policy> median(const uniform_distribution<RealType,Policy> & dist)325 inline RealType median(const uniform_distribution<RealType, Policy>& dist) 326 { 327 RealType lower = dist.lower(); 328 RealType upper = dist.upper(); 329 RealType result = 0; // of checks. 330 if(false == detail::check_uniform("boost::math::median(const uniform_distribution<%1%>&)", lower, upper, &result, Policy())) 331 { 332 return result; 333 } 334 return (lower + upper) / 2; // 335 } 336 template <class RealType, class Policy> skewness(const uniform_distribution<RealType,Policy> & dist)337 inline RealType skewness(const uniform_distribution<RealType, Policy>& dist) 338 { 339 RealType lower = dist.lower(); 340 RealType upper = dist.upper(); 341 RealType result = 0; // of checks. 342 if(false == detail::check_uniform("boost::math::skewness(const uniform_distribution<%1%>&)",lower, upper, &result, Policy())) 343 { 344 return result; 345 } 346 return 0; 347 } // RealType skewness(const uniform_distribution<RealType, Policy>& dist) 348 349 template <class RealType, class Policy> kurtosis_excess(const uniform_distribution<RealType,Policy> & dist)350 inline RealType kurtosis_excess(const uniform_distribution<RealType, Policy>& dist) 351 { 352 RealType lower = dist.lower(); 353 RealType upper = dist.upper(); 354 RealType result = 0; // of checks. 355 if(false == detail::check_uniform("boost::math::kurtosis_execess(const uniform_distribution<%1%>&)", lower, upper, &result, Policy())) 356 { 357 return result; 358 } 359 return static_cast<RealType>(-6)/5; // -6/5 = -1.2; 360 } // RealType kurtosis_excess(const uniform_distribution<RealType, Policy>& dist) 361 362 template <class RealType, class Policy> kurtosis(const uniform_distribution<RealType,Policy> & dist)363 inline RealType kurtosis(const uniform_distribution<RealType, Policy>& dist) 364 { 365 return kurtosis_excess(dist) + 3; 366 } 367 368 } // namespace math 369 } // namespace boost 370 371 // This include must be at the end, *after* the accessors 372 // for this distribution have been defined, in order to 373 // keep compilers that support two-phase lookup happy. 374 #include <boost/math/distributions/detail/derived_accessors.hpp> 375 376 #endif // BOOST_STATS_UNIFORM_HPP 377 378 379 380