non_central_f.hpp 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409
  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. return detail::generic_find_mode(
  123. dist,
  124. m * (n + l) / (n * (m - 2)),
  125. function);
  126. }
  127. template <class RealType, class Policy>
  128. inline RealType variance(const non_central_f_distribution<RealType, Policy>& dist)
  129. { // variance.
  130. const char* function = "variance(non_central_f_distribution<%1%> const&)";
  131. RealType n = dist.degrees_of_freedom1();
  132. RealType m = dist.degrees_of_freedom2();
  133. RealType l = dist.non_centrality();
  134. RealType r;
  135. if(!detail::check_df(
  136. function,
  137. n, &r, Policy())
  138. ||
  139. !detail::check_df(
  140. function,
  141. m, &r, Policy())
  142. ||
  143. !detail::check_non_centrality(
  144. function,
  145. l,
  146. &r,
  147. Policy()))
  148. return r;
  149. if(m <= 4)
  150. return policies::raise_domain_error(
  151. function,
  152. "Second degrees of freedom parameter was %1%, but must be > 4 !",
  153. m, Policy());
  154. RealType result = 2 * m * m * ((n + l) * (n + l)
  155. + (m - 2) * (n + 2 * l));
  156. result /= (m - 4) * (m - 2) * (m - 2) * n * n;
  157. return result;
  158. }
  159. // RealType standard_deviation(const non_central_f_distribution<RealType, Policy>& dist)
  160. // standard_deviation provided by derived accessors.
  161. template <class RealType, class Policy>
  162. inline RealType skewness(const non_central_f_distribution<RealType, Policy>& dist)
  163. { // skewness = sqrt(l).
  164. const char* function = "skewness(non_central_f_distribution<%1%> const&)";
  165. BOOST_MATH_STD_USING
  166. RealType n = dist.degrees_of_freedom1();
  167. RealType m = dist.degrees_of_freedom2();
  168. RealType l = dist.non_centrality();
  169. RealType r;
  170. if(!detail::check_df(
  171. function,
  172. n, &r, Policy())
  173. ||
  174. !detail::check_df(
  175. function,
  176. m, &r, Policy())
  177. ||
  178. !detail::check_non_centrality(
  179. function,
  180. l,
  181. &r,
  182. Policy()))
  183. return r;
  184. if(m <= 6)
  185. return policies::raise_domain_error(
  186. function,
  187. "Second degrees of freedom parameter was %1%, but must be > 6 !",
  188. m, Policy());
  189. RealType result = 2 * constants::root_two<RealType>();
  190. result *= sqrt(m - 4);
  191. result *= (n * (m + n - 2) *(m + 2 * n - 2)
  192. + 3 * (m + n - 2) * (m + 2 * n - 2) * l
  193. + 6 * (m + n - 2) * l * l + 2 * l * l * l);
  194. result /= (m - 6) * pow(n * (m + n - 2) + 2 * (m + n - 2) * l + l * l, RealType(1.5f));
  195. return result;
  196. }
  197. template <class RealType, class Policy>
  198. inline RealType kurtosis_excess(const non_central_f_distribution<RealType, Policy>& dist)
  199. {
  200. const char* function = "kurtosis_excess(non_central_f_distribution<%1%> const&)";
  201. BOOST_MATH_STD_USING
  202. RealType n = dist.degrees_of_freedom1();
  203. RealType m = dist.degrees_of_freedom2();
  204. RealType l = dist.non_centrality();
  205. RealType r;
  206. if(!detail::check_df(
  207. function,
  208. n, &r, Policy())
  209. ||
  210. !detail::check_df(
  211. function,
  212. m, &r, Policy())
  213. ||
  214. !detail::check_non_centrality(
  215. function,
  216. l,
  217. &r,
  218. Policy()))
  219. return r;
  220. if(m <= 8)
  221. return policies::raise_domain_error(
  222. function,
  223. "Second degrees of freedom parameter was %1%, but must be > 8 !",
  224. m, Policy());
  225. RealType l2 = l * l;
  226. RealType l3 = l2 * l;
  227. RealType l4 = l2 * l2;
  228. RealType result = (3 * (m - 4) * (n * (m + n - 2)
  229. * (4 * (m - 2) * (m - 2)
  230. + (m - 2) * (m + 10) * n
  231. + (10 + m) * n * n)
  232. + 4 * (m + n - 2) * (4 * (m - 2) * (m - 2)
  233. + (m - 2) * (10 + m) * n
  234. + (10 + m) * n * n) * l + 2 * (10 + m)
  235. * (m + n - 2) * (2 * m + 3 * n - 4) * l2
  236. + 4 * (10 + m) * (-2 + m + n) * l3
  237. + (10 + m) * l4))
  238. /
  239. ((-8 + m) * (-6 + m) * boost::math::pow<2>(n * (-2 + m + n)
  240. + 2 * (-2 + m + n) * l + l2));
  241. return result;
  242. } // kurtosis_excess
  243. template <class RealType, class Policy>
  244. inline RealType kurtosis(const non_central_f_distribution<RealType, Policy>& dist)
  245. {
  246. return kurtosis_excess(dist) + 3;
  247. }
  248. template <class RealType, class Policy>
  249. inline RealType pdf(const non_central_f_distribution<RealType, Policy>& dist, const RealType& x)
  250. { // Probability Density/Mass Function.
  251. typedef typename policies::evaluation<RealType, Policy>::type value_type;
  252. typedef typename policies::normalise<
  253. Policy,
  254. policies::promote_float<false>,
  255. policies::promote_double<false>,
  256. policies::discrete_quantile<>,
  257. policies::assert_undefined<> >::type forwarding_policy;
  258. value_type alpha = dist.degrees_of_freedom1() / 2;
  259. value_type beta = dist.degrees_of_freedom2() / 2;
  260. value_type y = x * alpha / beta;
  261. value_type r = pdf(boost::math::non_central_beta_distribution<value_type, forwarding_policy>(alpha, beta, dist.non_centrality()), y / (1 + y));
  262. return policies::checked_narrowing_cast<RealType, forwarding_policy>(
  263. r * (dist.degrees_of_freedom1() / dist.degrees_of_freedom2()) / ((1 + y) * (1 + y)),
  264. "pdf(non_central_f_distribution<%1%>, %1%)");
  265. } // pdf
  266. template <class RealType, class Policy>
  267. RealType cdf(const non_central_f_distribution<RealType, Policy>& dist, const RealType& x)
  268. {
  269. const char* function = "cdf(const non_central_f_distribution<%1%>&, %1%)";
  270. RealType r;
  271. if(!detail::check_df(
  272. function,
  273. dist.degrees_of_freedom1(), &r, Policy())
  274. ||
  275. !detail::check_df(
  276. function,
  277. dist.degrees_of_freedom2(), &r, Policy())
  278. ||
  279. !detail::check_non_centrality(
  280. function,
  281. dist.non_centrality(),
  282. &r,
  283. Policy()))
  284. return r;
  285. if((x < 0) || !(boost::math::isfinite)(x))
  286. {
  287. return policies::raise_domain_error<RealType>(
  288. function, "Random Variable parameter was %1%, but must be > 0 !", x, Policy());
  289. }
  290. RealType alpha = dist.degrees_of_freedom1() / 2;
  291. RealType beta = dist.degrees_of_freedom2() / 2;
  292. RealType y = x * alpha / beta;
  293. RealType c = y / (1 + y);
  294. RealType cp = 1 / (1 + y);
  295. //
  296. // To ensure accuracy, we pass both x and 1-x to the
  297. // non-central beta cdf routine, this ensures accuracy
  298. // even when we compute x to be ~ 1:
  299. //
  300. r = detail::non_central_beta_cdf(c, cp, alpha, beta,
  301. dist.non_centrality(), false, Policy());
  302. return r;
  303. } // cdf
  304. template <class RealType, class Policy>
  305. RealType cdf(const complemented2_type<non_central_f_distribution<RealType, Policy>, RealType>& c)
  306. { // Complemented Cumulative Distribution Function
  307. const char* function = "cdf(complement(const non_central_f_distribution<%1%>&, %1%))";
  308. RealType r;
  309. if(!detail::check_df(
  310. function,
  311. c.dist.degrees_of_freedom1(), &r, Policy())
  312. ||
  313. !detail::check_df(
  314. function,
  315. c.dist.degrees_of_freedom2(), &r, Policy())
  316. ||
  317. !detail::check_non_centrality(
  318. function,
  319. c.dist.non_centrality(),
  320. &r,
  321. Policy()))
  322. return r;
  323. if((c.param < 0) || !(boost::math::isfinite)(c.param))
  324. {
  325. return policies::raise_domain_error<RealType>(
  326. function, "Random Variable parameter was %1%, but must be > 0 !", c.param, Policy());
  327. }
  328. RealType alpha = c.dist.degrees_of_freedom1() / 2;
  329. RealType beta = c.dist.degrees_of_freedom2() / 2;
  330. RealType y = c.param * alpha / beta;
  331. RealType x = y / (1 + y);
  332. RealType cx = 1 / (1 + y);
  333. //
  334. // To ensure accuracy, we pass both x and 1-x to the
  335. // non-central beta cdf routine, this ensures accuracy
  336. // even when we compute x to be ~ 1:
  337. //
  338. r = detail::non_central_beta_cdf(x, cx, alpha, beta,
  339. c.dist.non_centrality(), true, Policy());
  340. return r;
  341. } // ccdf
  342. template <class RealType, class Policy>
  343. inline RealType quantile(const non_central_f_distribution<RealType, Policy>& dist, const RealType& p)
  344. { // Quantile (or Percent Point) function.
  345. RealType alpha = dist.degrees_of_freedom1() / 2;
  346. RealType beta = dist.degrees_of_freedom2() / 2;
  347. RealType x = quantile(boost::math::non_central_beta_distribution<RealType, Policy>(alpha, beta, dist.non_centrality()), p);
  348. if(x == 1)
  349. return policies::raise_overflow_error<RealType>(
  350. "quantile(const non_central_f_distribution<%1%>&, %1%)",
  351. "Result of non central F quantile is too large to represent.",
  352. Policy());
  353. return (x / (1 - x)) * (dist.degrees_of_freedom2() / dist.degrees_of_freedom1());
  354. } // quantile
  355. template <class RealType, class Policy>
  356. inline RealType quantile(const complemented2_type<non_central_f_distribution<RealType, Policy>, RealType>& c)
  357. { // Quantile (or Percent Point) function.
  358. RealType alpha = c.dist.degrees_of_freedom1() / 2;
  359. RealType beta = c.dist.degrees_of_freedom2() / 2;
  360. RealType x = quantile(complement(boost::math::non_central_beta_distribution<RealType, Policy>(alpha, beta, c.dist.non_centrality()), c.param));
  361. if(x == 1)
  362. return policies::raise_overflow_error<RealType>(
  363. "quantile(complement(const non_central_f_distribution<%1%>&, %1%))",
  364. "Result of non central F quantile is too large to represent.",
  365. Policy());
  366. return (x / (1 - x)) * (c.dist.degrees_of_freedom2() / c.dist.degrees_of_freedom1());
  367. } // quantile complement.
  368. } // namespace math
  369. } // namespace boost
  370. // This include must be at the end, *after* the accessors
  371. // for this distribution have been defined, in order to
  372. // keep compilers that support two-phase lookup happy.
  373. #include <boost/math/distributions/detail/derived_accessors.hpp>
  374. #endif // BOOST_MATH_SPECIAL_NON_CENTRAL_F_HPP