non_central_t.hpp 48 KB

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