pareto.hpp 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509
  1. // Copyright John Maddock 2007.
  2. // Copyright Paul A. Bristow 2007, 2009
  3. // Copyright Matt Borland 2023.
  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. #ifndef BOOST_STATS_PARETO_HPP
  8. #define BOOST_STATS_PARETO_HPP
  9. // http://en.wikipedia.org/wiki/Pareto_distribution
  10. // http://www.itl.nist.gov/div898/handbook/eda/section3/eda3661.htm
  11. // Also:
  12. // Weisstein, Eric W. "Pareto Distribution."
  13. // From MathWorld--A Wolfram Web Resource.
  14. // http://mathworld.wolfram.com/ParetoDistribution.html
  15. // Handbook of Statistical Distributions with Applications, K Krishnamoorthy, ISBN 1-58488-635-8, Chapter 23, pp 257 - 267.
  16. // Caution KK's a and b are the reverse of Mathworld!
  17. #include <boost/math/distributions/fwd.hpp>
  18. #include <boost/math/distributions/complement.hpp>
  19. #include <boost/math/distributions/detail/common_error_handling.hpp>
  20. #include <boost/math/special_functions/powm1.hpp>
  21. #include <boost/math/special_functions/log1p.hpp>
  22. #include <utility> // for BOOST_CURRENT_VALUE?
  23. #include <limits>
  24. #include <cmath>
  25. namespace boost
  26. {
  27. namespace math
  28. {
  29. namespace detail
  30. { // Parameter checking.
  31. template <class RealType, class Policy>
  32. inline bool check_pareto_scale(
  33. const char* function,
  34. RealType scale,
  35. RealType* result, const Policy& pol)
  36. {
  37. if((boost::math::isfinite)(scale))
  38. { // any > 0 finite value is OK.
  39. if (scale > 0)
  40. {
  41. return true;
  42. }
  43. else
  44. {
  45. *result = policies::raise_domain_error<RealType>(
  46. function,
  47. "Scale parameter is %1%, but must be > 0!", scale, pol);
  48. return false;
  49. }
  50. }
  51. else
  52. { // Not finite.
  53. *result = policies::raise_domain_error<RealType>(
  54. function,
  55. "Scale parameter is %1%, but must be finite!", scale, pol);
  56. return false;
  57. }
  58. } // bool check_pareto_scale
  59. template <class RealType, class Policy>
  60. inline bool check_pareto_shape(
  61. const char* function,
  62. RealType shape,
  63. RealType* result, const Policy& pol)
  64. {
  65. if((boost::math::isfinite)(shape))
  66. { // Any finite value > 0 is OK.
  67. if (shape > 0)
  68. {
  69. return true;
  70. }
  71. else
  72. {
  73. *result = policies::raise_domain_error<RealType>(
  74. function,
  75. "Shape parameter is %1%, but must be > 0!", shape, pol);
  76. return false;
  77. }
  78. }
  79. else
  80. { // Not finite.
  81. *result = policies::raise_domain_error<RealType>(
  82. function,
  83. "Shape parameter is %1%, but must be finite!", shape, pol);
  84. return false;
  85. }
  86. } // bool check_pareto_shape(
  87. template <class RealType, class Policy>
  88. inline bool check_pareto_x(
  89. const char* function,
  90. RealType const& x,
  91. RealType* result, const Policy& pol)
  92. {
  93. if((boost::math::isfinite)(x))
  94. { //
  95. if (x > 0)
  96. {
  97. return true;
  98. }
  99. else
  100. {
  101. *result = policies::raise_domain_error<RealType>(
  102. function,
  103. "x parameter is %1%, but must be > 0 !", x, pol);
  104. return false;
  105. }
  106. }
  107. else
  108. { // Not finite..
  109. *result = policies::raise_domain_error<RealType>(
  110. function,
  111. "x parameter is %1%, but must be finite!", x, pol);
  112. return false;
  113. }
  114. } // bool check_pareto_x
  115. template <class RealType, class Policy>
  116. inline bool check_pareto( // distribution parameters.
  117. const char* function,
  118. RealType scale,
  119. RealType shape,
  120. RealType* result, const Policy& pol)
  121. {
  122. return check_pareto_scale(function, scale, result, pol)
  123. && check_pareto_shape(function, shape, result, pol);
  124. } // bool check_pareto(
  125. } // namespace detail
  126. template <class RealType = double, class Policy = policies::policy<> >
  127. class pareto_distribution
  128. {
  129. public:
  130. typedef RealType value_type;
  131. typedef Policy policy_type;
  132. pareto_distribution(RealType l_scale = 1, RealType l_shape = 1)
  133. : m_scale(l_scale), m_shape(l_shape)
  134. { // Constructor.
  135. RealType result = 0;
  136. detail::check_pareto("boost::math::pareto_distribution<%1%>::pareto_distribution", l_scale, l_shape, &result, Policy());
  137. }
  138. RealType scale()const
  139. { // AKA Xm and Wolfram b and beta
  140. return m_scale;
  141. }
  142. RealType shape()const
  143. { // AKA k and Wolfram a and alpha
  144. return m_shape;
  145. }
  146. private:
  147. // Data members:
  148. RealType m_scale; // distribution scale (xm) or beta
  149. RealType m_shape; // distribution shape (k) or alpha
  150. };
  151. typedef pareto_distribution<double> pareto; // Convenience to allow pareto(2., 3.);
  152. #ifdef __cpp_deduction_guides
  153. template <class RealType>
  154. pareto_distribution(RealType)->pareto_distribution<typename boost::math::tools::promote_args<RealType>::type>;
  155. template <class RealType>
  156. pareto_distribution(RealType,RealType)->pareto_distribution<typename boost::math::tools::promote_args<RealType>::type>;
  157. #endif
  158. template <class RealType, class Policy>
  159. inline const std::pair<RealType, RealType> range(const pareto_distribution<RealType, Policy>& /*dist*/)
  160. { // Range of permissible values for random variable x.
  161. using boost::math::tools::max_value;
  162. return std::pair<RealType, RealType>(static_cast<RealType>(0), max_value<RealType>()); // scale zero to + infinity.
  163. } // range
  164. template <class RealType, class Policy>
  165. inline const std::pair<RealType, RealType> support(const pareto_distribution<RealType, Policy>& dist)
  166. { // Range of supported values for random variable x.
  167. // This is range where cdf rises from 0 to 1, and outside it, the pdf is zero.
  168. using boost::math::tools::max_value;
  169. return std::pair<RealType, RealType>(dist.scale(), max_value<RealType>() ); // scale to + infinity.
  170. } // support
  171. template <class RealType, class Policy>
  172. inline RealType pdf(const pareto_distribution<RealType, Policy>& dist, const RealType& x)
  173. {
  174. BOOST_MATH_STD_USING // for ADL of std function pow.
  175. static const char* function = "boost::math::pdf(const pareto_distribution<%1%>&, %1%)";
  176. RealType scale = dist.scale();
  177. RealType shape = dist.shape();
  178. RealType result = 0;
  179. if(false == (detail::check_pareto_x(function, x, &result, Policy())
  180. && detail::check_pareto(function, scale, shape, &result, Policy())))
  181. return result;
  182. if (x < scale)
  183. { // regardless of shape, pdf is zero (or should be disallow x < scale and throw an exception?).
  184. return 0;
  185. }
  186. result = shape * pow(scale, shape) / pow(x, shape+1);
  187. return result;
  188. } // pdf
  189. template <class RealType, class Policy>
  190. inline RealType cdf(const pareto_distribution<RealType, Policy>& dist, const RealType& x)
  191. {
  192. BOOST_MATH_STD_USING // for ADL of std function pow.
  193. static const char* function = "boost::math::cdf(const pareto_distribution<%1%>&, %1%)";
  194. RealType scale = dist.scale();
  195. RealType shape = dist.shape();
  196. RealType result = 0;
  197. if(false == (detail::check_pareto_x(function, x, &result, Policy())
  198. && detail::check_pareto(function, scale, shape, &result, Policy())))
  199. return result;
  200. if (x <= scale)
  201. { // regardless of shape, cdf is zero.
  202. return 0;
  203. }
  204. // result = RealType(1) - pow((scale / x), shape);
  205. result = -boost::math::powm1(scale/x, shape, Policy()); // should be more accurate.
  206. return result;
  207. } // cdf
  208. template <class RealType, class Policy>
  209. inline RealType logcdf(const pareto_distribution<RealType, Policy>& dist, const RealType& x)
  210. {
  211. BOOST_MATH_STD_USING // for ADL of std function pow.
  212. static const char* function = "boost::math::logcdf(const pareto_distribution<%1%>&, %1%)";
  213. RealType scale = dist.scale();
  214. RealType shape = dist.shape();
  215. RealType result = 0;
  216. if(false == (detail::check_pareto_x(function, x, &result, Policy())
  217. && detail::check_pareto(function, scale, shape, &result, Policy())))
  218. return result;
  219. if (x <= scale)
  220. { // regardless of shape, cdf is zero.
  221. return -std::numeric_limits<RealType>::infinity();
  222. }
  223. result = log1p(-pow(scale/x, shape), Policy());
  224. return result;
  225. } // logcdf
  226. template <class RealType, class Policy>
  227. inline RealType quantile(const pareto_distribution<RealType, Policy>& dist, const RealType& p)
  228. {
  229. BOOST_MATH_STD_USING // for ADL of std function pow.
  230. static const char* function = "boost::math::quantile(const pareto_distribution<%1%>&, %1%)";
  231. RealType result = 0;
  232. RealType scale = dist.scale();
  233. RealType shape = dist.shape();
  234. if(false == (detail::check_probability(function, p, &result, Policy())
  235. && detail::check_pareto(function, scale, shape, &result, Policy())))
  236. {
  237. return result;
  238. }
  239. if (p == 0)
  240. {
  241. return scale; // x must be scale (or less).
  242. }
  243. if (p == 1)
  244. {
  245. return policies::raise_overflow_error<RealType>(function, 0, Policy()); // x = + infinity.
  246. }
  247. result = scale /
  248. (pow((1 - p), 1 / shape));
  249. // K. Krishnamoorthy, ISBN 1-58488-635-8 eq 23.1.3
  250. return result;
  251. } // quantile
  252. template <class RealType, class Policy>
  253. inline RealType cdf(const complemented2_type<pareto_distribution<RealType, Policy>, RealType>& c)
  254. {
  255. BOOST_MATH_STD_USING // for ADL of std function pow.
  256. static const char* function = "boost::math::cdf(const pareto_distribution<%1%>&, %1%)";
  257. RealType result = 0;
  258. RealType x = c.param;
  259. RealType scale = c.dist.scale();
  260. RealType shape = c.dist.shape();
  261. if(false == (detail::check_pareto_x(function, x, &result, Policy())
  262. && detail::check_pareto(function, scale, shape, &result, Policy())))
  263. return result;
  264. if (x <= scale)
  265. { // regardless of shape, cdf is zero, and complement is unity.
  266. return 1;
  267. }
  268. result = pow((scale/x), shape);
  269. return result;
  270. } // cdf complement
  271. template <class RealType, class Policy>
  272. inline RealType logcdf(const complemented2_type<pareto_distribution<RealType, Policy>, RealType>& c)
  273. {
  274. BOOST_MATH_STD_USING // for ADL of std function pow.
  275. static const char* function = "boost::math::logcdf(const pareto_distribution<%1%>&, %1%)";
  276. RealType result = 0;
  277. RealType x = c.param;
  278. RealType scale = c.dist.scale();
  279. RealType shape = c.dist.shape();
  280. if(false == (detail::check_pareto_x(function, x, &result, Policy())
  281. && detail::check_pareto(function, scale, shape, &result, Policy())))
  282. return result;
  283. if (x <= scale)
  284. { // regardless of shape, cdf is zero, and complement is unity.
  285. return 0;
  286. }
  287. result = log(pow((scale/x), shape));
  288. return result;
  289. } // logcdf complement
  290. template <class RealType, class Policy>
  291. inline RealType quantile(const complemented2_type<pareto_distribution<RealType, Policy>, RealType>& c)
  292. {
  293. BOOST_MATH_STD_USING // for ADL of std function pow.
  294. static const char* function = "boost::math::quantile(const pareto_distribution<%1%>&, %1%)";
  295. RealType result = 0;
  296. RealType q = c.param;
  297. RealType scale = c.dist.scale();
  298. RealType shape = c.dist.shape();
  299. if(false == (detail::check_probability(function, q, &result, Policy())
  300. && detail::check_pareto(function, scale, shape, &result, Policy())))
  301. {
  302. return result;
  303. }
  304. if (q == 1)
  305. {
  306. return scale; // x must be scale (or less).
  307. }
  308. if (q == 0)
  309. {
  310. return policies::raise_overflow_error<RealType>(function, 0, Policy()); // x = + infinity.
  311. }
  312. result = scale / (pow(q, 1 / shape));
  313. // K. Krishnamoorthy, ISBN 1-58488-635-8 eq 23.1.3
  314. return result;
  315. } // quantile complement
  316. template <class RealType, class Policy>
  317. inline RealType mean(const pareto_distribution<RealType, Policy>& dist)
  318. {
  319. RealType result = 0;
  320. static const char* function = "boost::math::mean(const pareto_distribution<%1%>&, %1%)";
  321. if(false == detail::check_pareto(function, dist.scale(), dist.shape(), &result, Policy()))
  322. {
  323. return result;
  324. }
  325. if (dist.shape() > RealType(1))
  326. {
  327. return dist.shape() * dist.scale() / (dist.shape() - 1);
  328. }
  329. else
  330. {
  331. using boost::math::tools::max_value;
  332. return max_value<RealType>(); // +infinity.
  333. }
  334. } // mean
  335. template <class RealType, class Policy>
  336. inline RealType mode(const pareto_distribution<RealType, Policy>& dist)
  337. {
  338. return dist.scale();
  339. } // mode
  340. template <class RealType, class Policy>
  341. inline RealType median(const pareto_distribution<RealType, Policy>& dist)
  342. {
  343. RealType result = 0;
  344. static const char* function = "boost::math::median(const pareto_distribution<%1%>&, %1%)";
  345. if(false == detail::check_pareto(function, dist.scale(), dist.shape(), &result, Policy()))
  346. {
  347. return result;
  348. }
  349. BOOST_MATH_STD_USING
  350. return dist.scale() * pow(RealType(2), (1/dist.shape()));
  351. } // median
  352. template <class RealType, class Policy>
  353. inline RealType variance(const pareto_distribution<RealType, Policy>& dist)
  354. {
  355. RealType result = 0;
  356. RealType scale = dist.scale();
  357. RealType shape = dist.shape();
  358. static const char* function = "boost::math::variance(const pareto_distribution<%1%>&, %1%)";
  359. if(false == detail::check_pareto(function, scale, shape, &result, Policy()))
  360. {
  361. return result;
  362. }
  363. if (shape > 2)
  364. {
  365. result = (scale * scale * shape) /
  366. ((shape - 1) * (shape - 1) * (shape - 2));
  367. }
  368. else
  369. {
  370. result = policies::raise_domain_error<RealType>(
  371. function,
  372. "variance is undefined for shape <= 2, but got %1%.", dist.shape(), Policy());
  373. }
  374. return result;
  375. } // variance
  376. template <class RealType, class Policy>
  377. inline RealType skewness(const pareto_distribution<RealType, Policy>& dist)
  378. {
  379. BOOST_MATH_STD_USING
  380. RealType result = 0;
  381. RealType shape = dist.shape();
  382. static const char* function = "boost::math::pdf(const pareto_distribution<%1%>&, %1%)";
  383. if(false == detail::check_pareto(function, dist.scale(), shape, &result, Policy()))
  384. {
  385. return result;
  386. }
  387. if (shape > 3)
  388. {
  389. result = sqrt((shape - 2) / shape) *
  390. 2 * (shape + 1) /
  391. (shape - 3);
  392. }
  393. else
  394. {
  395. result = policies::raise_domain_error<RealType>(
  396. function,
  397. "skewness is undefined for shape <= 3, but got %1%.", dist.shape(), Policy());
  398. }
  399. return result;
  400. } // skewness
  401. template <class RealType, class Policy>
  402. inline RealType kurtosis(const pareto_distribution<RealType, Policy>& dist)
  403. {
  404. RealType result = 0;
  405. RealType shape = dist.shape();
  406. static const char* function = "boost::math::pdf(const pareto_distribution<%1%>&, %1%)";
  407. if(false == detail::check_pareto(function, dist.scale(), shape, &result, Policy()))
  408. {
  409. return result;
  410. }
  411. if (shape > 4)
  412. {
  413. result = 3 * ((shape - 2) * (3 * shape * shape + shape + 2)) /
  414. (shape * (shape - 3) * (shape - 4));
  415. }
  416. else
  417. {
  418. result = policies::raise_domain_error<RealType>(
  419. function,
  420. "kurtosis_excess is undefined for shape <= 4, but got %1%.", shape, Policy());
  421. }
  422. return result;
  423. } // kurtosis
  424. template <class RealType, class Policy>
  425. inline RealType kurtosis_excess(const pareto_distribution<RealType, Policy>& dist)
  426. {
  427. RealType result = 0;
  428. RealType shape = dist.shape();
  429. static const char* function = "boost::math::pdf(const pareto_distribution<%1%>&, %1%)";
  430. if(false == detail::check_pareto(function, dist.scale(), shape, &result, Policy()))
  431. {
  432. return result;
  433. }
  434. if (shape > 4)
  435. {
  436. result = 6 * ((shape * shape * shape) + (shape * shape) - 6 * shape - 2) /
  437. (shape * (shape - 3) * (shape - 4));
  438. }
  439. else
  440. {
  441. result = policies::raise_domain_error<RealType>(
  442. function,
  443. "kurtosis_excess is undefined for shape <= 4, but got %1%.", dist.shape(), Policy());
  444. }
  445. return result;
  446. } // kurtosis_excess
  447. template <class RealType, class Policy>
  448. inline RealType entropy(const pareto_distribution<RealType, Policy>& dist)
  449. {
  450. using std::log;
  451. RealType xm = dist.scale();
  452. RealType alpha = dist.shape();
  453. return log(xm/alpha) + 1 + 1/alpha;
  454. }
  455. } // namespace math
  456. } // namespace boost
  457. // This include must be at the end, *after* the accessors
  458. // for this distribution have been defined, in order to
  459. // keep compilers that support two-phase lookup happy.
  460. #include <boost/math/distributions/detail/derived_accessors.hpp>
  461. #endif // BOOST_STATS_PARETO_HPP