non_central_t.hpp 49 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221
  1. // boost\math\distributions\non_central_t.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_T_HPP
  8. #define BOOST_MATH_SPECIAL_NON_CENTRAL_T_HPP
  9. #include <boost/math/distributions/fwd.hpp>
  10. #include <boost/math/distributions/non_central_beta.hpp> // for nc beta
  11. #include <boost/math/distributions/normal.hpp> // for normal CDF and quantile
  12. #include <boost/math/distributions/students_t.hpp>
  13. #include <boost/math/distributions/detail/generic_quantile.hpp> // quantile
  14. #include <boost/math/special_functions/trunc.hpp>
  15. namespace boost
  16. {
  17. namespace math
  18. {
  19. template <class RealType, class Policy>
  20. class non_central_t_distribution;
  21. namespace detail{
  22. template <class T, class Policy>
  23. T non_central_t2_p(T v, T delta, T x, T y, const Policy& pol, T init_val)
  24. {
  25. BOOST_MATH_STD_USING
  26. //
  27. // Variables come first:
  28. //
  29. std::uintmax_t max_iter = policies::get_max_series_iterations<Policy>();
  30. T errtol = policies::get_epsilon<T, Policy>();
  31. T d2 = delta * delta / 2;
  32. //
  33. // k is the starting point for iteration, and is the
  34. // maximum of the poisson weighting term, we don't
  35. // ever allow k == 0 as this can lead to catastrophic
  36. // cancellation errors later (test case is v = 1621286869049072.3
  37. // delta = 0.16212868690490723, x = 0.86987415482475994).
  38. //
  39. long long k = lltrunc(d2);
  40. T pois;
  41. if(k == 0) k = 1;
  42. // Starting Poisson weight:
  43. pois = gamma_p_derivative(T(k+1), d2, pol)
  44. * tgamma_delta_ratio(T(k + 1), T(0.5f))
  45. * delta / constants::root_two<T>();
  46. if(pois == 0)
  47. return init_val;
  48. T xterm, beta;
  49. // Recurrence & starting beta terms:
  50. beta = x < y
  51. ? detail::ibeta_imp(T(k + 1), T(v / 2), x, pol, false, true, &xterm)
  52. : detail::ibeta_imp(T(v / 2), T(k + 1), y, pol, true, true, &xterm);
  53. xterm *= y / (v / 2 + k);
  54. T poisf(pois), betaf(beta), xtermf(xterm);
  55. T sum = init_val;
  56. if((xterm == 0) && (beta == 0))
  57. return init_val;
  58. //
  59. // Backwards recursion first, this is the stable
  60. // direction for recursion:
  61. //
  62. std::uintmax_t count = 0;
  63. T last_term = 0;
  64. for(auto i = k; i >= 0; --i)
  65. {
  66. T term = beta * pois;
  67. sum += term;
  68. // Don't terminate on first term in case we "fixed" k above:
  69. if(((fabs(last_term) > fabs(term)) && fabs(term/sum) < errtol) || (v == 2 && i == 0))
  70. break;
  71. last_term = term;
  72. pois *= (i + 0.5f) / d2;
  73. beta += xterm;
  74. xterm *= (i) / (x * (v / 2 + i - 1));
  75. ++count;
  76. }
  77. last_term = 0;
  78. for(auto i = k + 1; ; ++i)
  79. {
  80. poisf *= d2 / (i + 0.5f);
  81. xtermf *= (x * (v / 2 + i - 1)) / (i);
  82. betaf -= xtermf;
  83. T term = poisf * betaf;
  84. sum += term;
  85. if((fabs(last_term) >= fabs(term)) && (fabs(term/sum) < errtol))
  86. break;
  87. last_term = term;
  88. ++count;
  89. if(count > max_iter)
  90. {
  91. return policies::raise_evaluation_error(
  92. "cdf(non_central_t_distribution<%1%>, %1%)",
  93. "Series did not converge, closest value was %1%", sum, pol);
  94. }
  95. }
  96. return sum;
  97. }
  98. template <class T, class Policy>
  99. T non_central_t2_q(T v, T delta, T x, T y, const Policy& pol, T init_val)
  100. {
  101. BOOST_MATH_STD_USING
  102. //
  103. // Variables come first:
  104. //
  105. std::uintmax_t max_iter = policies::get_max_series_iterations<Policy>();
  106. T errtol = boost::math::policies::get_epsilon<T, Policy>();
  107. T d2 = delta * delta / 2;
  108. //
  109. // k is the starting point for iteration, and is the
  110. // maximum of the poisson weighting term, we don't allow
  111. // k == 0 as this can cause catastrophic cancellation errors
  112. // (test case is v = 561908036470413.25, delta = 0.056190803647041321,
  113. // x = 1.6155232703966216):
  114. //
  115. long long k = lltrunc(d2);
  116. if(k == 0) k = 1;
  117. // Starting Poisson weight:
  118. T pois;
  119. if((k < static_cast<long long>(max_factorial<T>::value)) && (d2 < tools::log_max_value<T>()) && (log(d2) * k < tools::log_max_value<T>()))
  120. {
  121. //
  122. // For small k we can optimise this calculation by using
  123. // a simpler reduced formula:
  124. //
  125. pois = exp(-d2);
  126. pois *= pow(d2, static_cast<T>(k));
  127. pois /= boost::math::tgamma(T(k + 1 + 0.5), pol);
  128. pois *= delta / constants::root_two<T>();
  129. }
  130. else
  131. {
  132. pois = gamma_p_derivative(T(k+1), d2, pol)
  133. * tgamma_delta_ratio(T(k + 1), T(0.5f))
  134. * delta / constants::root_two<T>();
  135. }
  136. if(pois == 0)
  137. return init_val;
  138. // Recurance term:
  139. T xterm;
  140. T beta;
  141. // Starting beta term:
  142. if(k != 0)
  143. {
  144. beta = x < y
  145. ? detail::ibeta_imp(T(k + 1), T(v / 2), x, pol, true, true, &xterm)
  146. : detail::ibeta_imp(T(v / 2), T(k + 1), y, pol, false, true, &xterm);
  147. xterm *= y / (v / 2 + k);
  148. }
  149. else
  150. {
  151. beta = pow(y, v / 2);
  152. xterm = beta;
  153. }
  154. T poisf(pois), betaf(beta), xtermf(xterm);
  155. T sum = init_val;
  156. if((xterm == 0) && (beta == 0))
  157. return init_val;
  158. //
  159. // Fused forward and backwards recursion:
  160. //
  161. std::uintmax_t count = 0;
  162. T last_term = 0;
  163. for(auto i = k + 1, j = k; ; ++i, --j)
  164. {
  165. poisf *= d2 / (i + 0.5f);
  166. xtermf *= (x * (v / 2 + i - 1)) / (i);
  167. betaf += xtermf;
  168. T term = poisf * betaf;
  169. if(j >= 0)
  170. {
  171. term += beta * pois;
  172. pois *= (j + 0.5f) / d2;
  173. beta -= xterm;
  174. if(!(v == 2 && j == 0))
  175. xterm *= (j) / (x * (v / 2 + j - 1));
  176. }
  177. sum += term;
  178. // Don't terminate on first term in case we "fixed" the value of k above:
  179. if((fabs(last_term) > fabs(term)) && fabs(term/sum) < errtol)
  180. break;
  181. last_term = term;
  182. if(count > max_iter)
  183. {
  184. return policies::raise_evaluation_error(
  185. "cdf(non_central_t_distribution<%1%>, %1%)",
  186. "Series did not converge, closest value was %1%", sum, pol);
  187. }
  188. ++count;
  189. }
  190. return sum;
  191. }
  192. template <class T, class Policy>
  193. T non_central_t_cdf(T v, T delta, T t, bool invert, const Policy& pol)
  194. {
  195. BOOST_MATH_STD_USING
  196. if ((boost::math::isinf)(v))
  197. { // Infinite degrees of freedom, so use normal distribution located at delta.
  198. normal_distribution<T, Policy> n(delta, 1);
  199. return cdf(n, t);
  200. }
  201. //
  202. // Otherwise, for t < 0 we have to use the reflection formula:
  203. if(t < 0)
  204. {
  205. t = -t;
  206. delta = -delta;
  207. invert = !invert;
  208. }
  209. if(fabs(delta / (4 * v)) < policies::get_epsilon<T, Policy>())
  210. {
  211. // Approximate with a Student's T centred on delta,
  212. // the crossover point is based on eq 2.6 from
  213. // "A Comparison of Approximations To Percentiles of the
  214. // Noncentral t-Distribution". H. Sahai and M. M. Ojeda,
  215. // Revista Investigacion Operacional Vol 21, No 2, 2000.
  216. // Original sources referenced in the above are:
  217. // "Some Approximations to the Percentage Points of the Noncentral
  218. // t-Distribution". C. van Eeden. International Statistical Review, 29, 4-31.
  219. // "Continuous Univariate Distributions". N.L. Johnson, S. Kotz and
  220. // N. Balkrishnan. 1995. John Wiley and Sons New York.
  221. T result = cdf(students_t_distribution<T, Policy>(v), t - delta);
  222. return invert ? 1 - result : result;
  223. }
  224. //
  225. // x and y are the corresponding random
  226. // variables for the noncentral beta distribution,
  227. // with y = 1 - x:
  228. //
  229. T x = t * t / (v + t * t);
  230. T y = v / (v + t * t);
  231. T d2 = delta * delta;
  232. T a = 0.5f;
  233. T b = v / 2;
  234. T c = a + b + d2 / 2;
  235. //
  236. // Crossover point for calculating p or q is the same
  237. // as for the noncentral beta:
  238. //
  239. T cross = 1 - (b / c) * (1 + d2 / (2 * c * c));
  240. T result;
  241. if(x < cross)
  242. {
  243. //
  244. // Calculate p:
  245. //
  246. if(x != 0)
  247. {
  248. result = non_central_beta_p(a, b, d2, x, y, pol);
  249. result = non_central_t2_p(v, delta, x, y, pol, result);
  250. result /= 2;
  251. }
  252. else
  253. result = 0;
  254. result += cdf(boost::math::normal_distribution<T, Policy>(), -delta);
  255. }
  256. else
  257. {
  258. //
  259. // Calculate q:
  260. //
  261. invert = !invert;
  262. if(x != 0)
  263. {
  264. result = non_central_beta_q(a, b, d2, x, y, pol);
  265. result = non_central_t2_q(v, delta, x, y, pol, result);
  266. result /= 2;
  267. }
  268. else // x == 0
  269. result = cdf(complement(boost::math::normal_distribution<T, Policy>(), -delta));
  270. }
  271. if(invert)
  272. result = 1 - result;
  273. return result;
  274. }
  275. template <class T, class Policy>
  276. T non_central_t_quantile(const char* function, T v, T delta, T p, T q, const Policy&)
  277. {
  278. BOOST_MATH_STD_USING
  279. // static const char* function = "quantile(non_central_t_distribution<%1%>, %1%)";
  280. // now passed as function
  281. typedef typename policies::evaluation<T, Policy>::type value_type;
  282. typedef typename policies::normalise<
  283. Policy,
  284. policies::promote_float<false>,
  285. policies::promote_double<false>,
  286. policies::discrete_quantile<>,
  287. policies::assert_undefined<> >::type forwarding_policy;
  288. T r;
  289. if(!detail::check_df_gt0_to_inf(
  290. function,
  291. v, &r, Policy())
  292. ||
  293. !detail::check_non_centrality(
  294. function,
  295. static_cast<T>(delta * delta),
  296. &r,
  297. Policy())
  298. ||
  299. !detail::check_probability(
  300. function,
  301. p,
  302. &r,
  303. Policy()))
  304. return r;
  305. value_type guess = 0;
  306. if ( ((boost::math::isinf)(v)) || (v > 1 / boost::math::tools::epsilon<T>()) )
  307. { // Infinite or very large degrees of freedom, so use normal distribution located at delta.
  308. normal_distribution<T, Policy> n(delta, 1);
  309. if (p < q)
  310. {
  311. return quantile(n, p);
  312. }
  313. else
  314. {
  315. return quantile(complement(n, q));
  316. }
  317. }
  318. else if(v > 3)
  319. { // Use normal distribution to calculate guess.
  320. value_type mean = (v > 1 / policies::get_epsilon<T, Policy>()) ? delta : delta * sqrt(v / 2) * tgamma_delta_ratio((v - 1) * 0.5f, T(0.5f));
  321. value_type var = (v > 1 / policies::get_epsilon<T, Policy>()) ? value_type(1) : (((delta * delta + 1) * v) / (v - 2) - mean * mean);
  322. if(p < q)
  323. guess = quantile(normal_distribution<value_type, forwarding_policy>(mean, var), p);
  324. else
  325. guess = quantile(complement(normal_distribution<value_type, forwarding_policy>(mean, var), q));
  326. }
  327. //
  328. // We *must* get the sign of the initial guess correct,
  329. // or our root-finder will fail, so double check it now:
  330. //
  331. value_type pzero = non_central_t_cdf(
  332. static_cast<value_type>(v),
  333. static_cast<value_type>(delta),
  334. static_cast<value_type>(0),
  335. !(p < q),
  336. forwarding_policy());
  337. int s;
  338. if(p < q)
  339. s = boost::math::sign(p - pzero);
  340. else
  341. s = boost::math::sign(pzero - q);
  342. if(s != boost::math::sign(guess))
  343. {
  344. guess = static_cast<T>(s);
  345. }
  346. value_type result = detail::generic_quantile(
  347. non_central_t_distribution<value_type, forwarding_policy>(v, delta),
  348. (p < q ? p : q),
  349. guess,
  350. (p >= q),
  351. function);
  352. return policies::checked_narrowing_cast<T, forwarding_policy>(
  353. result,
  354. function);
  355. }
  356. template <class T, class Policy>
  357. T non_central_t2_pdf(T n, T delta, T x, T y, const Policy& pol, T init_val)
  358. {
  359. BOOST_MATH_STD_USING
  360. //
  361. // Variables come first:
  362. //
  363. std::uintmax_t max_iter = policies::get_max_series_iterations<Policy>();
  364. T errtol = boost::math::policies::get_epsilon<T, Policy>();
  365. T d2 = delta * delta / 2;
  366. //
  367. // k is the starting point for iteration, and is the
  368. // maximum of the poisson weighting term:
  369. //
  370. long long k = lltrunc(d2);
  371. T pois, xterm;
  372. if(k == 0)
  373. k = 1;
  374. // Starting Poisson weight:
  375. pois = gamma_p_derivative(T(k+1), d2, pol)
  376. * tgamma_delta_ratio(T(k + 1), T(0.5f))
  377. * delta / constants::root_two<T>();
  378. BOOST_MATH_INSTRUMENT_VARIABLE(pois);
  379. // Starting beta term:
  380. xterm = x < y
  381. ? ibeta_derivative(T(k + 1), n / 2, x, pol)
  382. : ibeta_derivative(n / 2, T(k + 1), y, pol);
  383. BOOST_MATH_INSTRUMENT_VARIABLE(xterm);
  384. T poisf(pois), xtermf(xterm);
  385. T sum = init_val;
  386. if((pois == 0) || (xterm == 0))
  387. return init_val;
  388. //
  389. // Backwards recursion first, this is the stable
  390. // direction for recursion:
  391. //
  392. std::uintmax_t count = 0;
  393. T old_ratio = 1; // arbitrary "large" value
  394. for(auto i = k; i >= 0; --i)
  395. {
  396. T term = xterm * pois;
  397. sum += term;
  398. BOOST_MATH_INSTRUMENT_VARIABLE(sum);
  399. T ratio = fabs(term / sum);
  400. if(((ratio < errtol) && (i != k) && (ratio < old_ratio)) || (term == 0))
  401. break;
  402. old_ratio = ratio;
  403. pois *= (i + 0.5f) / d2;
  404. xterm *= (i) / (x * (n / 2 + i));
  405. ++count;
  406. if(count > max_iter)
  407. {
  408. return policies::raise_evaluation_error(
  409. "pdf(non_central_t_distribution<%1%>, %1%)",
  410. "Series did not converge, closest value was %1%", sum, pol);
  411. }
  412. }
  413. BOOST_MATH_INSTRUMENT_VARIABLE(sum);
  414. for(auto i = k + 1; ; ++i)
  415. {
  416. poisf *= d2 / (i + 0.5f);
  417. xtermf *= (x * (n / 2 + i)) / (i);
  418. T term = poisf * xtermf;
  419. sum += term;
  420. if((fabs(term/sum) < errtol) || (term == 0))
  421. break;
  422. ++count;
  423. if(count > max_iter)
  424. {
  425. return policies::raise_evaluation_error(
  426. "pdf(non_central_t_distribution<%1%>, %1%)",
  427. "Series did not converge, closest value was %1%", sum, pol);
  428. }
  429. }
  430. BOOST_MATH_INSTRUMENT_VARIABLE(sum);
  431. return sum;
  432. }
  433. template <class T, class Policy>
  434. T non_central_t_pdf(T n, T delta, T t, const Policy& pol)
  435. {
  436. BOOST_MATH_STD_USING
  437. if ((boost::math::isinf)(n))
  438. { // Infinite degrees of freedom, so use normal distribution located at delta.
  439. normal_distribution<T, Policy> norm(delta, 1);
  440. return pdf(norm, t);
  441. }
  442. //
  443. // Otherwise, for t < 0 we have to use the reflection formula:
  444. if(t < 0)
  445. {
  446. t = -t;
  447. delta = -delta;
  448. }
  449. if(t == 0)
  450. {
  451. //
  452. // Handle this as a special case, using the formula
  453. // from Weisstein, Eric W.
  454. // "Noncentral Student's t-Distribution."
  455. // From MathWorld--A Wolfram Web Resource.
  456. // http://mathworld.wolfram.com/NoncentralStudentst-Distribution.html
  457. //
  458. // The formula is simplified thanks to the relation
  459. // 1F1(a,b,0) = 1.
  460. //
  461. return tgamma_delta_ratio(n / 2 + 0.5f, T(0.5f))
  462. * sqrt(n / constants::pi<T>())
  463. * exp(-delta * delta / 2) / 2;
  464. }
  465. if(fabs(delta / (4 * n)) < policies::get_epsilon<T, Policy>())
  466. {
  467. // Approximate with a Student's T centred on delta,
  468. // the crossover point is based on eq 2.6 from
  469. // "A Comparison of Approximations To Percentiles of the
  470. // Noncentral t-Distribution". H. Sahai and M. M. Ojeda,
  471. // Revista Investigacion Operacional Vol 21, No 2, 2000.
  472. // Original sources referenced in the above are:
  473. // "Some Approximations to the Percentage Points of the Noncentral
  474. // t-Distribution". C. van Eeden. International Statistical Review, 29, 4-31.
  475. // "Continuous Univariate Distributions". N.L. Johnson, S. Kotz and
  476. // N. Balkrishnan. 1995. John Wiley and Sons New York.
  477. return pdf(students_t_distribution<T, Policy>(n), t - delta);
  478. }
  479. //
  480. // x and y are the corresponding random
  481. // variables for the noncentral beta distribution,
  482. // with y = 1 - x:
  483. //
  484. T x = t * t / (n + t * t);
  485. T y = n / (n + t * t);
  486. T a = 0.5f;
  487. T b = n / 2;
  488. T d2 = delta * delta;
  489. //
  490. // Calculate pdf:
  491. //
  492. T dt = n * t / (n * n + 2 * n * t * t + t * t * t * t);
  493. BOOST_MATH_INSTRUMENT_VARIABLE(dt);
  494. T result = non_central_beta_pdf(a, b, d2, x, y, pol);
  495. BOOST_MATH_INSTRUMENT_VARIABLE(result);
  496. T tol = tools::epsilon<T>() * result * 500;
  497. result = non_central_t2_pdf(n, delta, x, y, pol, result);
  498. BOOST_MATH_INSTRUMENT_VARIABLE(result);
  499. if(result <= tol)
  500. result = 0;
  501. result *= dt;
  502. return result;
  503. }
  504. template <class T, class Policy>
  505. T mean(T v, T delta, const Policy& pol)
  506. {
  507. if ((boost::math::isinf)(v))
  508. {
  509. return delta;
  510. }
  511. BOOST_MATH_STD_USING
  512. if (v > 1 / boost::math::tools::epsilon<T>() )
  513. {
  514. //normal_distribution<T, Policy> n(delta, 1);
  515. //return boost::math::mean(n);
  516. return delta;
  517. }
  518. else
  519. {
  520. return delta * sqrt(v / 2) * tgamma_delta_ratio((v - 1) * 0.5f, T(0.5f), pol);
  521. }
  522. // Other moments use mean so using normal distribution is propagated.
  523. }
  524. template <class T, class Policy>
  525. T variance(T v, T delta, const Policy& pol)
  526. {
  527. if ((boost::math::isinf)(v))
  528. {
  529. return 1;
  530. }
  531. if (delta == 0)
  532. { // == Student's t
  533. return v / (v - 2);
  534. }
  535. T result = ((delta * delta + 1) * v) / (v - 2);
  536. T m = mean(v, delta, pol);
  537. result -= m * m;
  538. return result;
  539. }
  540. template <class T, class Policy>
  541. T skewness(T v, T delta, const Policy& pol)
  542. {
  543. BOOST_MATH_STD_USING
  544. if ((boost::math::isinf)(v))
  545. {
  546. return 0;
  547. }
  548. if(delta == 0)
  549. { // == Student's t
  550. return 0;
  551. }
  552. T mean = boost::math::detail::mean(v, delta, pol);
  553. T l2 = delta * delta;
  554. T var = ((l2 + 1) * v) / (v - 2) - mean * mean;
  555. T result = -2 * var;
  556. result += v * (l2 + 2 * v - 3) / ((v - 3) * (v - 2));
  557. result *= mean;
  558. result /= pow(var, T(1.5f));
  559. return result;
  560. }
  561. template <class T, class Policy>
  562. T kurtosis_excess(T v, T delta, const Policy& pol)
  563. {
  564. BOOST_MATH_STD_USING
  565. if ((boost::math::isinf)(v))
  566. {
  567. return 1;
  568. }
  569. if (delta == 0)
  570. { // == Student's t
  571. return 1;
  572. }
  573. T mean = boost::math::detail::mean(v, delta, pol);
  574. T l2 = delta * delta;
  575. T var = ((l2 + 1) * v) / (v - 2) - mean * mean;
  576. T result = -3 * var;
  577. result += v * (l2 * (v + 1) + 3 * (3 * v - 5)) / ((v - 3) * (v - 2));
  578. result *= -mean * mean;
  579. result += v * v * (l2 * l2 + 6 * l2 + 3) / ((v - 4) * (v - 2));
  580. result /= var * var;
  581. result -= static_cast<T>(3);
  582. return result;
  583. }
  584. #if 0
  585. //
  586. // This code is disabled, since there can be multiple answers to the
  587. // question, and it's not clear how to find the "right" one.
  588. //
  589. template <class RealType, class Policy>
  590. struct t_degrees_of_freedom_finder
  591. {
  592. t_degrees_of_freedom_finder(
  593. RealType delta_, RealType x_, RealType p_, bool c)
  594. : delta(delta_), x(x_), p(p_), comp(c) {}
  595. RealType operator()(const RealType& v)
  596. {
  597. non_central_t_distribution<RealType, Policy> d(v, delta);
  598. return comp ?
  599. p - cdf(complement(d, x))
  600. : cdf(d, x) - p;
  601. }
  602. private:
  603. RealType delta;
  604. RealType x;
  605. RealType p;
  606. bool comp;
  607. };
  608. template <class RealType, class Policy>
  609. inline RealType find_t_degrees_of_freedom(
  610. RealType delta, RealType x, RealType p, RealType q, const Policy& pol)
  611. {
  612. const char* function = "non_central_t<%1%>::find_degrees_of_freedom";
  613. if((p == 0) || (q == 0))
  614. {
  615. //
  616. // Can't a thing if one of p and q is zero:
  617. //
  618. return policies::raise_evaluation_error<RealType>(function,
  619. "Can't find degrees of freedom when the probability is 0 or 1, only possible answer is %1%",
  620. RealType(std::numeric_limits<RealType>::quiet_NaN()), Policy());
  621. }
  622. t_degrees_of_freedom_finder<RealType, Policy> f(delta, x, p < q ? p : q, p < q ? false : true);
  623. tools::eps_tolerance<RealType> tol(policies::digits<RealType, Policy>());
  624. std::uintmax_t max_iter = policies::get_max_root_iterations<Policy>();
  625. //
  626. // Pick an initial guess:
  627. //
  628. RealType guess = 200;
  629. std::pair<RealType, RealType> ir = tools::bracket_and_solve_root(
  630. f, guess, RealType(2), false, tol, max_iter, pol);
  631. RealType result = ir.first + (ir.second - ir.first) / 2;
  632. if(max_iter >= policies::get_max_root_iterations<Policy>())
  633. {
  634. return policies::raise_evaluation_error<RealType>(function, "Unable to locate solution in a reasonable time:"
  635. " or there is no answer to problem. Current best guess is %1%", result, Policy());
  636. }
  637. return result;
  638. }
  639. template <class RealType, class Policy>
  640. struct t_non_centrality_finder
  641. {
  642. t_non_centrality_finder(
  643. RealType v_, RealType x_, RealType p_, bool c)
  644. : v(v_), x(x_), p(p_), comp(c) {}
  645. RealType operator()(const RealType& delta)
  646. {
  647. non_central_t_distribution<RealType, Policy> d(v, delta);
  648. return comp ?
  649. p - cdf(complement(d, x))
  650. : cdf(d, x) - p;
  651. }
  652. private:
  653. RealType v;
  654. RealType x;
  655. RealType p;
  656. bool comp;
  657. };
  658. template <class RealType, class Policy>
  659. inline RealType find_t_non_centrality(
  660. RealType v, RealType x, RealType p, RealType q, const Policy& pol)
  661. {
  662. const char* function = "non_central_t<%1%>::find_t_non_centrality";
  663. if((p == 0) || (q == 0))
  664. {
  665. //
  666. // Can't do a thing if one of p and q is zero:
  667. //
  668. return policies::raise_evaluation_error<RealType>(function,
  669. "Can't find non-centrality parameter when the probability is 0 or 1, only possible answer is %1%",
  670. RealType(std::numeric_limits<RealType>::quiet_NaN()), Policy());
  671. }
  672. t_non_centrality_finder<RealType, Policy> f(v, x, p < q ? p : q, p < q ? false : true);
  673. tools::eps_tolerance<RealType> tol(policies::digits<RealType, Policy>());
  674. std::uintmax_t max_iter = policies::get_max_root_iterations<Policy>();
  675. //
  676. // Pick an initial guess that we know is the right side of
  677. // zero:
  678. //
  679. RealType guess;
  680. if(f(0) < 0)
  681. guess = 1;
  682. else
  683. guess = -1;
  684. std::pair<RealType, RealType> ir = tools::bracket_and_solve_root(
  685. f, guess, RealType(2), false, tol, max_iter, pol);
  686. RealType result = ir.first + (ir.second - ir.first) / 2;
  687. if(max_iter >= policies::get_max_root_iterations<Policy>())
  688. {
  689. return policies::raise_evaluation_error<RealType>(function, "Unable to locate solution in a reasonable time:"
  690. " or there is no answer to problem. Current best guess is %1%", result, Policy());
  691. }
  692. return result;
  693. }
  694. #endif
  695. } // namespace detail ======================================================================
  696. template <class RealType = double, class Policy = policies::policy<> >
  697. class non_central_t_distribution
  698. {
  699. public:
  700. typedef RealType value_type;
  701. typedef Policy policy_type;
  702. non_central_t_distribution(RealType v_, RealType lambda) : v(v_), ncp(lambda)
  703. {
  704. const char* function = "boost::math::non_central_t_distribution<%1%>::non_central_t_distribution(%1%,%1%)";
  705. RealType r;
  706. detail::check_df_gt0_to_inf(
  707. function,
  708. v, &r, Policy());
  709. detail::check_non_centrality(
  710. function,
  711. static_cast<value_type>(lambda * lambda),
  712. &r,
  713. Policy());
  714. } // non_central_t_distribution constructor.
  715. RealType degrees_of_freedom() const
  716. { // Private data getter function.
  717. return v;
  718. }
  719. RealType non_centrality() const
  720. { // Private data getter function.
  721. return ncp;
  722. }
  723. #if 0
  724. //
  725. // This code is disabled, since there can be multiple answers to the
  726. // question, and it's not clear how to find the "right" one.
  727. //
  728. static RealType find_degrees_of_freedom(RealType delta, RealType x, RealType p)
  729. {
  730. const char* function = "non_central_t<%1%>::find_degrees_of_freedom";
  731. typedef typename policies::evaluation<RealType, Policy>::type value_type;
  732. typedef typename policies::normalise<
  733. Policy,
  734. policies::promote_float<false>,
  735. policies::promote_double<false>,
  736. policies::discrete_quantile<>,
  737. policies::assert_undefined<> >::type forwarding_policy;
  738. value_type result = detail::find_t_degrees_of_freedom(
  739. static_cast<value_type>(delta),
  740. static_cast<value_type>(x),
  741. static_cast<value_type>(p),
  742. static_cast<value_type>(1-p),
  743. forwarding_policy());
  744. return policies::checked_narrowing_cast<RealType, forwarding_policy>(
  745. result,
  746. function);
  747. }
  748. template <class A, class B, class C>
  749. static RealType find_degrees_of_freedom(const complemented3_type<A,B,C>& c)
  750. {
  751. const char* function = "non_central_t<%1%>::find_degrees_of_freedom";
  752. typedef typename policies::evaluation<RealType, Policy>::type value_type;
  753. typedef typename policies::normalise<
  754. Policy,
  755. policies::promote_float<false>,
  756. policies::promote_double<false>,
  757. policies::discrete_quantile<>,
  758. policies::assert_undefined<> >::type forwarding_policy;
  759. value_type result = detail::find_t_degrees_of_freedom(
  760. static_cast<value_type>(c.dist),
  761. static_cast<value_type>(c.param1),
  762. static_cast<value_type>(1-c.param2),
  763. static_cast<value_type>(c.param2),
  764. forwarding_policy());
  765. return policies::checked_narrowing_cast<RealType, forwarding_policy>(
  766. result,
  767. function);
  768. }
  769. static RealType find_non_centrality(RealType v, RealType x, RealType p)
  770. {
  771. const char* function = "non_central_t<%1%>::find_t_non_centrality";
  772. typedef typename policies::evaluation<RealType, Policy>::type value_type;
  773. typedef typename policies::normalise<
  774. Policy,
  775. policies::promote_float<false>,
  776. policies::promote_double<false>,
  777. policies::discrete_quantile<>,
  778. policies::assert_undefined<> >::type forwarding_policy;
  779. value_type result = detail::find_t_non_centrality(
  780. static_cast<value_type>(v),
  781. static_cast<value_type>(x),
  782. static_cast<value_type>(p),
  783. static_cast<value_type>(1-p),
  784. forwarding_policy());
  785. return policies::checked_narrowing_cast<RealType, forwarding_policy>(
  786. result,
  787. function);
  788. }
  789. template <class A, class B, class C>
  790. static RealType find_non_centrality(const complemented3_type<A,B,C>& c)
  791. {
  792. const char* function = "non_central_t<%1%>::find_t_non_centrality";
  793. typedef typename policies::evaluation<RealType, Policy>::type value_type;
  794. typedef typename policies::normalise<
  795. Policy,
  796. policies::promote_float<false>,
  797. policies::promote_double<false>,
  798. policies::discrete_quantile<>,
  799. policies::assert_undefined<> >::type forwarding_policy;
  800. value_type result = detail::find_t_non_centrality(
  801. static_cast<value_type>(c.dist),
  802. static_cast<value_type>(c.param1),
  803. static_cast<value_type>(1-c.param2),
  804. static_cast<value_type>(c.param2),
  805. forwarding_policy());
  806. return policies::checked_narrowing_cast<RealType, forwarding_policy>(
  807. result,
  808. function);
  809. }
  810. #endif
  811. private:
  812. // Data member, initialized by constructor.
  813. RealType v; // degrees of freedom
  814. RealType ncp; // non-centrality parameter
  815. }; // template <class RealType, class Policy> class non_central_t_distribution
  816. typedef non_central_t_distribution<double> non_central_t; // Reserved name of type double.
  817. #ifdef __cpp_deduction_guides
  818. template <class RealType>
  819. non_central_t_distribution(RealType,RealType)->non_central_t_distribution<typename boost::math::tools::promote_args<RealType>::type>;
  820. #endif
  821. // Non-member functions to give properties of the distribution.
  822. template <class RealType, class Policy>
  823. inline const std::pair<RealType, RealType> range(const non_central_t_distribution<RealType, Policy>& /* dist */)
  824. { // Range of permissible values for random variable k.
  825. using boost::math::tools::max_value;
  826. return std::pair<RealType, RealType>(-max_value<RealType>(), max_value<RealType>());
  827. }
  828. template <class RealType, class Policy>
  829. inline const std::pair<RealType, RealType> support(const non_central_t_distribution<RealType, Policy>& /* dist */)
  830. { // Range of supported values for random variable k.
  831. // This is range where cdf rises from 0 to 1, and outside it, the pdf is zero.
  832. using boost::math::tools::max_value;
  833. return std::pair<RealType, RealType>(-max_value<RealType>(), max_value<RealType>());
  834. }
  835. template <class RealType, class Policy>
  836. inline RealType mode(const non_central_t_distribution<RealType, Policy>& dist)
  837. { // mode.
  838. static const char* function = "mode(non_central_t_distribution<%1%> const&)";
  839. RealType v = dist.degrees_of_freedom();
  840. RealType l = dist.non_centrality();
  841. RealType r;
  842. if(!detail::check_df_gt0_to_inf(
  843. function,
  844. v, &r, Policy())
  845. ||
  846. !detail::check_non_centrality(
  847. function,
  848. static_cast<RealType>(l * l),
  849. &r,
  850. Policy()))
  851. return static_cast<RealType>(r);
  852. BOOST_MATH_STD_USING
  853. RealType m = v < 3 ? 0 : detail::mean(v, l, Policy());
  854. RealType var = v < 4 ? 1 : detail::variance(v, l, Policy());
  855. return detail::generic_find_mode(
  856. dist,
  857. m,
  858. function,
  859. sqrt(var));
  860. }
  861. template <class RealType, class Policy>
  862. inline RealType mean(const non_central_t_distribution<RealType, Policy>& dist)
  863. {
  864. BOOST_MATH_STD_USING
  865. const char* function = "mean(const non_central_t_distribution<%1%>&)";
  866. typedef typename policies::evaluation<RealType, Policy>::type value_type;
  867. typedef typename policies::normalise<
  868. Policy,
  869. policies::promote_float<false>,
  870. policies::promote_double<false>,
  871. policies::discrete_quantile<>,
  872. policies::assert_undefined<> >::type forwarding_policy;
  873. RealType v = dist.degrees_of_freedom();
  874. RealType l = dist.non_centrality();
  875. RealType r;
  876. if(!detail::check_df_gt0_to_inf(
  877. function,
  878. v, &r, Policy())
  879. ||
  880. !detail::check_non_centrality(
  881. function,
  882. static_cast<RealType>(l * l),
  883. &r,
  884. Policy()))
  885. return static_cast<RealType>(r);
  886. if(v <= 1)
  887. return policies::raise_domain_error<RealType>(
  888. function,
  889. "The non-central t distribution has no defined mean for degrees of freedom <= 1: got v=%1%.", v, Policy());
  890. // return l * sqrt(v / 2) * tgamma_delta_ratio((v - 1) * 0.5f, RealType(0.5f));
  891. return policies::checked_narrowing_cast<RealType, forwarding_policy>(
  892. detail::mean(static_cast<value_type>(v), static_cast<value_type>(l), forwarding_policy()), function);
  893. } // mean
  894. template <class RealType, class Policy>
  895. inline RealType variance(const non_central_t_distribution<RealType, Policy>& dist)
  896. { // variance.
  897. const char* function = "variance(const non_central_t_distribution<%1%>&)";
  898. typedef typename policies::evaluation<RealType, Policy>::type value_type;
  899. typedef typename policies::normalise<
  900. Policy,
  901. policies::promote_float<false>,
  902. policies::promote_double<false>,
  903. policies::discrete_quantile<>,
  904. policies::assert_undefined<> >::type forwarding_policy;
  905. BOOST_MATH_STD_USING
  906. RealType v = dist.degrees_of_freedom();
  907. RealType l = dist.non_centrality();
  908. RealType r;
  909. if(!detail::check_df_gt0_to_inf(
  910. function,
  911. v, &r, Policy())
  912. ||
  913. !detail::check_non_centrality(
  914. function,
  915. static_cast<RealType>(l * l),
  916. &r,
  917. Policy()))
  918. return static_cast<RealType>(r);
  919. if(v <= 2)
  920. return policies::raise_domain_error<RealType>(
  921. function,
  922. "The non-central t distribution has no defined variance for degrees of freedom <= 2: got v=%1%.", v, Policy());
  923. return policies::checked_narrowing_cast<RealType, forwarding_policy>(
  924. detail::variance(static_cast<value_type>(v), static_cast<value_type>(l), forwarding_policy()), function);
  925. }
  926. // RealType standard_deviation(const non_central_t_distribution<RealType, Policy>& dist)
  927. // standard_deviation provided by derived accessors.
  928. template <class RealType, class Policy>
  929. inline RealType skewness(const non_central_t_distribution<RealType, Policy>& dist)
  930. { // skewness = sqrt(l).
  931. const char* function = "skewness(const non_central_t_distribution<%1%>&)";
  932. typedef typename policies::evaluation<RealType, Policy>::type value_type;
  933. typedef typename policies::normalise<
  934. Policy,
  935. policies::promote_float<false>,
  936. policies::promote_double<false>,
  937. policies::discrete_quantile<>,
  938. policies::assert_undefined<> >::type forwarding_policy;
  939. RealType v = dist.degrees_of_freedom();
  940. RealType l = dist.non_centrality();
  941. RealType r;
  942. if(!detail::check_df_gt0_to_inf(
  943. function,
  944. v, &r, Policy())
  945. ||
  946. !detail::check_non_centrality(
  947. function,
  948. static_cast<RealType>(l * l),
  949. &r,
  950. Policy()))
  951. return static_cast<RealType>(r);
  952. if(v <= 3)
  953. return policies::raise_domain_error<RealType>(
  954. function,
  955. "The non-central t distribution has no defined skewness for degrees of freedom <= 3: got v=%1%.", v, Policy());;
  956. return policies::checked_narrowing_cast<RealType, forwarding_policy>(
  957. detail::skewness(static_cast<value_type>(v), static_cast<value_type>(l), forwarding_policy()), function);
  958. }
  959. template <class RealType, class Policy>
  960. inline RealType kurtosis_excess(const non_central_t_distribution<RealType, Policy>& dist)
  961. {
  962. const char* function = "kurtosis_excess(const non_central_t_distribution<%1%>&)";
  963. typedef typename policies::evaluation<RealType, Policy>::type value_type;
  964. typedef typename policies::normalise<
  965. Policy,
  966. policies::promote_float<false>,
  967. policies::promote_double<false>,
  968. policies::discrete_quantile<>,
  969. policies::assert_undefined<> >::type forwarding_policy;
  970. RealType v = dist.degrees_of_freedom();
  971. RealType l = dist.non_centrality();
  972. RealType r;
  973. if(!detail::check_df_gt0_to_inf(
  974. function,
  975. v, &r, Policy())
  976. ||
  977. !detail::check_non_centrality(
  978. function,
  979. static_cast<RealType>(l * l),
  980. &r,
  981. Policy()))
  982. return static_cast<RealType>(r);
  983. if(v <= 4)
  984. return policies::raise_domain_error<RealType>(
  985. function,
  986. "The non-central t distribution has no defined kurtosis for degrees of freedom <= 4: got v=%1%.", v, Policy());;
  987. return policies::checked_narrowing_cast<RealType, forwarding_policy>(
  988. detail::kurtosis_excess(static_cast<value_type>(v), static_cast<value_type>(l), forwarding_policy()), function);
  989. } // kurtosis_excess
  990. template <class RealType, class Policy>
  991. inline RealType kurtosis(const non_central_t_distribution<RealType, Policy>& dist)
  992. {
  993. return kurtosis_excess(dist) + 3;
  994. }
  995. template <class RealType, class Policy>
  996. inline RealType pdf(const non_central_t_distribution<RealType, Policy>& dist, const RealType& t)
  997. { // Probability Density/Mass Function.
  998. const char* function = "pdf(non_central_t_distribution<%1%>, %1%)";
  999. typedef typename policies::evaluation<RealType, Policy>::type value_type;
  1000. typedef typename policies::normalise<
  1001. Policy,
  1002. policies::promote_float<false>,
  1003. policies::promote_double<false>,
  1004. policies::discrete_quantile<>,
  1005. policies::assert_undefined<> >::type forwarding_policy;
  1006. RealType v = dist.degrees_of_freedom();
  1007. RealType l = dist.non_centrality();
  1008. RealType r;
  1009. if(!detail::check_df_gt0_to_inf(
  1010. function,
  1011. v, &r, Policy())
  1012. ||
  1013. !detail::check_non_centrality(
  1014. function,
  1015. static_cast<RealType>(l * l), // we need l^2 to be countable.
  1016. &r,
  1017. Policy())
  1018. ||
  1019. !detail::check_x(
  1020. function,
  1021. t,
  1022. &r,
  1023. Policy()))
  1024. return static_cast<RealType>(r);
  1025. return policies::checked_narrowing_cast<RealType, forwarding_policy>(
  1026. detail::non_central_t_pdf(static_cast<value_type>(v),
  1027. static_cast<value_type>(l),
  1028. static_cast<value_type>(t),
  1029. Policy()),
  1030. function);
  1031. } // pdf
  1032. template <class RealType, class Policy>
  1033. RealType cdf(const non_central_t_distribution<RealType, Policy>& dist, const RealType& x)
  1034. {
  1035. const char* function = "boost::math::cdf(non_central_t_distribution<%1%>&, %1%)";
  1036. // was const char* function = "boost::math::non_central_t_distribution<%1%>::cdf(%1%)";
  1037. typedef typename policies::evaluation<RealType, Policy>::type value_type;
  1038. typedef typename policies::normalise<
  1039. Policy,
  1040. policies::promote_float<false>,
  1041. policies::promote_double<false>,
  1042. policies::discrete_quantile<>,
  1043. policies::assert_undefined<> >::type forwarding_policy;
  1044. RealType v = dist.degrees_of_freedom();
  1045. RealType l = dist.non_centrality();
  1046. RealType r;
  1047. if(!detail::check_df_gt0_to_inf(
  1048. function,
  1049. v, &r, Policy())
  1050. ||
  1051. !detail::check_non_centrality(
  1052. function,
  1053. static_cast<RealType>(l * l),
  1054. &r,
  1055. Policy())
  1056. ||
  1057. !detail::check_x(
  1058. function,
  1059. x,
  1060. &r,
  1061. Policy()))
  1062. return static_cast<RealType>(r);
  1063. if ((boost::math::isinf)(v))
  1064. { // Infinite degrees of freedom, so use normal distribution located at delta.
  1065. normal_distribution<RealType, Policy> n(l, 1);
  1066. cdf(n, x);
  1067. //return cdf(normal_distribution<RealType, Policy>(l, 1), x);
  1068. }
  1069. if(l == 0)
  1070. { // NO non-centrality, so use Student's t instead.
  1071. return cdf(students_t_distribution<RealType, Policy>(v), x);
  1072. }
  1073. return policies::checked_narrowing_cast<RealType, forwarding_policy>(
  1074. detail::non_central_t_cdf(
  1075. static_cast<value_type>(v),
  1076. static_cast<value_type>(l),
  1077. static_cast<value_type>(x),
  1078. false, Policy()),
  1079. function);
  1080. } // cdf
  1081. template <class RealType, class Policy>
  1082. RealType cdf(const complemented2_type<non_central_t_distribution<RealType, Policy>, RealType>& c)
  1083. { // Complemented Cumulative Distribution Function
  1084. // was const char* function = "boost::math::non_central_t_distribution<%1%>::cdf(%1%)";
  1085. const char* function = "boost::math::cdf(const complement(non_central_t_distribution<%1%>&), %1%)";
  1086. typedef typename policies::evaluation<RealType, Policy>::type value_type;
  1087. typedef typename policies::normalise<
  1088. Policy,
  1089. policies::promote_float<false>,
  1090. policies::promote_double<false>,
  1091. policies::discrete_quantile<>,
  1092. policies::assert_undefined<> >::type forwarding_policy;
  1093. non_central_t_distribution<RealType, Policy> const& dist = c.dist;
  1094. RealType x = c.param;
  1095. RealType v = dist.degrees_of_freedom();
  1096. RealType l = dist.non_centrality(); // aka delta
  1097. RealType r;
  1098. if(!detail::check_df_gt0_to_inf(
  1099. function,
  1100. v, &r, Policy())
  1101. ||
  1102. !detail::check_non_centrality(
  1103. function,
  1104. static_cast<RealType>(l * l),
  1105. &r,
  1106. Policy())
  1107. ||
  1108. !detail::check_x(
  1109. function,
  1110. x,
  1111. &r,
  1112. Policy()))
  1113. return static_cast<RealType>(r);
  1114. if ((boost::math::isinf)(v))
  1115. { // Infinite degrees of freedom, so use normal distribution located at delta.
  1116. normal_distribution<RealType, Policy> n(l, 1);
  1117. return cdf(complement(n, x));
  1118. }
  1119. if(l == 0)
  1120. { // zero non-centrality so use Student's t distribution.
  1121. return cdf(complement(students_t_distribution<RealType, Policy>(v), x));
  1122. }
  1123. return policies::checked_narrowing_cast<RealType, forwarding_policy>(
  1124. detail::non_central_t_cdf(
  1125. static_cast<value_type>(v),
  1126. static_cast<value_type>(l),
  1127. static_cast<value_type>(x),
  1128. true, Policy()),
  1129. function);
  1130. } // ccdf
  1131. template <class RealType, class Policy>
  1132. inline RealType quantile(const non_central_t_distribution<RealType, Policy>& dist, const RealType& p)
  1133. { // Quantile (or Percent Point) function.
  1134. static const char* function = "quantile(const non_central_t_distribution<%1%>, %1%)";
  1135. RealType v = dist.degrees_of_freedom();
  1136. RealType l = dist.non_centrality();
  1137. return detail::non_central_t_quantile(function, v, l, p, RealType(1-p), Policy());
  1138. } // quantile
  1139. template <class RealType, class Policy>
  1140. inline RealType quantile(const complemented2_type<non_central_t_distribution<RealType, Policy>, RealType>& c)
  1141. { // Quantile (or Percent Point) function.
  1142. static const char* function = "quantile(const complement(non_central_t_distribution<%1%>, %1%))";
  1143. non_central_t_distribution<RealType, Policy> const& dist = c.dist;
  1144. RealType q = c.param;
  1145. RealType v = dist.degrees_of_freedom();
  1146. RealType l = dist.non_centrality();
  1147. return detail::non_central_t_quantile(function, v, l, RealType(1-q), q, Policy());
  1148. } // quantile complement.
  1149. } // namespace math
  1150. } // namespace boost
  1151. // This include must be at the end, *after* the accessors
  1152. // for this distribution have been defined, in order to
  1153. // keep compilers that support two-phase lookup happy.
  1154. #include <boost/math/distributions/detail/derived_accessors.hpp>
  1155. #endif // BOOST_MATH_SPECIAL_NON_CENTRAL_T_HPP