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