]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | // Copyright John Maddock 2007. |
2 | // Copyright Paul A. Bristow 2007. | |
3 | ||
4 | // Use, modification and distribution are subject to the | |
5 | // Boost Software License, Version 1.0. (See accompanying file | |
6 | // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) | |
7 | ||
8 | #ifndef BOOST_STATS_FIND_LOCATION_HPP | |
9 | #define BOOST_STATS_FIND_LOCATION_HPP | |
10 | ||
11 | #include <boost/math/distributions/fwd.hpp> // for all distribution signatures. | |
12 | #include <boost/math/distributions/complement.hpp> | |
13 | #include <boost/math/policies/policy.hpp> | |
14 | #include <boost/math/tools/traits.hpp> | |
15 | #include <boost/static_assert.hpp> | |
16 | #include <boost/math/special_functions/fpclassify.hpp> | |
17 | #include <boost/math/policies/error_handling.hpp> | |
18 | // using boost::math::policies::policy; | |
19 | // using boost::math::complement; // will be needed by users who want complement, | |
20 | // but NOT placed here to avoid putting it in global scope. | |
21 | ||
22 | namespace boost | |
23 | { | |
24 | namespace math | |
25 | { | |
26 | // Function to find location of random variable z | |
27 | // to give probability p (given scale) | |
28 | // Applies to normal, lognormal, extreme value, Cauchy, (and symmetrical triangular), | |
29 | // enforced by BOOST_STATIC_ASSERT below. | |
30 | ||
31 | template <class Dist, class Policy> | |
32 | inline | |
33 | typename Dist::value_type find_location( // For example, normal mean. | |
34 | typename Dist::value_type z, // location of random variable z to give probability, P(X > z) == p. | |
35 | // For example, a nominal minimum acceptable z, so that p * 100 % are > z | |
36 | typename Dist::value_type p, // probability value desired at x, say 0.95 for 95% > z. | |
37 | typename Dist::value_type scale, // scale parameter, for example, normal standard deviation. | |
38 | const Policy& pol | |
39 | ) | |
40 | { | |
41 | #if !defined(BOOST_NO_SFINAE) && !BOOST_WORKAROUND(__SUNPRO_CC, BOOST_TESTED_AT(0x590)) | |
42 | // Will fail to compile here if try to use with a distribution without scale & location, | |
43 | // for example pareto, and many others. These tests are disabled by the pp-logic | |
44 | // above if the compiler doesn't support the SFINAE tricks used in the traits class. | |
45 | BOOST_STATIC_ASSERT(::boost::math::tools::is_distribution<Dist>::value); | |
46 | BOOST_STATIC_ASSERT(::boost::math::tools::is_scaled_distribution<Dist>::value); | |
47 | #endif | |
48 | static const char* function = "boost::math::find_location<Dist, Policy>&, %1%)"; | |
49 | ||
50 | if(!(boost::math::isfinite)(p) || (p < 0) || (p > 1)) | |
51 | { | |
52 | return policies::raise_domain_error<typename Dist::value_type>( | |
53 | function, "Probability parameter was %1%, but must be >= 0 and <= 1!", p, pol); | |
54 | } | |
55 | if(!(boost::math::isfinite)(z)) | |
56 | { | |
57 | return policies::raise_domain_error<typename Dist::value_type>( | |
58 | function, "z parameter was %1%, but must be finite!", z, pol); | |
59 | } | |
60 | if(!(boost::math::isfinite)(scale)) | |
61 | { | |
62 | return policies::raise_domain_error<typename Dist::value_type>( | |
63 | function, "scale parameter was %1%, but must be finite!", scale, pol); | |
64 | } | |
65 | ||
66 | //cout << "z " << z << ", p " << p << ", quantile(Dist(), p) " | |
67 | // << quantile(Dist(), p) << ", quan * scale " << quantile(Dist(), p) * scale << endl; | |
68 | return z - (quantile(Dist(), p) * scale); | |
69 | } // find_location | |
70 | ||
71 | template <class Dist> | |
72 | inline // with default policy. | |
73 | typename Dist::value_type find_location( // For example, normal mean. | |
74 | typename Dist::value_type z, // location of random variable z to give probability, P(X > z) == p. | |
75 | // For example, a nominal minimum acceptable z, so that p * 100 % are > z | |
76 | typename Dist::value_type p, // probability value desired at x, say 0.95 for 95% > z. | |
77 | typename Dist::value_type scale) // scale parameter, for example, normal standard deviation. | |
78 | { // Forward to find_location with default policy. | |
79 | return (find_location<Dist>(z, p, scale, policies::policy<>())); | |
80 | } // find_location | |
81 | ||
82 | // So the user can start from the complement q = (1 - p) of the probability p, | |
83 | // for example, l = find_location<normal>(complement(z, q, sd)); | |
84 | ||
85 | template <class Dist, class Real1, class Real2, class Real3> | |
86 | inline typename Dist::value_type find_location( // Default policy. | |
87 | complemented3_type<Real1, Real2, Real3> const& c) | |
88 | { | |
89 | static const char* function = "boost::math::find_location<Dist, Policy>&, %1%)"; | |
90 | ||
91 | typename Dist::value_type p = c.param1; | |
92 | if(!(boost::math::isfinite)(p) || (p < 0) || (p > 1)) | |
93 | { | |
94 | return policies::raise_domain_error<typename Dist::value_type>( | |
95 | function, "Probability parameter was %1%, but must be >= 0 and <= 1!", p, policies::policy<>()); | |
96 | } | |
97 | typename Dist::value_type z = c.dist; | |
98 | if(!(boost::math::isfinite)(z)) | |
99 | { | |
100 | return policies::raise_domain_error<typename Dist::value_type>( | |
101 | function, "z parameter was %1%, but must be finite!", z, policies::policy<>()); | |
102 | } | |
103 | typename Dist::value_type scale = c.param2; | |
104 | if(!(boost::math::isfinite)(scale)) | |
105 | { | |
106 | return policies::raise_domain_error<typename Dist::value_type>( | |
107 | function, "scale parameter was %1%, but must be finite!", scale, policies::policy<>()); | |
108 | } | |
109 | // cout << "z " << c.dist << ", quantile (Dist(), " << c.param1 << ") * scale " << c.param2 << endl; | |
110 | return z - quantile(Dist(), p) * scale; | |
111 | } // find_location complement | |
112 | ||
113 | ||
114 | template <class Dist, class Real1, class Real2, class Real3, class Real4> | |
115 | inline typename Dist::value_type find_location( // Explicit policy. | |
116 | complemented4_type<Real1, Real2, Real3, Real4> const& c) | |
117 | { | |
118 | static const char* function = "boost::math::find_location<Dist, Policy>&, %1%)"; | |
119 | ||
120 | typename Dist::value_type p = c.param1; | |
121 | if(!(boost::math::isfinite)(p) || (p < 0) || (p > 1)) | |
122 | { | |
123 | return policies::raise_domain_error<typename Dist::value_type>( | |
124 | function, "Probability parameter was %1%, but must be >= 0 and <= 1!", p, c.param3); | |
125 | } | |
126 | typename Dist::value_type z = c.dist; | |
127 | if(!(boost::math::isfinite)(z)) | |
128 | { | |
129 | return policies::raise_domain_error<typename Dist::value_type>( | |
130 | function, "z parameter was %1%, but must be finite!", z, c.param3); | |
131 | } | |
132 | typename Dist::value_type scale = c.param2; | |
133 | if(!(boost::math::isfinite)(scale)) | |
134 | { | |
135 | return policies::raise_domain_error<typename Dist::value_type>( | |
136 | function, "scale parameter was %1%, but must be finite!", scale, c.param3); | |
137 | } | |
138 | // cout << "z " << c.dist << ", quantile (Dist(), " << c.param1 << ") * scale " << c.param2 << endl; | |
139 | return z - quantile(Dist(), p) * scale; | |
140 | } // find_location complement | |
141 | ||
142 | } // namespace boost | |
143 | } // namespace math | |
144 | ||
145 | #endif // BOOST_STATS_FIND_LOCATION_HPP | |
146 |