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