uniform.hpp 14 KB

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