distributions.hpp 17 KB

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