gsl_cdf__tdistinv.c 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238
  1. /* cdf/tdistinv.c
  2. *
  3. * Copyright (C) 2007 Brian Gough
  4. * Copyright (C) 2002 Jason H. Stover.
  5. *
  6. * This program is free software; you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation; either version 3 of the License, or (at
  9. * your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful, but
  12. * WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  14. * General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with this program; if not, write to the Free Software
  18. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
  19. */
  20. #include "gsl__config.h"
  21. #include <math.h>
  22. #include "gsl_cdf.h"
  23. #include "gsl_math.h"
  24. #include "gsl_randist.h"
  25. #include "gsl_sf_gamma.h"
  26. #include <stdio.h>
  27. static double
  28. inv_cornish_fisher (double z, double nu)
  29. {
  30. double a = 1 / (nu - 0.5);
  31. double b = 48.0 / (a * a);
  32. double cf1 = z * (3 + z * z);
  33. double cf2 = z * (945 + z * z * (360 + z * z * (63 + z * z * 4)));
  34. double y = z - cf1 / b + cf2 / (10 * b * b);
  35. double t = GSL_SIGN (z) * sqrt (nu * expm1 (a * y * y));
  36. return t;
  37. }
  38. double
  39. gsl_cdf_tdist_Pinv (const double P, const double nu)
  40. {
  41. double x, ptail;
  42. if (P == 1.0)
  43. {
  44. return GSL_POSINF;
  45. }
  46. else if (P == 0.0)
  47. {
  48. return GSL_NEGINF;
  49. }
  50. if (nu == 1.0)
  51. {
  52. x = tan (M_PI * (P - 0.5));
  53. }
  54. else if (nu == 2.0)
  55. {
  56. double a = 2 * P - 1;
  57. x = a / sqrt (2 * (1 - a * a));
  58. }
  59. ptail = (P < 0.5) ? P : 1 - P;
  60. if (sqrt (M_PI * nu / 2) * ptail > pow (0.05, nu / 2))
  61. {
  62. double xg = gsl_cdf_ugaussian_Pinv (P);
  63. x = inv_cornish_fisher (xg, nu);
  64. }
  65. else
  66. {
  67. /* Use an asymptotic expansion of the tail of integral */
  68. double beta = gsl_sf_beta (0.5, nu / 2);
  69. if (P < 0.5)
  70. {
  71. x = -sqrt (nu) * pow (beta * nu * P, -1.0 / nu);
  72. }
  73. else
  74. {
  75. x = sqrt (nu) * pow (beta * nu * (1 - P), -1.0 / nu);
  76. }
  77. /* Correct nu -> nu/(1+nu/x^2) in the leading term to account
  78. for higher order terms. This avoids overestimating x, which
  79. makes the iteration unstable due to the rapidly decreasing
  80. tails of the distribution. */
  81. x /= sqrt (1 + nu / (x * x));
  82. }
  83. {
  84. double dP, phi;
  85. unsigned int n = 0;
  86. start:
  87. dP = P - gsl_cdf_tdist_P (x, nu);
  88. phi = gsl_ran_tdist_pdf (x, nu);
  89. if (dP == 0.0 || n++ > 32)
  90. goto end;
  91. {
  92. double lambda = dP / phi;
  93. double step0 = lambda;
  94. double step1 = ((nu + 1) * x / (x * x + nu)) * (lambda * lambda / 4.0);
  95. double step = step0;
  96. if (fabs (step1) < fabs (step0))
  97. {
  98. step += step1;
  99. }
  100. if (P > 0.5 && x + step < 0)
  101. x /= 2;
  102. else if (P < 0.5 && x + step > 0)
  103. x /= 2;
  104. else
  105. x += step;
  106. if (fabs (step) > 1e-10 * fabs (x))
  107. goto start;
  108. }
  109. end:
  110. if (fabs(dP) > GSL_SQRT_DBL_EPSILON * P)
  111. {
  112. GSL_ERROR_VAL("inverse failed to converge", GSL_EFAILED, GSL_NAN);
  113. }
  114. return x;
  115. }
  116. }
  117. double
  118. gsl_cdf_tdist_Qinv (const double Q, const double nu)
  119. {
  120. double x, qtail;
  121. if (Q == 0.0)
  122. {
  123. return GSL_POSINF;
  124. }
  125. else if (Q == 1.0)
  126. {
  127. return GSL_NEGINF;
  128. }
  129. if (nu == 1.0)
  130. {
  131. x = tan (M_PI * (0.5 - Q));
  132. }
  133. else if (nu == 2.0)
  134. {
  135. double a = 2 * (1 - Q) - 1;
  136. x = a / sqrt (2 * (1 - a * a));
  137. }
  138. qtail = (Q < 0.5) ? Q : 1 - Q;
  139. if (sqrt (M_PI * nu / 2) * qtail > pow (0.05, nu / 2))
  140. {
  141. double xg = gsl_cdf_ugaussian_Qinv (Q);
  142. x = inv_cornish_fisher (xg, nu);
  143. }
  144. else
  145. {
  146. /* Use an asymptotic expansion of the tail of integral */
  147. double beta = gsl_sf_beta (0.5, nu / 2);
  148. if (Q < 0.5)
  149. {
  150. x = sqrt (nu) * pow (beta * nu * Q, -1.0 / nu);
  151. }
  152. else
  153. {
  154. x = -sqrt (nu) * pow (beta * nu * (1 - Q), -1.0 / nu);
  155. }
  156. /* Correct nu -> nu/(1+nu/x^2) in the leading term to account
  157. for higher order terms. This avoids overestimating x, which
  158. makes the iteration unstable due to the rapidly decreasing
  159. tails of the distribution. */
  160. x /= sqrt (1 + nu / (x * x));
  161. }
  162. {
  163. double dQ, phi;
  164. unsigned int n = 0;
  165. start:
  166. dQ = Q - gsl_cdf_tdist_Q (x, nu);
  167. phi = gsl_ran_tdist_pdf (x, nu);
  168. if (dQ == 0.0 || n++ > 32)
  169. goto end;
  170. {
  171. double lambda = - dQ / phi;
  172. double step0 = lambda;
  173. double step1 = ((nu + 1) * x / (x * x + nu)) * (lambda * lambda / 4.0);
  174. double step = step0;
  175. if (fabs (step1) < fabs (step0))
  176. {
  177. step += step1;
  178. }
  179. if (Q < 0.5 && x + step < 0)
  180. x /= 2;
  181. else if (Q > 0.5 && x + step > 0)
  182. x /= 2;
  183. else
  184. x += step;
  185. if (fabs (step) > 1e-10 * fabs (x))
  186. goto start;
  187. }
  188. }
  189. end:
  190. return x;
  191. }