]>
Commit | Line | Data |
---|---|---|
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: | |
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 | ||
122 | 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> | |
248 | static void test_extra_members(const D&) | |
249 | {} | |
250 | template <class R, class P> | |
251 | 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> | |
257 | 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> | |
271 | 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> | |
286 | 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> | |
293 | 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> | |
301 | 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> | |
307 | 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> | |
314 | 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> | |
321 | 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> | |
328 | 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> | |
335 | 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> | |
342 | 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> | |
350 | 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> | |
357 | 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> | |
364 | 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> | |
371 | 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> | |
382 | 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> | |
391 | 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> | |
402 | 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> | |
410 | 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> | |
417 | 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> | |
426 | 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> | |
433 | 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> | |
439 | 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> | |
445 | 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> | |
453 | 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> | |
461 | 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> | |
468 | 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; | |
476 | 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 |