find_location.hpp 6.3 KB

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