non_central_f.hpp 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410
  1. // boost\math\distributions\non_central_f.hpp
  2. // Copyright John Maddock 2008.
  3. // Use, modification and distribution are subject to the
  4. // Boost Software License, Version 1.0.
  5. // (See accompanying file LICENSE_1_0.txt
  6. // or copy at http://www.boost.org/LICENSE_1_0.txt)
  7. #ifndef BOOST_MATH_SPECIAL_NON_CENTRAL_F_HPP
  8. #define BOOST_MATH_SPECIAL_NON_CENTRAL_F_HPP
  9. #include <boost/math/distributions/non_central_beta.hpp>
  10. #include <boost/math/distributions/detail/generic_mode.hpp>
  11. #include <boost/math/special_functions/pow.hpp>
  12. namespace boost
  13. {
  14. namespace math
  15. {
  16. template <class RealType = double, class Policy = policies::policy<> >
  17. class non_central_f_distribution
  18. {
  19. public:
  20. typedef RealType value_type;
  21. typedef Policy policy_type;
  22. non_central_f_distribution(RealType v1_, RealType v2_, RealType lambda) : v1(v1_), v2(v2_), ncp(lambda)
  23. {
  24. const char* function = "boost::math::non_central_f_distribution<%1%>::non_central_f_distribution(%1%,%1%)";
  25. RealType r;
  26. detail::check_df(
  27. function,
  28. v1, &r, Policy());
  29. detail::check_df(
  30. function,
  31. v2, &r, Policy());
  32. detail::check_non_centrality(
  33. function,
  34. lambda,
  35. &r,
  36. Policy());
  37. } // non_central_f_distribution constructor.
  38. RealType degrees_of_freedom1()const
  39. {
  40. return v1;
  41. }
  42. RealType degrees_of_freedom2()const
  43. {
  44. return v2;
  45. }
  46. RealType non_centrality() const
  47. { // Private data getter function.
  48. return ncp;
  49. }
  50. private:
  51. // Data member, initialized by constructor.
  52. RealType v1; // alpha.
  53. RealType v2; // beta.
  54. RealType ncp; // non-centrality parameter
  55. }; // template <class RealType, class Policy> class non_central_f_distribution
  56. typedef non_central_f_distribution<double> non_central_f; // Reserved name of type double.
  57. // Non-member functions to give properties of the distribution.
  58. template <class RealType, class Policy>
  59. inline const std::pair<RealType, RealType> range(const non_central_f_distribution<RealType, Policy>& /* dist */)
  60. { // Range of permissible values for random variable k.
  61. using boost::math::tools::max_value;
  62. return std::pair<RealType, RealType>(static_cast<RealType>(0), max_value<RealType>());
  63. }
  64. template <class RealType, class Policy>
  65. inline const std::pair<RealType, RealType> support(const non_central_f_distribution<RealType, Policy>& /* dist */)
  66. { // Range of supported values for random variable k.
  67. // This is range where cdf rises from 0 to 1, and outside it, the pdf is zero.
  68. using boost::math::tools::max_value;
  69. return std::pair<RealType, RealType>(static_cast<RealType>(0), max_value<RealType>());
  70. }
  71. template <class RealType, class Policy>
  72. inline RealType mean(const non_central_f_distribution<RealType, Policy>& dist)
  73. {
  74. const char* function = "mean(non_central_f_distribution<%1%> const&)";
  75. RealType v1 = dist.degrees_of_freedom1();
  76. RealType v2 = dist.degrees_of_freedom2();
  77. RealType l = dist.non_centrality();
  78. RealType r;
  79. if(!detail::check_df(
  80. function,
  81. v1, &r, Policy())
  82. ||
  83. !detail::check_df(
  84. function,
  85. v2, &r, Policy())
  86. ||
  87. !detail::check_non_centrality(
  88. function,
  89. l,
  90. &r,
  91. Policy()))
  92. return r;
  93. if(v2 <= 2)
  94. return policies::raise_domain_error(
  95. function,
  96. "Second degrees of freedom parameter was %1%, but must be > 2 !",
  97. v2, Policy());
  98. return v2 * (v1 + l) / (v1 * (v2 - 2));
  99. } // mean
  100. template <class RealType, class Policy>
  101. inline RealType mode(const non_central_f_distribution<RealType, Policy>& dist)
  102. { // mode.
  103. static const char* function = "mode(non_central_chi_squared_distribution<%1%> const&)";
  104. RealType n = dist.degrees_of_freedom1();
  105. RealType m = dist.degrees_of_freedom2();
  106. RealType l = dist.non_centrality();
  107. RealType r;
  108. if(!detail::check_df(
  109. function,
  110. n, &r, Policy())
  111. ||
  112. !detail::check_df(
  113. function,
  114. m, &r, Policy())
  115. ||
  116. !detail::check_non_centrality(
  117. function,
  118. l,
  119. &r,
  120. Policy()))
  121. return r;
  122. RealType guess = m > 2 ? RealType(m * (n + l) / (n * (m - 2))) : RealType(1);
  123. return detail::generic_find_mode(
  124. dist,
  125. guess,
  126. function);
  127. }
  128. template <class RealType, class Policy>
  129. inline RealType variance(const non_central_f_distribution<RealType, Policy>& dist)
  130. { // variance.
  131. const char* function = "variance(non_central_f_distribution<%1%> const&)";
  132. RealType n = dist.degrees_of_freedom1();
  133. RealType m = dist.degrees_of_freedom2();
  134. RealType l = dist.non_centrality();
  135. RealType r;
  136. if(!detail::check_df(
  137. function,
  138. n, &r, Policy())
  139. ||
  140. !detail::check_df(
  141. function,
  142. m, &r, Policy())
  143. ||
  144. !detail::check_non_centrality(
  145. function,
  146. l,
  147. &r,
  148. Policy()))
  149. return r;
  150. if(m <= 4)
  151. return policies::raise_domain_error(
  152. function,
  153. "Second degrees of freedom parameter was %1%, but must be > 4 !",
  154. m, Policy());
  155. RealType result = 2 * m * m * ((n + l) * (n + l)
  156. + (m - 2) * (n + 2 * l));
  157. result /= (m - 4) * (m - 2) * (m - 2) * n * n;
  158. return result;
  159. }
  160. // RealType standard_deviation(const non_central_f_distribution<RealType, Policy>& dist)
  161. // standard_deviation provided by derived accessors.
  162. template <class RealType, class Policy>
  163. inline RealType skewness(const non_central_f_distribution<RealType, Policy>& dist)
  164. { // skewness = sqrt(l).
  165. const char* function = "skewness(non_central_f_distribution<%1%> const&)";
  166. BOOST_MATH_STD_USING
  167. RealType n = dist.degrees_of_freedom1();
  168. RealType m = dist.degrees_of_freedom2();
  169. RealType l = dist.non_centrality();
  170. RealType r;
  171. if(!detail::check_df(
  172. function,
  173. n, &r, Policy())
  174. ||
  175. !detail::check_df(
  176. function,
  177. m, &r, Policy())
  178. ||
  179. !detail::check_non_centrality(
  180. function,
  181. l,
  182. &r,
  183. Policy()))
  184. return r;
  185. if(m <= 6)
  186. return policies::raise_domain_error(
  187. function,
  188. "Second degrees of freedom parameter was %1%, but must be > 6 !",
  189. m, Policy());
  190. RealType result = 2 * constants::root_two<RealType>();
  191. result *= sqrt(m - 4);
  192. result *= (n * (m + n - 2) *(m + 2 * n - 2)
  193. + 3 * (m + n - 2) * (m + 2 * n - 2) * l
  194. + 6 * (m + n - 2) * l * l + 2 * l * l * l);
  195. result /= (m - 6) * pow(n * (m + n - 2) + 2 * (m + n - 2) * l + l * l, RealType(1.5f));
  196. return result;
  197. }
  198. template <class RealType, class Policy>
  199. inline RealType kurtosis_excess(const non_central_f_distribution<RealType, Policy>& dist)
  200. {
  201. const char* function = "kurtosis_excess(non_central_f_distribution<%1%> const&)";
  202. BOOST_MATH_STD_USING
  203. RealType n = dist.degrees_of_freedom1();
  204. RealType m = dist.degrees_of_freedom2();
  205. RealType l = dist.non_centrality();
  206. RealType r;
  207. if(!detail::check_df(
  208. function,
  209. n, &r, Policy())
  210. ||
  211. !detail::check_df(
  212. function,
  213. m, &r, Policy())
  214. ||
  215. !detail::check_non_centrality(
  216. function,
  217. l,
  218. &r,
  219. Policy()))
  220. return r;
  221. if(m <= 8)
  222. return policies::raise_domain_error(
  223. function,
  224. "Second degrees of freedom parameter was %1%, but must be > 8 !",
  225. m, Policy());
  226. RealType l2 = l * l;
  227. RealType l3 = l2 * l;
  228. RealType l4 = l2 * l2;
  229. RealType result = (3 * (m - 4) * (n * (m + n - 2)
  230. * (4 * (m - 2) * (m - 2)
  231. + (m - 2) * (m + 10) * n
  232. + (10 + m) * n * n)
  233. + 4 * (m + n - 2) * (4 * (m - 2) * (m - 2)
  234. + (m - 2) * (10 + m) * n
  235. + (10 + m) * n * n) * l + 2 * (10 + m)
  236. * (m + n - 2) * (2 * m + 3 * n - 4) * l2
  237. + 4 * (10 + m) * (-2 + m + n) * l3
  238. + (10 + m) * l4))
  239. /
  240. ((-8 + m) * (-6 + m) * boost::math::pow<2>(n * (-2 + m + n)
  241. + 2 * (-2 + m + n) * l + l2));
  242. return result;
  243. } // kurtosis_excess
  244. template <class RealType, class Policy>
  245. inline RealType kurtosis(const non_central_f_distribution<RealType, Policy>& dist)
  246. {
  247. return kurtosis_excess(dist) + 3;
  248. }
  249. template <class RealType, class Policy>
  250. inline RealType pdf(const non_central_f_distribution<RealType, Policy>& dist, const RealType& x)
  251. { // Probability Density/Mass Function.
  252. typedef typename policies::evaluation<RealType, Policy>::type value_type;
  253. typedef typename policies::normalise<
  254. Policy,
  255. policies::promote_float<false>,
  256. policies::promote_double<false>,
  257. policies::discrete_quantile<>,
  258. policies::assert_undefined<> >::type forwarding_policy;
  259. value_type alpha = dist.degrees_of_freedom1() / 2;
  260. value_type beta = dist.degrees_of_freedom2() / 2;
  261. value_type y = x * alpha / beta;
  262. value_type r = pdf(boost::math::non_central_beta_distribution<value_type, forwarding_policy>(alpha, beta, dist.non_centrality()), y / (1 + y));
  263. return policies::checked_narrowing_cast<RealType, forwarding_policy>(
  264. r * (dist.degrees_of_freedom1() / dist.degrees_of_freedom2()) / ((1 + y) * (1 + y)),
  265. "pdf(non_central_f_distribution<%1%>, %1%)");
  266. } // pdf
  267. template <class RealType, class Policy>
  268. RealType cdf(const non_central_f_distribution<RealType, Policy>& dist, const RealType& x)
  269. {
  270. const char* function = "cdf(const non_central_f_distribution<%1%>&, %1%)";
  271. RealType r;
  272. if(!detail::check_df(
  273. function,
  274. dist.degrees_of_freedom1(), &r, Policy())
  275. ||
  276. !detail::check_df(
  277. function,
  278. dist.degrees_of_freedom2(), &r, Policy())
  279. ||
  280. !detail::check_non_centrality(
  281. function,
  282. dist.non_centrality(),
  283. &r,
  284. Policy()))
  285. return r;
  286. if((x < 0) || !(boost::math::isfinite)(x))
  287. {
  288. return policies::raise_domain_error<RealType>(
  289. function, "Random Variable parameter was %1%, but must be > 0 !", x, Policy());
  290. }
  291. RealType alpha = dist.degrees_of_freedom1() / 2;
  292. RealType beta = dist.degrees_of_freedom2() / 2;
  293. RealType y = x * alpha / beta;
  294. RealType c = y / (1 + y);
  295. RealType cp = 1 / (1 + y);
  296. //
  297. // To ensure accuracy, we pass both x and 1-x to the
  298. // non-central beta cdf routine, this ensures accuracy
  299. // even when we compute x to be ~ 1:
  300. //
  301. r = detail::non_central_beta_cdf(c, cp, alpha, beta,
  302. dist.non_centrality(), false, Policy());
  303. return r;
  304. } // cdf
  305. template <class RealType, class Policy>
  306. RealType cdf(const complemented2_type<non_central_f_distribution<RealType, Policy>, RealType>& c)
  307. { // Complemented Cumulative Distribution Function
  308. const char* function = "cdf(complement(const non_central_f_distribution<%1%>&, %1%))";
  309. RealType r;
  310. if(!detail::check_df(
  311. function,
  312. c.dist.degrees_of_freedom1(), &r, Policy())
  313. ||
  314. !detail::check_df(
  315. function,
  316. c.dist.degrees_of_freedom2(), &r, Policy())
  317. ||
  318. !detail::check_non_centrality(
  319. function,
  320. c.dist.non_centrality(),
  321. &r,
  322. Policy()))
  323. return r;
  324. if((c.param < 0) || !(boost::math::isfinite)(c.param))
  325. {
  326. return policies::raise_domain_error<RealType>(
  327. function, "Random Variable parameter was %1%, but must be > 0 !", c.param, Policy());
  328. }
  329. RealType alpha = c.dist.degrees_of_freedom1() / 2;
  330. RealType beta = c.dist.degrees_of_freedom2() / 2;
  331. RealType y = c.param * alpha / beta;
  332. RealType x = y / (1 + y);
  333. RealType cx = 1 / (1 + y);
  334. //
  335. // To ensure accuracy, we pass both x and 1-x to the
  336. // non-central beta cdf routine, this ensures accuracy
  337. // even when we compute x to be ~ 1:
  338. //
  339. r = detail::non_central_beta_cdf(x, cx, alpha, beta,
  340. c.dist.non_centrality(), true, Policy());
  341. return r;
  342. } // ccdf
  343. template <class RealType, class Policy>
  344. inline RealType quantile(const non_central_f_distribution<RealType, Policy>& dist, const RealType& p)
  345. { // Quantile (or Percent Point) function.
  346. RealType alpha = dist.degrees_of_freedom1() / 2;
  347. RealType beta = dist.degrees_of_freedom2() / 2;
  348. RealType x = quantile(boost::math::non_central_beta_distribution<RealType, Policy>(alpha, beta, dist.non_centrality()), p);
  349. if(x == 1)
  350. return policies::raise_overflow_error<RealType>(
  351. "quantile(const non_central_f_distribution<%1%>&, %1%)",
  352. "Result of non central F quantile is too large to represent.",
  353. Policy());
  354. return (x / (1 - x)) * (dist.degrees_of_freedom2() / dist.degrees_of_freedom1());
  355. } // quantile
  356. template <class RealType, class Policy>
  357. inline RealType quantile(const complemented2_type<non_central_f_distribution<RealType, Policy>, RealType>& c)
  358. { // Quantile (or Percent Point) function.
  359. RealType alpha = c.dist.degrees_of_freedom1() / 2;
  360. RealType beta = c.dist.degrees_of_freedom2() / 2;
  361. RealType x = quantile(complement(boost::math::non_central_beta_distribution<RealType, Policy>(alpha, beta, c.dist.non_centrality()), c.param));
  362. if(x == 1)
  363. return policies::raise_overflow_error<RealType>(
  364. "quantile(complement(const non_central_f_distribution<%1%>&, %1%))",
  365. "Result of non central F quantile is too large to represent.",
  366. Policy());
  367. return (x / (1 - x)) * (c.dist.degrees_of_freedom2() / c.dist.degrees_of_freedom1());
  368. } // quantile complement.
  369. } // namespace math
  370. } // namespace boost
  371. // This include must be at the end, *after* the accessors
  372. // for this distribution have been defined, in order to
  373. // keep compilers that support two-phase lookup happy.
  374. #include <boost/math/distributions/detail/derived_accessors.hpp>
  375. #endif // BOOST_MATH_SPECIAL_NON_CENTRAL_F_HPP