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