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 find_location(typename Dist::value_type z,typename Dist::value_type p,typename Dist::value_type scale,const Policy & pol)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. find_location(typename Dist::value_type z,typename Dist::value_type p,typename Dist::value_type scale)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> find_location(complemented3_type<Real1,Real2,Real3> const & c)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> find_location(complemented4_type<Real1,Real2,Real3,Real4> const & c)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 147