File indexing completed on 2025-09-18 08:48:30
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #ifndef BOOST_MATH_SPECIAL_NON_CENTRAL_F_HPP
0011 #define BOOST_MATH_SPECIAL_NON_CENTRAL_F_HPP
0012
0013 #include <boost/math/tools/config.hpp>
0014 #include <boost/math/tools/tuple.hpp>
0015 #include <boost/math/tools/promotion.hpp>
0016 #include <boost/math/distributions/non_central_beta.hpp>
0017 #include <boost/math/distributions/detail/generic_mode.hpp>
0018 #include <boost/math/special_functions/pow.hpp>
0019 #include <boost/math/policies/policy.hpp>
0020
0021 namespace boost
0022 {
0023 namespace math
0024 {
0025 template <class RealType = double, class Policy = policies::policy<> >
0026 class non_central_f_distribution
0027 {
0028 public:
0029 typedef RealType value_type;
0030 typedef Policy policy_type;
0031
0032 BOOST_MATH_GPU_ENABLED non_central_f_distribution(RealType v1_, RealType v2_, RealType lambda) : v1(v1_), v2(v2_), ncp(lambda)
0033 {
0034 constexpr auto function = "boost::math::non_central_f_distribution<%1%>::non_central_f_distribution(%1%,%1%)";
0035 RealType r;
0036 detail::check_df(
0037 function,
0038 v1, &r, Policy());
0039 detail::check_df(
0040 function,
0041 v2, &r, Policy());
0042 detail::check_non_centrality(
0043 function,
0044 lambda,
0045 &r,
0046 Policy());
0047 }
0048
0049 BOOST_MATH_GPU_ENABLED RealType degrees_of_freedom1()const
0050 {
0051 return v1;
0052 }
0053 BOOST_MATH_GPU_ENABLED RealType degrees_of_freedom2()const
0054 {
0055 return v2;
0056 }
0057 BOOST_MATH_GPU_ENABLED RealType non_centrality() const
0058 {
0059 return ncp;
0060 }
0061 private:
0062
0063 RealType v1;
0064 RealType v2;
0065 RealType ncp;
0066 };
0067
0068 typedef non_central_f_distribution<double> non_central_f;
0069
0070 #ifdef __cpp_deduction_guides
0071 template <class RealType>
0072 non_central_f_distribution(RealType,RealType,RealType)->non_central_f_distribution<typename boost::math::tools::promote_args<RealType>::type>;
0073 #endif
0074
0075
0076
0077 template <class RealType, class Policy>
0078 BOOST_MATH_GPU_ENABLED inline const boost::math::pair<RealType, RealType> range(const non_central_f_distribution<RealType, Policy>& )
0079 {
0080 using boost::math::tools::max_value;
0081 return boost::math::pair<RealType, RealType>(static_cast<RealType>(0), max_value<RealType>());
0082 }
0083
0084 template <class RealType, class Policy>
0085 BOOST_MATH_GPU_ENABLED inline const boost::math::pair<RealType, RealType> support(const non_central_f_distribution<RealType, Policy>& )
0086 {
0087
0088 using boost::math::tools::max_value;
0089 return boost::math::pair<RealType, RealType>(static_cast<RealType>(0), max_value<RealType>());
0090 }
0091
0092 template <class RealType, class Policy>
0093 BOOST_MATH_GPU_ENABLED inline RealType mean(const non_central_f_distribution<RealType, Policy>& dist)
0094 {
0095 constexpr auto function = "mean(non_central_f_distribution<%1%> const&)";
0096 RealType v1 = dist.degrees_of_freedom1();
0097 RealType v2 = dist.degrees_of_freedom2();
0098 RealType l = dist.non_centrality();
0099 RealType r;
0100 if(!detail::check_df(
0101 function,
0102 v1, &r, Policy())
0103 ||
0104 !detail::check_df(
0105 function,
0106 v2, &r, Policy())
0107 ||
0108 !detail::check_non_centrality(
0109 function,
0110 l,
0111 &r,
0112 Policy()))
0113 return r;
0114 if(v2 <= 2)
0115 return policies::raise_domain_error(
0116 function,
0117 "Second degrees of freedom parameter was %1%, but must be > 2 !",
0118 v2, Policy());
0119 return v2 * (v1 + l) / (v1 * (v2 - 2));
0120 }
0121
0122 template <class RealType, class Policy>
0123 BOOST_MATH_GPU_ENABLED inline RealType mode(const non_central_f_distribution<RealType, Policy>& dist)
0124 {
0125 constexpr auto function = "mode(non_central_chi_squared_distribution<%1%> const&)";
0126
0127 RealType n = dist.degrees_of_freedom1();
0128 RealType m = dist.degrees_of_freedom2();
0129 RealType l = dist.non_centrality();
0130 RealType r;
0131 if(!detail::check_df(
0132 function,
0133 n, &r, Policy())
0134 ||
0135 !detail::check_df(
0136 function,
0137 m, &r, Policy())
0138 ||
0139 !detail::check_non_centrality(
0140 function,
0141 l,
0142 &r,
0143 Policy()))
0144 return r;
0145 RealType guess = m > 2 ? RealType(m * (n + l) / (n * (m - 2))) : RealType(1);
0146 return detail::generic_find_mode(
0147 dist,
0148 guess,
0149 function);
0150 }
0151
0152 template <class RealType, class Policy>
0153 BOOST_MATH_GPU_ENABLED inline RealType variance(const non_central_f_distribution<RealType, Policy>& dist)
0154 {
0155 constexpr auto function = "variance(non_central_f_distribution<%1%> const&)";
0156 RealType n = dist.degrees_of_freedom1();
0157 RealType m = dist.degrees_of_freedom2();
0158 RealType l = dist.non_centrality();
0159 RealType r;
0160 if(!detail::check_df(
0161 function,
0162 n, &r, Policy())
0163 ||
0164 !detail::check_df(
0165 function,
0166 m, &r, Policy())
0167 ||
0168 !detail::check_non_centrality(
0169 function,
0170 l,
0171 &r,
0172 Policy()))
0173 return r;
0174 if(m <= 4)
0175 return policies::raise_domain_error(
0176 function,
0177 "Second degrees of freedom parameter was %1%, but must be > 4 !",
0178 m, Policy());
0179 RealType result = 2 * m * m * ((n + l) * (n + l)
0180 + (m - 2) * (n + 2 * l));
0181 result /= (m - 4) * (m - 2) * (m - 2) * n * n;
0182 return result;
0183 }
0184
0185
0186
0187
0188 template <class RealType, class Policy>
0189 BOOST_MATH_GPU_ENABLED inline RealType skewness(const non_central_f_distribution<RealType, Policy>& dist)
0190 {
0191 constexpr auto function = "skewness(non_central_f_distribution<%1%> const&)";
0192 BOOST_MATH_STD_USING
0193 RealType n = dist.degrees_of_freedom1();
0194 RealType m = dist.degrees_of_freedom2();
0195 RealType l = dist.non_centrality();
0196 RealType r;
0197 if(!detail::check_df(
0198 function,
0199 n, &r, Policy())
0200 ||
0201 !detail::check_df(
0202 function,
0203 m, &r, Policy())
0204 ||
0205 !detail::check_non_centrality(
0206 function,
0207 l,
0208 &r,
0209 Policy()))
0210 return r;
0211 if(m <= 6)
0212 return policies::raise_domain_error(
0213 function,
0214 "Second degrees of freedom parameter was %1%, but must be > 6 !",
0215 m, Policy());
0216 RealType result = 2 * constants::root_two<RealType>();
0217 result *= sqrt(m - 4);
0218 result *= (n * (m + n - 2) *(m + 2 * n - 2)
0219 + 3 * (m + n - 2) * (m + 2 * n - 2) * l
0220 + 6 * (m + n - 2) * l * l + 2 * l * l * l);
0221 result /= (m - 6) * pow(n * (m + n - 2) + 2 * (m + n - 2) * l + l * l, RealType(1.5f));
0222 return result;
0223 }
0224
0225 template <class RealType, class Policy>
0226 BOOST_MATH_GPU_ENABLED inline RealType kurtosis_excess(const non_central_f_distribution<RealType, Policy>& dist)
0227 {
0228 constexpr auto function = "kurtosis_excess(non_central_f_distribution<%1%> const&)";
0229 BOOST_MATH_STD_USING
0230 RealType n = dist.degrees_of_freedom1();
0231 RealType m = dist.degrees_of_freedom2();
0232 RealType l = dist.non_centrality();
0233 RealType r;
0234 if(!detail::check_df(
0235 function,
0236 n, &r, Policy())
0237 ||
0238 !detail::check_df(
0239 function,
0240 m, &r, Policy())
0241 ||
0242 !detail::check_non_centrality(
0243 function,
0244 l,
0245 &r,
0246 Policy()))
0247 return r;
0248 if(m <= 8)
0249 return policies::raise_domain_error(
0250 function,
0251 "Second degrees of freedom parameter was %1%, but must be > 8 !",
0252 m, Policy());
0253 RealType l2 = l * l;
0254 RealType l3 = l2 * l;
0255 RealType l4 = l2 * l2;
0256 RealType result = (3 * (m - 4) * (n * (m + n - 2)
0257 * (4 * (m - 2) * (m - 2)
0258 + (m - 2) * (m + 10) * n
0259 + (10 + m) * n * n)
0260 + 4 * (m + n - 2) * (4 * (m - 2) * (m - 2)
0261 + (m - 2) * (10 + m) * n
0262 + (10 + m) * n * n) * l + 2 * (10 + m)
0263 * (m + n - 2) * (2 * m + 3 * n - 4) * l2
0264 + 4 * (10 + m) * (-2 + m + n) * l3
0265 + (10 + m) * l4))
0266 /
0267 ((-8 + m) * (-6 + m) * boost::math::pow<2>(n * (-2 + m + n)
0268 + 2 * (-2 + m + n) * l + l2));
0269 return result;
0270 }
0271
0272 template <class RealType, class Policy>
0273 BOOST_MATH_GPU_ENABLED inline RealType kurtosis(const non_central_f_distribution<RealType, Policy>& dist)
0274 {
0275 return kurtosis_excess(dist) + 3;
0276 }
0277
0278 template <class RealType, class Policy>
0279 BOOST_MATH_GPU_ENABLED inline RealType pdf(const non_central_f_distribution<RealType, Policy>& dist, const RealType& x)
0280 {
0281 typedef typename policies::evaluation<RealType, Policy>::type value_type;
0282 typedef typename policies::normalise<
0283 Policy,
0284 policies::promote_float<false>,
0285 policies::promote_double<false>,
0286 policies::discrete_quantile<>,
0287 policies::assert_undefined<> >::type forwarding_policy;
0288
0289 value_type alpha = dist.degrees_of_freedom1() / 2;
0290 value_type beta = dist.degrees_of_freedom2() / 2;
0291 value_type y = x * alpha / beta;
0292 value_type r = pdf(boost::math::non_central_beta_distribution<value_type, forwarding_policy>(alpha, beta, dist.non_centrality()), y / (1 + y));
0293 return policies::checked_narrowing_cast<RealType, forwarding_policy>(
0294 r * (dist.degrees_of_freedom1() / dist.degrees_of_freedom2()) / ((1 + y) * (1 + y)),
0295 "pdf(non_central_f_distribution<%1%>, %1%)");
0296 }
0297
0298 template <class RealType, class Policy>
0299 BOOST_MATH_GPU_ENABLED RealType cdf(const non_central_f_distribution<RealType, Policy>& dist, const RealType& x)
0300 {
0301 constexpr auto function = "cdf(const non_central_f_distribution<%1%>&, %1%)";
0302 RealType r;
0303 if(!detail::check_df(
0304 function,
0305 dist.degrees_of_freedom1(), &r, Policy())
0306 ||
0307 !detail::check_df(
0308 function,
0309 dist.degrees_of_freedom2(), &r, Policy())
0310 ||
0311 !detail::check_non_centrality(
0312 function,
0313 dist.non_centrality(),
0314 &r,
0315 Policy()))
0316 return r;
0317
0318 if((x < 0) || !(boost::math::isfinite)(x))
0319 {
0320 return policies::raise_domain_error<RealType>(
0321 function, "Random Variable parameter was %1%, but must be > 0 !", x, Policy());
0322 }
0323
0324 RealType alpha = dist.degrees_of_freedom1() / 2;
0325 RealType beta = dist.degrees_of_freedom2() / 2;
0326 RealType y = x * alpha / beta;
0327 RealType c = y / (1 + y);
0328 RealType cp = 1 / (1 + y);
0329
0330
0331
0332
0333
0334 r = detail::non_central_beta_cdf(c, cp, alpha, beta,
0335 dist.non_centrality(), false, Policy());
0336 return r;
0337 }
0338
0339 template <class RealType, class Policy>
0340 BOOST_MATH_GPU_ENABLED RealType cdf(const complemented2_type<non_central_f_distribution<RealType, Policy>, RealType>& c)
0341 {
0342 constexpr auto function = "cdf(complement(const non_central_f_distribution<%1%>&, %1%))";
0343 RealType r;
0344 if(!detail::check_df(
0345 function,
0346 c.dist.degrees_of_freedom1(), &r, Policy())
0347 ||
0348 !detail::check_df(
0349 function,
0350 c.dist.degrees_of_freedom2(), &r, Policy())
0351 ||
0352 !detail::check_non_centrality(
0353 function,
0354 c.dist.non_centrality(),
0355 &r,
0356 Policy()))
0357 return r;
0358
0359 if((c.param < 0) || !(boost::math::isfinite)(c.param))
0360 {
0361 return policies::raise_domain_error<RealType>(
0362 function, "Random Variable parameter was %1%, but must be > 0 !", c.param, Policy());
0363 }
0364
0365 RealType alpha = c.dist.degrees_of_freedom1() / 2;
0366 RealType beta = c.dist.degrees_of_freedom2() / 2;
0367 RealType y = c.param * alpha / beta;
0368 RealType x = y / (1 + y);
0369 RealType cx = 1 / (1 + y);
0370
0371
0372
0373
0374
0375 r = detail::non_central_beta_cdf(x, cx, alpha, beta,
0376 c.dist.non_centrality(), true, Policy());
0377 return r;
0378 }
0379
0380 template <class RealType, class Policy>
0381 BOOST_MATH_GPU_ENABLED inline RealType quantile(const non_central_f_distribution<RealType, Policy>& dist, const RealType& p)
0382 {
0383 RealType alpha = dist.degrees_of_freedom1() / 2;
0384 RealType beta = dist.degrees_of_freedom2() / 2;
0385 RealType x = quantile(boost::math::non_central_beta_distribution<RealType, Policy>(alpha, beta, dist.non_centrality()), p);
0386 if(x == 1)
0387 return policies::raise_overflow_error<RealType>(
0388 "quantile(const non_central_f_distribution<%1%>&, %1%)",
0389 "Result of non central F quantile is too large to represent.",
0390 Policy());
0391 return (x / (1 - x)) * (dist.degrees_of_freedom2() / dist.degrees_of_freedom1());
0392 }
0393
0394 template <class RealType, class Policy>
0395 BOOST_MATH_GPU_ENABLED inline RealType quantile(const complemented2_type<non_central_f_distribution<RealType, Policy>, RealType>& c)
0396 {
0397 RealType alpha = c.dist.degrees_of_freedom1() / 2;
0398 RealType beta = c.dist.degrees_of_freedom2() / 2;
0399 RealType x = quantile(complement(boost::math::non_central_beta_distribution<RealType, Policy>(alpha, beta, c.dist.non_centrality()), c.param));
0400 if(x == 1)
0401 return policies::raise_overflow_error<RealType>(
0402 "quantile(complement(const non_central_f_distribution<%1%>&, %1%))",
0403 "Result of non central F quantile is too large to represent.",
0404 Policy());
0405 return (x / (1 - x)) * (c.dist.degrees_of_freedom2() / c.dist.degrees_of_freedom1());
0406 }
0407
0408 }
0409 }
0410
0411
0412
0413
0414 #include <boost/math/distributions/detail/derived_accessors.hpp>
0415
0416 #endif
0417
0418
0419