Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:39:40

0001 //  Copyright John Maddock 2007.
0002 //  Copyright Paul A. Bristow 2007.
0003 
0004 //  Use, modification and distribution are subject to the
0005 //  Boost Software License, Version 1.0. (See accompanying file
0006 //  LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
0007 
0008 #ifndef BOOST_STATS_FIND_SCALE_HPP
0009 #define BOOST_STATS_FIND_SCALE_HPP
0010 
0011 #include <boost/math/distributions/fwd.hpp> // for all distribution signatures.
0012 #include <boost/math/distributions/complement.hpp>
0013 #include <boost/math/policies/policy.hpp>
0014 // using boost::math::policies::policy;
0015 #include <boost/math/tools/traits.hpp>
0016 #include <boost/math/tools/assert.hpp>
0017 #include <boost/math/special_functions/fpclassify.hpp>
0018 #include <boost/math/policies/error_handling.hpp>
0019 // using boost::math::complement; // will be needed by users who want complement,
0020 // but NOT placed here to avoid putting it in global scope.
0021 
0022 namespace boost
0023 {
0024   namespace math
0025   {
0026     // Function to find location of random variable z
0027     // to give probability p (given scale)
0028     // Applies to normal, lognormal, extreme value, Cauchy, (and symmetrical triangular),
0029     // distributions that have scale.
0030     // BOOST_STATIC_ASSERTs, see below, are used to enforce this.
0031 
0032     template <class Dist, class Policy>
0033     inline
0034       typename Dist::value_type find_scale( // For example, normal mean.
0035       typename Dist::value_type z, // location of random variable z to give probability, P(X > z) == p.
0036       // For example, a nominal minimum acceptable weight z, so that p * 100 % are > z
0037       typename Dist::value_type p, // probability value desired at x, say 0.95 for 95% > z.
0038       typename Dist::value_type location, // location parameter, for example, normal distribution mean.
0039       const Policy& pol 
0040       )
0041     {
0042       static_assert(::boost::math::tools::is_distribution<Dist>::value, "The provided distribution does not meet the conceptual requirements of a distribution."); 
0043       static_assert(::boost::math::tools::is_scaled_distribution<Dist>::value, "The provided distribution does not meet the conceptual requirements of a scaled distribution."); 
0044       static const char* function = "boost::math::find_scale<Dist, Policy>(%1%, %1%, %1%, Policy)";
0045 
0046       if(!(boost::math::isfinite)(p) || (p < 0) || (p > 1))
0047       {
0048         return policies::raise_domain_error<typename Dist::value_type>(
0049           function, "Probability parameter was %1%, but must be >= 0 and <= 1!", p, pol);
0050       }
0051       if(!(boost::math::isfinite)(z))
0052       {
0053         return policies::raise_domain_error<typename Dist::value_type>(
0054           function, "find_scale z parameter was %1%, but must be finite!", z, pol);
0055       }
0056       if(!(boost::math::isfinite)(location))
0057       {
0058         return policies::raise_domain_error<typename Dist::value_type>(
0059           function, "find_scale location parameter was %1%, but must be finite!", location, pol);
0060       }
0061 
0062       //cout << "z " << z << ", p " << p << ",  quantile(Dist(), p) "
0063       //<< quantile(Dist(), p) << ", z - mean " << z - location 
0064       //<<", sd " << (z - location)  / quantile(Dist(), p) << endl;
0065 
0066       //quantile(N01, 0.001) -3.09023
0067       //quantile(N01, 0.01) -2.32635
0068       //quantile(N01, 0.05) -1.64485
0069       //quantile(N01, 0.333333) -0.430728
0070       //quantile(N01, 0.5) 0  
0071       //quantile(N01, 0.666667) 0.430728
0072       //quantile(N01, 0.9) 1.28155
0073       //quantile(N01, 0.95) 1.64485
0074       //quantile(N01, 0.99) 2.32635
0075       //quantile(N01, 0.999) 3.09023
0076 
0077       typename Dist::value_type result = 
0078         (z - location)  // difference between desired x and current location.
0079         / quantile(Dist(), p); // standard distribution.
0080 
0081       if (result <= 0)
0082       { // If policy isn't to throw, return the scale <= 0.
0083         policies::raise_evaluation_error<typename Dist::value_type>(function,
0084           "Computed scale (%1%) is <= 0!" " Was the complement intended?",
0085           result, Policy());
0086       }
0087       return result;
0088     } // template <class Dist, class Policy> find_scale
0089 
0090     template <class Dist>
0091     inline // with default policy.
0092       typename Dist::value_type find_scale( // For example, normal mean.
0093       typename Dist::value_type z, // location of random variable z to give probability, P(X > z) == p.
0094       // For example, a nominal minimum acceptable z, so that p * 100 % are > z
0095       typename Dist::value_type p, // probability value desired at x, say 0.95 for 95% > z.
0096       typename Dist::value_type location) // location parameter, for example, mean.
0097     { // Forward to find_scale using the default policy.
0098       return (find_scale<Dist>(z, p, location, policies::policy<>()));
0099     } // find_scale
0100 
0101     template <class Dist, class Real1, class Real2, class Real3, class Policy>
0102     inline typename Dist::value_type find_scale(
0103       complemented4_type<Real1, Real2, Real3, Policy> const& c)
0104     {
0105       //cout << "cparam1 q " << c.param1 // q
0106       //  << ", c.dist z " << c.dist // z
0107       //  << ", c.param2 l " << c.param2 // l
0108       //  << ", quantile (Dist(), c.param1 = q) "
0109       //  << quantile(Dist(), c.param1) //q
0110       //  << endl;
0111 
0112       static_assert(::boost::math::tools::is_distribution<Dist>::value, "The provided distribution does not meet the conceptual requirements of a distribution."); 
0113       static_assert(::boost::math::tools::is_scaled_distribution<Dist>::value, "The provided distribution does not meet the conceptual requirements of a scaled distribution."); 
0114       static const char* function = "boost::math::find_scale<Dist, Policy>(complement(%1%, %1%, %1%, Policy))";
0115 
0116       // Checks on arguments, as not complemented version,
0117       // Explicit policy.
0118       typename Dist::value_type q = c.param1;
0119       if(!(boost::math::isfinite)(q) || (q < 0) || (q > 1))
0120       {
0121         return policies::raise_domain_error<typename Dist::value_type>(
0122           function, "Probability parameter was %1%, but must be >= 0 and <= 1!", q, c.param3);
0123       }
0124       typename Dist::value_type z = c.dist;
0125       if(!(boost::math::isfinite)(z))
0126       {
0127         return policies::raise_domain_error<typename Dist::value_type>(
0128           function, "find_scale z parameter was %1%, but must be finite!", z, c.param3);
0129       }
0130       typename Dist::value_type location = c.param2;
0131       if(!(boost::math::isfinite)(location))
0132       {
0133         return policies::raise_domain_error<typename Dist::value_type>(
0134           function, "find_scale location parameter was %1%, but must be finite!", location, c.param3);
0135       }
0136 
0137       typename Dist::value_type result = 
0138         (c.dist - c.param2)  // difference between desired x and current location.
0139         / quantile(complement(Dist(), c.param1));
0140       //     (  z    - location) / (quantile(complement(Dist(),  q)) 
0141       if (result <= 0)
0142       { // If policy isn't to throw, return the scale <= 0.
0143         policies::raise_evaluation_error<typename Dist::value_type>(function,
0144           "Computed scale (%1%) is <= 0!" " Was the complement intended?",
0145           result, Policy());
0146       }
0147       return result;
0148     } // template <class Dist, class Policy, class Real1, class Real2, class Real3> typename Dist::value_type find_scale
0149 
0150     // So the user can start from the complement q = (1 - p) of the probability p,
0151     // for example, s = find_scale<normal>(complement(z, q, l));
0152 
0153     template <class Dist, class Real1, class Real2, class Real3>
0154     inline typename Dist::value_type find_scale(
0155       complemented3_type<Real1, Real2, Real3> const& c)
0156     {
0157       //cout << "cparam1 q " << c.param1 // q
0158       //  << ", c.dist z " << c.dist // z
0159       //  << ", c.param2 l " << c.param2 // l
0160       //  << ", quantile (Dist(), c.param1 = q) "
0161       //  << quantile(Dist(), c.param1) //q
0162       //  << endl;
0163 
0164       static_assert(::boost::math::tools::is_distribution<Dist>::value, "The provided distribution does not meet the conceptual requirements of a distribution."); 
0165       static_assert(::boost::math::tools::is_scaled_distribution<Dist>::value, "The provided distribution does not meet the conceptual requirements of a scaled distribution.");  
0166       static const char* function = "boost::math::find_scale<Dist, Policy>(complement(%1%, %1%, %1%, Policy))";
0167 
0168       // Checks on arguments, as not complemented version,
0169       // default policy policies::policy<>().
0170       typename Dist::value_type q = c.param1;
0171       if(!(boost::math::isfinite)(q) || (q < 0) || (q > 1))
0172       {
0173         return policies::raise_domain_error<typename Dist::value_type>(
0174           function, "Probability parameter was %1%, but must be >= 0 and <= 1!", q, policies::policy<>());
0175       }
0176       typename Dist::value_type z = c.dist;
0177       if(!(boost::math::isfinite)(z))
0178       {
0179         return policies::raise_domain_error<typename Dist::value_type>(
0180           function, "find_scale z parameter was %1%, but must be finite!", z, policies::policy<>());
0181       }
0182       typename Dist::value_type location = c.param2;
0183       if(!(boost::math::isfinite)(location))
0184       {
0185         return policies::raise_domain_error<typename Dist::value_type>(
0186           function, "find_scale location parameter was %1%, but must be finite!", location, policies::policy<>());
0187       }
0188 
0189       typename Dist::value_type result = 
0190         (z - location)  // difference between desired x and current location.
0191         / quantile(complement(Dist(), q));
0192       //     (  z    - location) / (quantile(complement(Dist(),  q)) 
0193       if (result <= 0)
0194       { // If policy isn't to throw, return the scale <= 0.
0195         policies::raise_evaluation_error<typename Dist::value_type>(function,
0196           "Computed scale (%1%) is <= 0!" " Was the complement intended?",
0197           result, policies::policy<>()); // This is only the default policy - also Want a version with Policy here.
0198       }
0199       return result;
0200     } // template <class Dist, class Real1, class Real2, class Real3> typename Dist::value_type find_scale
0201 
0202   } // namespace boost
0203 } // namespace math
0204 
0205 #endif // BOOST_STATS_FIND_SCALE_HPP