distributions.hpp 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497
  1. // Copyright John Maddock 2006.
  2. // Use, modification and distribution are subject to the
  3. // Boost Software License, Version 1.0. (See accompanying file
  4. // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  5. // distributions.hpp provides definitions of the concept of a distribution
  6. // and non-member accessor functions that must be implemented by all distributions.
  7. // This is used to verify that
  8. // all the features of a distributions have been fully implemented.
  9. #ifndef BOOST_MATH_DISTRIBUTION_CONCEPT_HPP
  10. #define BOOST_MATH_DISTRIBUTION_CONCEPT_HPP
  11. #ifndef BOOST_MATH_STANDALONE
  12. #include <boost/math/distributions/complement.hpp>
  13. #include <boost/math/distributions/fwd.hpp>
  14. #ifdef _MSC_VER
  15. #pragma warning(push)
  16. #pragma warning(disable: 4100)
  17. #pragma warning(disable: 4510)
  18. #pragma warning(disable: 4610)
  19. #pragma warning(disable: 4189) // local variable is initialized but not referenced.
  20. #endif
  21. #include <boost/concept_check.hpp>
  22. #ifdef _MSC_VER
  23. #pragma warning(pop)
  24. #endif
  25. #include <utility>
  26. namespace boost{
  27. namespace math{
  28. namespace concepts
  29. {
  30. // Begin by defining a concept archetype
  31. // for a distribution class:
  32. //
  33. template <class RealType>
  34. class distribution_archetype
  35. {
  36. public:
  37. typedef RealType value_type;
  38. distribution_archetype(const distribution_archetype&); // Copy constructible.
  39. distribution_archetype& operator=(const distribution_archetype&); // Assignable.
  40. // There is no default constructor,
  41. // but we need a way to instantiate the archetype:
  42. static distribution_archetype& get_object()
  43. {
  44. // will never get called:
  45. return *reinterpret_cast<distribution_archetype*>(nullptr);
  46. }
  47. }; // template <class RealType>class distribution_archetype
  48. // Non-member accessor functions:
  49. // (This list defines the functions that must be implemented by all distributions).
  50. template <class RealType>
  51. RealType pdf(const distribution_archetype<RealType>& dist, const RealType& x);
  52. template <class RealType>
  53. RealType cdf(const distribution_archetype<RealType>& dist, const RealType& x);
  54. template <class RealType>
  55. RealType quantile(const distribution_archetype<RealType>& dist, const RealType& p);
  56. template <class RealType>
  57. RealType cdf(const complemented2_type<distribution_archetype<RealType>, RealType>& c);
  58. template <class RealType>
  59. RealType quantile(const complemented2_type<distribution_archetype<RealType>, RealType>& c);
  60. template <class RealType>
  61. RealType mean(const distribution_archetype<RealType>& dist);
  62. template <class RealType>
  63. RealType standard_deviation(const distribution_archetype<RealType>& dist);
  64. template <class RealType>
  65. RealType variance(const distribution_archetype<RealType>& dist);
  66. template <class RealType>
  67. RealType hazard(const distribution_archetype<RealType>& dist);
  68. template <class RealType>
  69. RealType chf(const distribution_archetype<RealType>& dist);
  70. // http://en.wikipedia.org/wiki/Characteristic_function_%28probability_theory%29
  71. template <class RealType>
  72. RealType coefficient_of_variation(const distribution_archetype<RealType>& dist);
  73. template <class RealType>
  74. RealType mode(const distribution_archetype<RealType>& dist);
  75. template <class RealType>
  76. RealType skewness(const distribution_archetype<RealType>& dist);
  77. template <class RealType>
  78. RealType kurtosis_excess(const distribution_archetype<RealType>& dist);
  79. template <class RealType>
  80. RealType kurtosis(const distribution_archetype<RealType>& dist);
  81. template <class RealType>
  82. RealType median(const distribution_archetype<RealType>& dist);
  83. template <class RealType>
  84. std::pair<RealType, RealType> range(const distribution_archetype<RealType>& dist);
  85. template <class RealType>
  86. std::pair<RealType, RealType> support(const distribution_archetype<RealType>& dist);
  87. //
  88. // Next comes the concept checks for verifying that a class
  89. // fulfils the requirements of a Distribution:
  90. //
  91. template <class Distribution>
  92. struct DistributionConcept
  93. {
  94. typedef typename Distribution::value_type value_type;
  95. void constraints()
  96. {
  97. function_requires<CopyConstructibleConcept<Distribution> >();
  98. function_requires<AssignableConcept<Distribution> >();
  99. const Distribution& dist = DistributionConcept<Distribution>::get_object();
  100. value_type x = 0;
  101. // The result values are ignored in all these checks.
  102. value_type v = cdf(dist, x);
  103. v = cdf(complement(dist, x));
  104. suppress_unused_variable_warning(v);
  105. v = pdf(dist, x);
  106. suppress_unused_variable_warning(v);
  107. v = quantile(dist, x);
  108. suppress_unused_variable_warning(v);
  109. v = quantile(complement(dist, x));
  110. suppress_unused_variable_warning(v);
  111. v = mean(dist);
  112. suppress_unused_variable_warning(v);
  113. v = mode(dist);
  114. suppress_unused_variable_warning(v);
  115. v = standard_deviation(dist);
  116. suppress_unused_variable_warning(v);
  117. v = variance(dist);
  118. suppress_unused_variable_warning(v);
  119. v = hazard(dist, x);
  120. suppress_unused_variable_warning(v);
  121. v = chf(dist, x);
  122. suppress_unused_variable_warning(v);
  123. v = coefficient_of_variation(dist);
  124. suppress_unused_variable_warning(v);
  125. v = skewness(dist);
  126. suppress_unused_variable_warning(v);
  127. v = kurtosis(dist);
  128. suppress_unused_variable_warning(v);
  129. v = kurtosis_excess(dist);
  130. suppress_unused_variable_warning(v);
  131. v = median(dist);
  132. suppress_unused_variable_warning(v);
  133. std::pair<value_type, value_type> pv;
  134. pv = range(dist);
  135. suppress_unused_variable_warning(pv);
  136. pv = support(dist);
  137. suppress_unused_variable_warning(pv);
  138. float f = 1;
  139. v = cdf(dist, f);
  140. suppress_unused_variable_warning(v);
  141. v = cdf(complement(dist, f));
  142. suppress_unused_variable_warning(v);
  143. v = pdf(dist, f);
  144. suppress_unused_variable_warning(v);
  145. v = quantile(dist, f);
  146. suppress_unused_variable_warning(v);
  147. v = quantile(complement(dist, f));
  148. suppress_unused_variable_warning(v);
  149. v = hazard(dist, f);
  150. suppress_unused_variable_warning(v);
  151. v = chf(dist, f);
  152. suppress_unused_variable_warning(v);
  153. double d = 1;
  154. v = cdf(dist, d);
  155. suppress_unused_variable_warning(v);
  156. v = cdf(complement(dist, d));
  157. suppress_unused_variable_warning(v);
  158. v = pdf(dist, d);
  159. suppress_unused_variable_warning(v);
  160. v = quantile(dist, d);
  161. suppress_unused_variable_warning(v);
  162. v = quantile(complement(dist, d));
  163. suppress_unused_variable_warning(v);
  164. v = hazard(dist, d);
  165. suppress_unused_variable_warning(v);
  166. v = chf(dist, d);
  167. suppress_unused_variable_warning(v);
  168. #ifndef TEST_MPFR
  169. long double ld = 1;
  170. v = cdf(dist, ld);
  171. suppress_unused_variable_warning(v);
  172. v = cdf(complement(dist, ld));
  173. suppress_unused_variable_warning(v);
  174. v = pdf(dist, ld);
  175. suppress_unused_variable_warning(v);
  176. v = quantile(dist, ld);
  177. suppress_unused_variable_warning(v);
  178. v = quantile(complement(dist, ld));
  179. suppress_unused_variable_warning(v);
  180. v = hazard(dist, ld);
  181. suppress_unused_variable_warning(v);
  182. v = chf(dist, ld);
  183. suppress_unused_variable_warning(v);
  184. #endif
  185. int i = 1;
  186. v = cdf(dist, i);
  187. suppress_unused_variable_warning(v);
  188. v = cdf(complement(dist, i));
  189. suppress_unused_variable_warning(v);
  190. v = pdf(dist, i);
  191. suppress_unused_variable_warning(v);
  192. v = quantile(dist, i);
  193. suppress_unused_variable_warning(v);
  194. v = quantile(complement(dist, i));
  195. suppress_unused_variable_warning(v);
  196. v = hazard(dist, i);
  197. suppress_unused_variable_warning(v);
  198. v = chf(dist, i);
  199. suppress_unused_variable_warning(v);
  200. unsigned long li = 1;
  201. v = cdf(dist, li);
  202. suppress_unused_variable_warning(v);
  203. v = cdf(complement(dist, li));
  204. suppress_unused_variable_warning(v);
  205. v = pdf(dist, li);
  206. suppress_unused_variable_warning(v);
  207. v = quantile(dist, li);
  208. suppress_unused_variable_warning(v);
  209. v = quantile(complement(dist, li));
  210. suppress_unused_variable_warning(v);
  211. v = hazard(dist, li);
  212. suppress_unused_variable_warning(v);
  213. v = chf(dist, li);
  214. suppress_unused_variable_warning(v);
  215. test_extra_members(dist);
  216. }
  217. template <class D>
  218. static void test_extra_members(const D&)
  219. {}
  220. template <class R, class P>
  221. static void test_extra_members(const boost::math::bernoulli_distribution<R, P>& d)
  222. {
  223. value_type r = d.success_fraction();
  224. (void)r; // warning suppression
  225. }
  226. template <class R, class P>
  227. static void test_extra_members(const boost::math::beta_distribution<R, P>& d)
  228. {
  229. value_type r1 = d.alpha();
  230. value_type r2 = d.beta();
  231. r1 = boost::math::beta_distribution<R, P>::find_alpha(r1, r2);
  232. suppress_unused_variable_warning(r1);
  233. r1 = boost::math::beta_distribution<R, P>::find_beta(r1, r2);
  234. suppress_unused_variable_warning(r1);
  235. r1 = boost::math::beta_distribution<R, P>::find_alpha(r1, r2, r1);
  236. suppress_unused_variable_warning(r1);
  237. r1 = boost::math::beta_distribution<R, P>::find_beta(r1, r2, r1);
  238. suppress_unused_variable_warning(r1);
  239. }
  240. template <class R, class P>
  241. static void test_extra_members(const boost::math::binomial_distribution<R, P>& d)
  242. {
  243. value_type r = d.success_fraction();
  244. r = d.trials();
  245. r = Distribution::find_lower_bound_on_p(r, r, r);
  246. r = Distribution::find_lower_bound_on_p(r, r, r, Distribution::clopper_pearson_exact_interval);
  247. r = Distribution::find_lower_bound_on_p(r, r, r, Distribution::jeffreys_prior_interval);
  248. r = Distribution::find_upper_bound_on_p(r, r, r);
  249. r = Distribution::find_upper_bound_on_p(r, r, r, Distribution::clopper_pearson_exact_interval);
  250. r = Distribution::find_upper_bound_on_p(r, r, r, Distribution::jeffreys_prior_interval);
  251. r = Distribution::find_minimum_number_of_trials(r, r, r);
  252. r = Distribution::find_maximum_number_of_trials(r, r, r);
  253. suppress_unused_variable_warning(r);
  254. }
  255. template <class R, class P>
  256. static void test_extra_members(const boost::math::cauchy_distribution<R, P>& d)
  257. {
  258. value_type r = d.location();
  259. r = d.scale();
  260. suppress_unused_variable_warning(r);
  261. }
  262. template <class R, class P>
  263. static void test_extra_members(const boost::math::chi_squared_distribution<R, P>& d)
  264. {
  265. value_type r = d.degrees_of_freedom();
  266. r = Distribution::find_degrees_of_freedom(r, r, r, r);
  267. r = Distribution::find_degrees_of_freedom(r, r, r, r, r);
  268. suppress_unused_variable_warning(r);
  269. }
  270. template <class R, class P>
  271. static void test_extra_members(const boost::math::exponential_distribution<R, P>& d)
  272. {
  273. value_type r = d.lambda();
  274. suppress_unused_variable_warning(r);
  275. }
  276. template <class R, class P>
  277. static void test_extra_members(const boost::math::extreme_value_distribution<R, P>& d)
  278. {
  279. value_type r = d.scale();
  280. r = d.location();
  281. suppress_unused_variable_warning(r);
  282. }
  283. template <class R, class P>
  284. static void test_extra_members(const boost::math::fisher_f_distribution<R, P>& d)
  285. {
  286. value_type r = d.degrees_of_freedom1();
  287. r = d.degrees_of_freedom2();
  288. suppress_unused_variable_warning(r);
  289. }
  290. template <class R, class P>
  291. static void test_extra_members(const boost::math::gamma_distribution<R, P>& d)
  292. {
  293. value_type r = d.scale();
  294. r = d.shape();
  295. suppress_unused_variable_warning(r);
  296. }
  297. template <class R, class P>
  298. static void test_extra_members(const boost::math::inverse_chi_squared_distribution<R, P>& d)
  299. {
  300. value_type r = d.scale();
  301. r = d.degrees_of_freedom();
  302. suppress_unused_variable_warning(r);
  303. }
  304. template <class R, class P>
  305. static void test_extra_members(const boost::math::inverse_gamma_distribution<R, P>& d)
  306. {
  307. value_type r = d.scale();
  308. r = d.shape();
  309. suppress_unused_variable_warning(r);
  310. }
  311. template <class R, class P>
  312. static void test_extra_members(const boost::math::hypergeometric_distribution<R, P>& d)
  313. {
  314. std::uint64_t u = d.defective();
  315. u = d.sample_count();
  316. u = d.total();
  317. suppress_unused_variable_warning(u);
  318. }
  319. template <class R, class P>
  320. static void test_extra_members(const boost::math::laplace_distribution<R, P>& d)
  321. {
  322. value_type r = d.scale();
  323. r = d.location();
  324. suppress_unused_variable_warning(r);
  325. }
  326. template <class R, class P>
  327. static void test_extra_members(const boost::math::logistic_distribution<R, P>& d)
  328. {
  329. value_type r = d.scale();
  330. r = d.location();
  331. suppress_unused_variable_warning(r);
  332. }
  333. template <class R, class P>
  334. static void test_extra_members(const boost::math::lognormal_distribution<R, P>& d)
  335. {
  336. value_type r = d.scale();
  337. r = d.location();
  338. suppress_unused_variable_warning(r);
  339. }
  340. template <class R, class P>
  341. static void test_extra_members(const boost::math::negative_binomial_distribution<R, P>& d)
  342. {
  343. value_type r = d.success_fraction();
  344. r = d.successes();
  345. r = Distribution::find_lower_bound_on_p(r, r, r);
  346. r = Distribution::find_upper_bound_on_p(r, r, r);
  347. r = Distribution::find_minimum_number_of_trials(r, r, r);
  348. r = Distribution::find_maximum_number_of_trials(r, r, r);
  349. suppress_unused_variable_warning(r);
  350. }
  351. template <class R, class P>
  352. static void test_extra_members(const boost::math::non_central_beta_distribution<R, P>& d)
  353. {
  354. value_type r1 = d.alpha();
  355. value_type r2 = d.beta();
  356. r1 = d.non_centrality();
  357. (void)r1; // warning suppression
  358. (void)r2; // warning suppression
  359. }
  360. template <class R, class P>
  361. static void test_extra_members(const boost::math::non_central_chi_squared_distribution<R, P>& d)
  362. {
  363. value_type r = d.degrees_of_freedom();
  364. r = d.non_centrality();
  365. r = Distribution::find_degrees_of_freedom(r, r, r);
  366. r = Distribution::find_degrees_of_freedom(boost::math::complement(r, r, r));
  367. r = Distribution::find_non_centrality(r, r, r);
  368. r = Distribution::find_non_centrality(boost::math::complement(r, r, r));
  369. (void)r; // warning suppression
  370. }
  371. template <class R, class P>
  372. static void test_extra_members(const boost::math::non_central_f_distribution<R, P>& d)
  373. {
  374. value_type r = d.degrees_of_freedom1();
  375. r = d.degrees_of_freedom2();
  376. r = d.non_centrality();
  377. (void)r; // warning suppression
  378. }
  379. template <class R, class P>
  380. static void test_extra_members(const boost::math::non_central_t_distribution<R, P>& d)
  381. {
  382. value_type r = d.degrees_of_freedom();
  383. r = d.non_centrality();
  384. (void)r; // warning suppression
  385. }
  386. template <class R, class P>
  387. static void test_extra_members(const boost::math::normal_distribution<R, P>& d)
  388. {
  389. value_type r = d.scale();
  390. r = d.location();
  391. r = d.mean();
  392. r = d.standard_deviation();
  393. (void)r; // warning suppression
  394. }
  395. template <class R, class P>
  396. static void test_extra_members(const boost::math::pareto_distribution<R, P>& d)
  397. {
  398. value_type r = d.scale();
  399. r = d.shape();
  400. (void)r; // warning suppression
  401. }
  402. template <class R, class P>
  403. static void test_extra_members(const boost::math::poisson_distribution<R, P>& d)
  404. {
  405. value_type r = d.mean();
  406. (void)r; // warning suppression
  407. }
  408. template <class R, class P>
  409. static void test_extra_members(const boost::math::rayleigh_distribution<R, P>& d)
  410. {
  411. value_type r = d.sigma();
  412. (void)r; // warning suppression
  413. }
  414. template <class R, class P>
  415. static void test_extra_members(const boost::math::students_t_distribution<R, P>& d)
  416. {
  417. value_type r = d.degrees_of_freedom();
  418. r = d.find_degrees_of_freedom(r, r, r, r);
  419. r = d.find_degrees_of_freedom(r, r, r, r, r);
  420. (void)r; // warning suppression
  421. }
  422. template <class R, class P>
  423. static void test_extra_members(const boost::math::triangular_distribution<R, P>& d)
  424. {
  425. value_type r = d.lower();
  426. r = d.mode();
  427. r = d.upper();
  428. (void)r; // warning suppression
  429. }
  430. template <class R, class P>
  431. static void test_extra_members(const boost::math::weibull_distribution<R, P>& d)
  432. {
  433. value_type r = d.scale();
  434. r = d.shape();
  435. (void)r; // warning suppression
  436. }
  437. template <class R, class P>
  438. static void test_extra_members(const boost::math::uniform_distribution<R, P>& d)
  439. {
  440. value_type r = d.lower();
  441. r = d.upper();
  442. (void)r; // warning suppression
  443. }
  444. private:
  445. static Distribution* pd;
  446. static Distribution& get_object()
  447. {
  448. // In reality this will never get called:
  449. return *pd;
  450. }
  451. }; // struct DistributionConcept
  452. template <class Distribution>
  453. Distribution* DistributionConcept<Distribution>::pd = 0;
  454. } // namespace concepts
  455. } // namespace math
  456. } // namespace boost
  457. #else
  458. #error This header can not be used in standalone mode.
  459. #endif // BOOST_MATH_STANDALONE
  460. #endif // BOOST_MATH_DISTRIBUTION_CONCEPT_HPP