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