123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410 |
- // boost\math\distributions\non_central_f.hpp
- // Copyright John Maddock 2008.
- // Use, modification and distribution are subject to the
- // Boost Software License, Version 1.0.
- // (See accompanying file LICENSE_1_0.txt
- // or copy at http://www.boost.org/LICENSE_1_0.txt)
- #ifndef BOOST_MATH_SPECIAL_NON_CENTRAL_F_HPP
- #define BOOST_MATH_SPECIAL_NON_CENTRAL_F_HPP
- #include <boost/math/distributions/non_central_beta.hpp>
- #include <boost/math/distributions/detail/generic_mode.hpp>
- #include <boost/math/special_functions/pow.hpp>
- namespace boost
- {
- namespace math
- {
- template <class RealType = double, class Policy = policies::policy<> >
- class non_central_f_distribution
- {
- public:
- typedef RealType value_type;
- typedef Policy policy_type;
- non_central_f_distribution(RealType v1_, RealType v2_, RealType lambda) : v1(v1_), v2(v2_), ncp(lambda)
- {
- const char* function = "boost::math::non_central_f_distribution<%1%>::non_central_f_distribution(%1%,%1%)";
- RealType r;
- detail::check_df(
- function,
- v1, &r, Policy());
- detail::check_df(
- function,
- v2, &r, Policy());
- detail::check_non_centrality(
- function,
- lambda,
- &r,
- Policy());
- } // non_central_f_distribution constructor.
- RealType degrees_of_freedom1()const
- {
- return v1;
- }
- RealType degrees_of_freedom2()const
- {
- return v2;
- }
- RealType non_centrality() const
- { // Private data getter function.
- return ncp;
- }
- private:
- // Data member, initialized by constructor.
- RealType v1; // alpha.
- RealType v2; // beta.
- RealType ncp; // non-centrality parameter
- }; // template <class RealType, class Policy> class non_central_f_distribution
- typedef non_central_f_distribution<double> non_central_f; // Reserved name of type double.
- // Non-member functions to give properties of the distribution.
- template <class RealType, class Policy>
- inline const std::pair<RealType, RealType> range(const non_central_f_distribution<RealType, Policy>& /* dist */)
- { // Range of permissible values for random variable k.
- using boost::math::tools::max_value;
- return std::pair<RealType, RealType>(static_cast<RealType>(0), max_value<RealType>());
- }
- template <class RealType, class Policy>
- inline const std::pair<RealType, RealType> support(const non_central_f_distribution<RealType, Policy>& /* dist */)
- { // Range of supported values for random variable k.
- // This is range where cdf rises from 0 to 1, and outside it, the pdf is zero.
- using boost::math::tools::max_value;
- return std::pair<RealType, RealType>(static_cast<RealType>(0), max_value<RealType>());
- }
- template <class RealType, class Policy>
- inline RealType mean(const non_central_f_distribution<RealType, Policy>& dist)
- {
- const char* function = "mean(non_central_f_distribution<%1%> const&)";
- RealType v1 = dist.degrees_of_freedom1();
- RealType v2 = dist.degrees_of_freedom2();
- RealType l = dist.non_centrality();
- RealType r;
- if(!detail::check_df(
- function,
- v1, &r, Policy())
- ||
- !detail::check_df(
- function,
- v2, &r, Policy())
- ||
- !detail::check_non_centrality(
- function,
- l,
- &r,
- Policy()))
- return r;
- if(v2 <= 2)
- return policies::raise_domain_error(
- function,
- "Second degrees of freedom parameter was %1%, but must be > 2 !",
- v2, Policy());
- return v2 * (v1 + l) / (v1 * (v2 - 2));
- } // mean
- template <class RealType, class Policy>
- inline RealType mode(const non_central_f_distribution<RealType, Policy>& dist)
- { // mode.
- static const char* function = "mode(non_central_chi_squared_distribution<%1%> const&)";
- RealType n = dist.degrees_of_freedom1();
- RealType m = dist.degrees_of_freedom2();
- RealType l = dist.non_centrality();
- RealType r;
- if(!detail::check_df(
- function,
- n, &r, Policy())
- ||
- !detail::check_df(
- function,
- m, &r, Policy())
- ||
- !detail::check_non_centrality(
- function,
- l,
- &r,
- Policy()))
- return r;
- RealType guess = m > 2 ? RealType(m * (n + l) / (n * (m - 2))) : RealType(1);
- return detail::generic_find_mode(
- dist,
- guess,
- function);
- }
- template <class RealType, class Policy>
- inline RealType variance(const non_central_f_distribution<RealType, Policy>& dist)
- { // variance.
- const char* function = "variance(non_central_f_distribution<%1%> const&)";
- RealType n = dist.degrees_of_freedom1();
- RealType m = dist.degrees_of_freedom2();
- RealType l = dist.non_centrality();
- RealType r;
- if(!detail::check_df(
- function,
- n, &r, Policy())
- ||
- !detail::check_df(
- function,
- m, &r, Policy())
- ||
- !detail::check_non_centrality(
- function,
- l,
- &r,
- Policy()))
- return r;
- if(m <= 4)
- return policies::raise_domain_error(
- function,
- "Second degrees of freedom parameter was %1%, but must be > 4 !",
- m, Policy());
- RealType result = 2 * m * m * ((n + l) * (n + l)
- + (m - 2) * (n + 2 * l));
- result /= (m - 4) * (m - 2) * (m - 2) * n * n;
- return result;
- }
- // RealType standard_deviation(const non_central_f_distribution<RealType, Policy>& dist)
- // standard_deviation provided by derived accessors.
- template <class RealType, class Policy>
- inline RealType skewness(const non_central_f_distribution<RealType, Policy>& dist)
- { // skewness = sqrt(l).
- const char* function = "skewness(non_central_f_distribution<%1%> const&)";
- BOOST_MATH_STD_USING
- RealType n = dist.degrees_of_freedom1();
- RealType m = dist.degrees_of_freedom2();
- RealType l = dist.non_centrality();
- RealType r;
- if(!detail::check_df(
- function,
- n, &r, Policy())
- ||
- !detail::check_df(
- function,
- m, &r, Policy())
- ||
- !detail::check_non_centrality(
- function,
- l,
- &r,
- Policy()))
- return r;
- if(m <= 6)
- return policies::raise_domain_error(
- function,
- "Second degrees of freedom parameter was %1%, but must be > 6 !",
- m, Policy());
- RealType result = 2 * constants::root_two<RealType>();
- result *= sqrt(m - 4);
- result *= (n * (m + n - 2) *(m + 2 * n - 2)
- + 3 * (m + n - 2) * (m + 2 * n - 2) * l
- + 6 * (m + n - 2) * l * l + 2 * l * l * l);
- result /= (m - 6) * pow(n * (m + n - 2) + 2 * (m + n - 2) * l + l * l, RealType(1.5f));
- return result;
- }
- template <class RealType, class Policy>
- inline RealType kurtosis_excess(const non_central_f_distribution<RealType, Policy>& dist)
- {
- const char* function = "kurtosis_excess(non_central_f_distribution<%1%> const&)";
- BOOST_MATH_STD_USING
- RealType n = dist.degrees_of_freedom1();
- RealType m = dist.degrees_of_freedom2();
- RealType l = dist.non_centrality();
- RealType r;
- if(!detail::check_df(
- function,
- n, &r, Policy())
- ||
- !detail::check_df(
- function,
- m, &r, Policy())
- ||
- !detail::check_non_centrality(
- function,
- l,
- &r,
- Policy()))
- return r;
- if(m <= 8)
- return policies::raise_domain_error(
- function,
- "Second degrees of freedom parameter was %1%, but must be > 8 !",
- m, Policy());
- RealType l2 = l * l;
- RealType l3 = l2 * l;
- RealType l4 = l2 * l2;
- RealType result = (3 * (m - 4) * (n * (m + n - 2)
- * (4 * (m - 2) * (m - 2)
- + (m - 2) * (m + 10) * n
- + (10 + m) * n * n)
- + 4 * (m + n - 2) * (4 * (m - 2) * (m - 2)
- + (m - 2) * (10 + m) * n
- + (10 + m) * n * n) * l + 2 * (10 + m)
- * (m + n - 2) * (2 * m + 3 * n - 4) * l2
- + 4 * (10 + m) * (-2 + m + n) * l3
- + (10 + m) * l4))
- /
- ((-8 + m) * (-6 + m) * boost::math::pow<2>(n * (-2 + m + n)
- + 2 * (-2 + m + n) * l + l2));
- return result;
- } // kurtosis_excess
- template <class RealType, class Policy>
- inline RealType kurtosis(const non_central_f_distribution<RealType, Policy>& dist)
- {
- return kurtosis_excess(dist) + 3;
- }
- template <class RealType, class Policy>
- inline RealType pdf(const non_central_f_distribution<RealType, Policy>& dist, const RealType& x)
- { // Probability Density/Mass Function.
- typedef typename policies::evaluation<RealType, Policy>::type value_type;
- typedef typename policies::normalise<
- Policy,
- policies::promote_float<false>,
- policies::promote_double<false>,
- policies::discrete_quantile<>,
- policies::assert_undefined<> >::type forwarding_policy;
- value_type alpha = dist.degrees_of_freedom1() / 2;
- value_type beta = dist.degrees_of_freedom2() / 2;
- value_type y = x * alpha / beta;
- value_type r = pdf(boost::math::non_central_beta_distribution<value_type, forwarding_policy>(alpha, beta, dist.non_centrality()), y / (1 + y));
- return policies::checked_narrowing_cast<RealType, forwarding_policy>(
- r * (dist.degrees_of_freedom1() / dist.degrees_of_freedom2()) / ((1 + y) * (1 + y)),
- "pdf(non_central_f_distribution<%1%>, %1%)");
- } // pdf
- template <class RealType, class Policy>
- RealType cdf(const non_central_f_distribution<RealType, Policy>& dist, const RealType& x)
- {
- const char* function = "cdf(const non_central_f_distribution<%1%>&, %1%)";
- RealType r;
- if(!detail::check_df(
- function,
- dist.degrees_of_freedom1(), &r, Policy())
- ||
- !detail::check_df(
- function,
- dist.degrees_of_freedom2(), &r, Policy())
- ||
- !detail::check_non_centrality(
- function,
- dist.non_centrality(),
- &r,
- Policy()))
- return r;
- if((x < 0) || !(boost::math::isfinite)(x))
- {
- return policies::raise_domain_error<RealType>(
- function, "Random Variable parameter was %1%, but must be > 0 !", x, Policy());
- }
- RealType alpha = dist.degrees_of_freedom1() / 2;
- RealType beta = dist.degrees_of_freedom2() / 2;
- RealType y = x * alpha / beta;
- RealType c = y / (1 + y);
- RealType cp = 1 / (1 + y);
- //
- // To ensure accuracy, we pass both x and 1-x to the
- // non-central beta cdf routine, this ensures accuracy
- // even when we compute x to be ~ 1:
- //
- r = detail::non_central_beta_cdf(c, cp, alpha, beta,
- dist.non_centrality(), false, Policy());
- return r;
- } // cdf
- template <class RealType, class Policy>
- RealType cdf(const complemented2_type<non_central_f_distribution<RealType, Policy>, RealType>& c)
- { // Complemented Cumulative Distribution Function
- const char* function = "cdf(complement(const non_central_f_distribution<%1%>&, %1%))";
- RealType r;
- if(!detail::check_df(
- function,
- c.dist.degrees_of_freedom1(), &r, Policy())
- ||
- !detail::check_df(
- function,
- c.dist.degrees_of_freedom2(), &r, Policy())
- ||
- !detail::check_non_centrality(
- function,
- c.dist.non_centrality(),
- &r,
- Policy()))
- return r;
- if((c.param < 0) || !(boost::math::isfinite)(c.param))
- {
- return policies::raise_domain_error<RealType>(
- function, "Random Variable parameter was %1%, but must be > 0 !", c.param, Policy());
- }
- RealType alpha = c.dist.degrees_of_freedom1() / 2;
- RealType beta = c.dist.degrees_of_freedom2() / 2;
- RealType y = c.param * alpha / beta;
- RealType x = y / (1 + y);
- RealType cx = 1 / (1 + y);
- //
- // To ensure accuracy, we pass both x and 1-x to the
- // non-central beta cdf routine, this ensures accuracy
- // even when we compute x to be ~ 1:
- //
- r = detail::non_central_beta_cdf(x, cx, alpha, beta,
- c.dist.non_centrality(), true, Policy());
- return r;
- } // ccdf
- template <class RealType, class Policy>
- inline RealType quantile(const non_central_f_distribution<RealType, Policy>& dist, const RealType& p)
- { // Quantile (or Percent Point) function.
- RealType alpha = dist.degrees_of_freedom1() / 2;
- RealType beta = dist.degrees_of_freedom2() / 2;
- RealType x = quantile(boost::math::non_central_beta_distribution<RealType, Policy>(alpha, beta, dist.non_centrality()), p);
- if(x == 1)
- return policies::raise_overflow_error<RealType>(
- "quantile(const non_central_f_distribution<%1%>&, %1%)",
- "Result of non central F quantile is too large to represent.",
- Policy());
- return (x / (1 - x)) * (dist.degrees_of_freedom2() / dist.degrees_of_freedom1());
- } // quantile
- template <class RealType, class Policy>
- inline RealType quantile(const complemented2_type<non_central_f_distribution<RealType, Policy>, RealType>& c)
- { // Quantile (or Percent Point) function.
- RealType alpha = c.dist.degrees_of_freedom1() / 2;
- RealType beta = c.dist.degrees_of_freedom2() / 2;
- RealType x = quantile(complement(boost::math::non_central_beta_distribution<RealType, Policy>(alpha, beta, c.dist.non_centrality()), c.param));
- if(x == 1)
- return policies::raise_overflow_error<RealType>(
- "quantile(complement(const non_central_f_distribution<%1%>&, %1%))",
- "Result of non central F quantile is too large to represent.",
- Policy());
- return (x / (1 - x)) * (c.dist.degrees_of_freedom2() / c.dist.degrees_of_freedom1());
- } // quantile complement.
- } // namespace math
- } // namespace boost
- // This include must be at the end, *after* the accessors
- // for this distribution have been defined, in order to
- // keep compilers that support two-phase lookup happy.
- #include <boost/math/distributions/detail/derived_accessors.hpp>
- #endif // BOOST_MATH_SPECIAL_NON_CENTRAL_F_HPP
|