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)
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.
11 #ifndef BOOST_MATH_DISTRIBUTION_CONCEPT_HPP
12 #define BOOST_MATH_DISTRIBUTION_CONCEPT_HPP
14 #ifndef BOOST_MATH_STANDALONE
16 #include <boost/math/distributions/complement.hpp>
17 #include <boost/math/distributions/fwd.hpp>
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.
25 #include <boost/concept_check.hpp>
36 // Begin by defining a concept archetype
37 // for a distribution class:
39 template <class RealType>
40 class distribution_archetype
43 typedef RealType value_type;
45 distribution_archetype(const distribution_archetype&); // Copy constructible.
46 distribution_archetype& operator=(const distribution_archetype&); // Assignable.
48 // There is no default constructor,
49 // but we need a way to instantiate the archetype:
50 static distribution_archetype& get_object()
52 // will never get caled:
53 return *reinterpret_cast<distribution_archetype*>(0);
55 }; // template <class RealType>class distribution_archetype
57 // Non-member accessor functions:
58 // (This list defines the functions that must be implemented by all distributions).
60 template <class RealType>
61 RealType pdf(const distribution_archetype<RealType>& dist, const RealType& x);
63 template <class RealType>
64 RealType cdf(const distribution_archetype<RealType>& dist, const RealType& x);
66 template <class RealType>
67 RealType quantile(const distribution_archetype<RealType>& dist, const RealType& p);
69 template <class RealType>
70 RealType cdf(const complemented2_type<distribution_archetype<RealType>, RealType>& c);
72 template <class RealType>
73 RealType quantile(const complemented2_type<distribution_archetype<RealType>, RealType>& c);
75 template <class RealType>
76 RealType mean(const distribution_archetype<RealType>& dist);
78 template <class RealType>
79 RealType standard_deviation(const distribution_archetype<RealType>& dist);
81 template <class RealType>
82 RealType variance(const distribution_archetype<RealType>& dist);
84 template <class RealType>
85 RealType hazard(const distribution_archetype<RealType>& dist);
87 template <class RealType>
88 RealType chf(const distribution_archetype<RealType>& dist);
89 // http://en.wikipedia.org/wiki/Characteristic_function_%28probability_theory%29
91 template <class RealType>
92 RealType coefficient_of_variation(const distribution_archetype<RealType>& dist);
94 template <class RealType>
95 RealType mode(const distribution_archetype<RealType>& dist);
97 template <class RealType>
98 RealType skewness(const distribution_archetype<RealType>& dist);
100 template <class RealType>
101 RealType kurtosis_excess(const distribution_archetype<RealType>& dist);
103 template <class RealType>
104 RealType kurtosis(const distribution_archetype<RealType>& dist);
106 template <class RealType>
107 RealType median(const distribution_archetype<RealType>& dist);
109 template <class RealType>
110 std::pair<RealType, RealType> range(const distribution_archetype<RealType>& dist);
112 template <class RealType>
113 std::pair<RealType, RealType> support(const distribution_archetype<RealType>& dist);
116 // Next comes the concept checks for verifying that a class
117 // fulfils the requirements of a Distribution:
119 template <class Distribution>
120 struct DistributionConcept
122 typedef typename Distribution::value_type value_type;
126 function_requires<CopyConstructibleConcept<Distribution> >();
127 function_requires<AssignableConcept<Distribution> >();
129 const Distribution& dist = DistributionConcept<Distribution>::get_object();
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);
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);
143 suppress_unused_variable_warning(v);
145 suppress_unused_variable_warning(v);
146 v = standard_deviation(dist);
147 suppress_unused_variable_warning(v);
149 suppress_unused_variable_warning(v);
151 suppress_unused_variable_warning(v);
153 suppress_unused_variable_warning(v);
154 v = coefficient_of_variation(dist);
155 suppress_unused_variable_warning(v);
157 suppress_unused_variable_warning(v);
159 suppress_unused_variable_warning(v);
160 v = kurtosis_excess(dist);
161 suppress_unused_variable_warning(v);
163 suppress_unused_variable_warning(v);
164 std::pair<value_type, value_type> pv;
166 suppress_unused_variable_warning(pv);
168 suppress_unused_variable_warning(pv);
172 suppress_unused_variable_warning(v);
173 v = cdf(complement(dist, f));
174 suppress_unused_variable_warning(v);
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);
182 suppress_unused_variable_warning(v);
184 suppress_unused_variable_warning(v);
187 suppress_unused_variable_warning(v);
188 v = cdf(complement(dist, d));
189 suppress_unused_variable_warning(v);
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);
197 suppress_unused_variable_warning(v);
199 suppress_unused_variable_warning(v);
203 suppress_unused_variable_warning(v);
204 v = cdf(complement(dist, ld));
205 suppress_unused_variable_warning(v);
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);
215 suppress_unused_variable_warning(v);
219 suppress_unused_variable_warning(v);
220 v = cdf(complement(dist, i));
221 suppress_unused_variable_warning(v);
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);
229 suppress_unused_variable_warning(v);
231 suppress_unused_variable_warning(v);
232 unsigned long li = 1;
234 suppress_unused_variable_warning(v);
235 v = cdf(complement(dist, li));
236 suppress_unused_variable_warning(v);
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);
246 suppress_unused_variable_warning(v);
247 test_extra_members(dist);
250 static void test_extra_members(const D&)
252 template <class R, class P>
253 static void test_extra_members(const boost::math::bernoulli_distribution<R, P>& d)
255 value_type r = d.success_fraction();
256 (void)r; // warning suppression
258 template <class R, class P>
259 static void test_extra_members(const boost::math::beta_distribution<R, P>& d)
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);
272 template <class R, class P>
273 static void test_extra_members(const boost::math::binomial_distribution<R, P>& d)
275 value_type r = d.success_fraction();
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);
287 template <class R, class P>
288 static void test_extra_members(const boost::math::cauchy_distribution<R, P>& d)
290 value_type r = d.location();
292 suppress_unused_variable_warning(r);
294 template <class R, class P>
295 static void test_extra_members(const boost::math::chi_squared_distribution<R, P>& d)
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);
302 template <class R, class P>
303 static void test_extra_members(const boost::math::exponential_distribution<R, P>& d)
305 value_type r = d.lambda();
306 suppress_unused_variable_warning(r);
308 template <class R, class P>
309 static void test_extra_members(const boost::math::extreme_value_distribution<R, P>& d)
311 value_type r = d.scale();
313 suppress_unused_variable_warning(r);
315 template <class R, class P>
316 static void test_extra_members(const boost::math::fisher_f_distribution<R, P>& d)
318 value_type r = d.degrees_of_freedom1();
319 r = d.degrees_of_freedom2();
320 suppress_unused_variable_warning(r);
322 template <class R, class P>
323 static void test_extra_members(const boost::math::gamma_distribution<R, P>& d)
325 value_type r = d.scale();
327 suppress_unused_variable_warning(r);
329 template <class R, class P>
330 static void test_extra_members(const boost::math::inverse_chi_squared_distribution<R, P>& d)
332 value_type r = d.scale();
333 r = d.degrees_of_freedom();
334 suppress_unused_variable_warning(r);
336 template <class R, class P>
337 static void test_extra_members(const boost::math::inverse_gamma_distribution<R, P>& d)
339 value_type r = d.scale();
341 suppress_unused_variable_warning(r);
343 template <class R, class P>
344 static void test_extra_members(const boost::math::hypergeometric_distribution<R, P>& d)
346 unsigned u = d.defective();
347 u = d.sample_count();
349 suppress_unused_variable_warning(u);
351 template <class R, class P>
352 static void test_extra_members(const boost::math::laplace_distribution<R, P>& d)
354 value_type r = d.scale();
356 suppress_unused_variable_warning(r);
358 template <class R, class P>
359 static void test_extra_members(const boost::math::logistic_distribution<R, P>& d)
361 value_type r = d.scale();
363 suppress_unused_variable_warning(r);
365 template <class R, class P>
366 static void test_extra_members(const boost::math::lognormal_distribution<R, P>& d)
368 value_type r = d.scale();
370 suppress_unused_variable_warning(r);
372 template <class R, class P>
373 static void test_extra_members(const boost::math::negative_binomial_distribution<R, P>& d)
375 value_type r = d.success_fraction();
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);
383 template <class R, class P>
384 static void test_extra_members(const boost::math::non_central_beta_distribution<R, P>& d)
386 value_type r1 = d.alpha();
387 value_type r2 = d.beta();
388 r1 = d.non_centrality();
389 (void)r1; // warning suppression
390 (void)r2; // warning suppression
392 template <class R, class P>
393 static void test_extra_members(const boost::math::non_central_chi_squared_distribution<R, P>& d)
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 suppression
403 template <class R, class P>
404 static void test_extra_members(const boost::math::non_central_f_distribution<R, P>& d)
406 value_type r = d.degrees_of_freedom1();
407 r = d.degrees_of_freedom2();
408 r = d.non_centrality();
409 (void)r; // warning suppression
411 template <class R, class P>
412 static void test_extra_members(const boost::math::non_central_t_distribution<R, P>& d)
414 value_type r = d.degrees_of_freedom();
415 r = d.non_centrality();
416 (void)r; // warning suppression
418 template <class R, class P>
419 static void test_extra_members(const boost::math::normal_distribution<R, P>& d)
421 value_type r = d.scale();
424 r = d.standard_deviation();
425 (void)r; // warning suppression
427 template <class R, class P>
428 static void test_extra_members(const boost::math::pareto_distribution<R, P>& d)
430 value_type r = d.scale();
432 (void)r; // warning suppression
434 template <class R, class P>
435 static void test_extra_members(const boost::math::poisson_distribution<R, P>& d)
437 value_type r = d.mean();
438 (void)r; // warning suppression
440 template <class R, class P>
441 static void test_extra_members(const boost::math::rayleigh_distribution<R, P>& d)
443 value_type r = d.sigma();
444 (void)r; // warning suppression
446 template <class R, class P>
447 static void test_extra_members(const boost::math::students_t_distribution<R, P>& d)
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 suppression
454 template <class R, class P>
455 static void test_extra_members(const boost::math::triangular_distribution<R, P>& d)
457 value_type r = d.lower();
460 (void)r; // warning suppression
462 template <class R, class P>
463 static void test_extra_members(const boost::math::weibull_distribution<R, P>& d)
465 value_type r = d.scale();
467 (void)r; // warning suppression
469 template <class R, class P>
470 static void test_extra_members(const boost::math::uniform_distribution<R, P>& d)
472 value_type r = d.lower();
474 (void)r; // warning suppression
477 static Distribution* pd;
478 static Distribution& get_object()
480 // In reality this will never get called:
483 }; // struct DistributionConcept
485 template <class Distribution>
486 Distribution* DistributionConcept<Distribution>::pd = 0;
488 } // namespace concepts
493 #error This header can not be used in standalone mode.
494 #endif // BOOST_MATH_STANDALONE
496 #endif // BOOST_MATH_DISTRIBUTION_CONCEPT_HPP