NUMmathlib.cpp 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622
  1. /*
  2. * Mathlib : A C Library of Special Functions
  3. * Copyright (C) 1998 Ross Ihaka
  4. * Copyright (C) 2000--2007 The R Core Team
  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 2 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU 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, a copy is available at
  18. * http://www.r-project.org/Licenses/
  19. *
  20. * SYNOPSIS
  21. *
  22. * #include <Rmath.h>
  23. * double ptukey(q, rr, cc, df, lower_tail, log_p);
  24. *
  25. * DESCRIPTION
  26. *
  27. * Computes the probability that the maximum of rr studentized
  28. * ranges, each based on cc means and with df degrees of freedom
  29. * for the standard error, is less than q.
  30. *
  31. * The algorithm is based on that of the reference.
  32. *
  33. * REFERENCE
  34. *
  35. * Copenhaver, Margaret Diponzio & Holland, Burt S.
  36. * Multiple comparisons of simple effects in
  37. * the two-way analysis of variance with fixed effects.
  38. * Journal of Statistical Computation and Simulation,
  39. * Vol.30, pp.1-15, 1988.
  40. */
  41. #include "NUM2.h"
  42. #define R_Q_P01_boundaries(p, _LEFT_, _RIGHT_) \
  43. if (log_p) { \
  44. if (p > 0.0) \
  45. return undefined; \
  46. if (p == 0.0) /* upper bound*/ \
  47. return lower_tail ? _RIGHT_ : _LEFT_; \
  48. if (isundef (p)) /* cannot occur*/ \
  49. return lower_tail ? _LEFT_ : _RIGHT_; \
  50. } else { /* !log_p */ \
  51. if (p < 0.0 || p > 1.0) \
  52. return undefined; \
  53. if (p == 0.0) \
  54. return lower_tail ? _LEFT_ : _RIGHT_; \
  55. if (p == 1.0) \
  56. return lower_tail ? _RIGHT_ : _LEFT_; \
  57. }
  58. #define R_D_Lval(p) (lower_tail ? (p) : (0.5 - (p) + 0.5))
  59. #define R_DT_qIv(p) (log_p ? (lower_tail ? exp(p) : - expm1(p)) : R_D_Lval(p))
  60. #define R_D__0 (log_p ? undefined : 0.0) /* 0 */
  61. #define R_D__1 (log_p ? 0.0 : 1.0) /* 1 */
  62. #define R_DT_0 (lower_tail ? R_D__0 : R_D__1) /* 0 */
  63. #define R_DT_1 (lower_tail ? R_D__1 : R_D__0) /* 1 */
  64. #define R_D_val(x) (log_p ? log(x) : (x))
  65. #define R_D_Clog(p) (log_p ? log1p(-(p)) : (0.5 - (p) + 0.5)) /* [log](1-p) */
  66. #define R_DT_val(x) (lower_tail ? R_D_val(x) : R_D_Clog(x))
  67. static double wprob(double w, double rr, double cc)
  68. {
  69. /* wprob() :
  70. This function calculates probability integral of Hartley's
  71. form of the range.
  72. w = value of range
  73. rr = no. of rows or groups
  74. cc = no. of columns or treatments
  75. ir = error flag = 1 if pr_w probability > 1
  76. pr_w = returned probability integral from (0, w)
  77. program will not terminate if ir is raised.
  78. bb = upper limit of legendre integration
  79. iMax = maximum acceptable value of integral
  80. nleg = order of legendre quadrature
  81. ihalf = int ((nleg + 1) / 2)
  82. wlar = value of range above which wincr1 intervals are used to
  83. calculate second part of integral,
  84. else wincr2 intervals are used.
  85. C1, C2, C3 = values which are used as cutoffs for terminating
  86. or modifying a calculation.
  87. M_1_SQRT_2PI = 1 / sqrt(2 * pi); from abramowitz & stegun, p. 3.
  88. M_SQRT2 = sqrt(2)
  89. xleg = legendre 12-point nodes
  90. aleg = legendre 12-point coefficients
  91. */
  92. #define nleg 12
  93. #define ihalf 6
  94. /* looks like this is suboptimal for double precision.
  95. (see how C1-C3 are used) <MM>
  96. */
  97. /* const double iMax = 1.; not used if = 1*/
  98. const static double C1 = -30.;
  99. const static double C2 = -50.;
  100. const static double C3 = 60.;
  101. const static double bb = 8.;
  102. const static double wlar = 3.;
  103. const static double wincr1 = 2.;
  104. const static double wincr2 = 3.;
  105. const static double xleg[ihalf] = {
  106. 0.981560634246719250690549090149,
  107. 0.904117256370474856678465866119,
  108. 0.769902674194304687036893833213,
  109. 0.587317954286617447296702418941,
  110. 0.367831498998180193752691536644,
  111. 0.125233408511468915472441369464
  112. };
  113. const static double aleg[ihalf] = {
  114. 0.047175336386511827194615961485,
  115. 0.106939325995318430960254718194,
  116. 0.160078328543346226334652529543,
  117. 0.203167426723065921749064455810,
  118. 0.233492536538354808760849898925,
  119. 0.249147045813402785000562436043
  120. };
  121. double a, ac, pr_w, b, binc, c, cc1,
  122. pminus, pplus, qexpo, qsqz, rinsum, wi, wincr, xx;
  123. long double blb, bub, einsum, elsum;
  124. int j, jj;
  125. qsqz = w * 0.5;
  126. /* if w >= 16 then the integral lower bound (occurs for c=20) */
  127. /* is 0.99999999999995 so return a value of 1. */
  128. if (qsqz >= bb)
  129. return 1.0;
  130. /* find (f(w/2) - 1) ^ cc */
  131. /* (first term in integral of hartley's form). */
  132. // djwm: pnorm(q,m,s,1,0) = NUMgaussP((q-m)/s)
  133. // pr_w = 2 * pnorm(qsqz, 0.,1., 1,0) - 1.; /* erf(qsqz / M_SQRT2) */
  134. pr_w = 2 * NUMgaussP (qsqz) - 1.0;
  135. /* if pr_w ^ cc < 2e-22 then set pr_w = 0 */
  136. if (pr_w >= exp(C2 / cc))
  137. pr_w = pow(pr_w, cc);
  138. else
  139. pr_w = 0.0;
  140. /* if w is large then the second component of the */
  141. /* integral is small, so fewer intervals are needed. */
  142. if (w > wlar)
  143. wincr = wincr1;
  144. else
  145. wincr = wincr2;
  146. /* find the integral of second term of hartley's form */
  147. /* for the integral of the range for equal-length */
  148. /* intervals using legendre quadrature. limits of */
  149. /* integration are from (w/2, 8). two or three */
  150. /* equal-length intervals are used. */
  151. /* blb and bub are lower and upper limits of integration. */
  152. blb = qsqz;
  153. binc = (bb - qsqz) / wincr;
  154. bub = blb + binc;
  155. einsum = 0.0;
  156. /* integrate over each interval */
  157. cc1 = cc - 1.0;
  158. for (wi = 1; wi <= wincr; wi ++) {
  159. elsum = 0.0;
  160. a = double (0.5 * (bub + blb));
  161. /* legendre quadrature with order = nleg */
  162. b = double (0.5 * (bub - blb));
  163. for (jj = 1; jj <= nleg; jj ++) {
  164. if (ihalf < jj) {
  165. j = (nleg - jj) + 1;
  166. xx = xleg [j-1];
  167. } else {
  168. j = jj;
  169. xx = -xleg [j-1];
  170. }
  171. c = b * xx;
  172. ac = a + c;
  173. /* if exp(-qexpo/2) < 9e-14, */
  174. /* then doesn't contribute to integral */
  175. qexpo = ac * ac;
  176. if (qexpo > C3)
  177. break;
  178. pplus = 2 * NUMgaussP (ac); // djmw: 2 * pnorm(ac, 0., 1., 1,0);
  179. pminus= 2 * NUMgaussP (ac - w); // djmw: 2 * pnorm(ac, w, 1., 1,0);
  180. /* if rinsum ^ (cc-1) < 9e-14, */
  181. /* then doesn't contribute to integral */
  182. rinsum = pplus * 0.5 - pminus * 0.5;
  183. if (rinsum >= exp (C1 / cc1)) {
  184. rinsum = aleg[j-1] * exp(-(0.5 * qexpo)) * pow(rinsum, cc1);
  185. elsum += rinsum;
  186. }
  187. }
  188. elsum *= 2.0 * b * cc * NUM1_sqrt2pi;
  189. einsum += elsum;
  190. blb = bub;
  191. bub += binc;
  192. }
  193. /* if pr_w ^ rr < 9e-14, then return 0 */
  194. pr_w += (double) einsum;
  195. if (pr_w <= exp(C1 / rr))
  196. return 0.0;
  197. pr_w = pow(pr_w, rr);
  198. if (pr_w >= 1.0) // 1 was iMax was eps
  199. return 1.0;
  200. return pr_w;
  201. } /* wprob() */
  202. static double ptukey(double q, double rr, double cc, double df, int lower_tail, int log_p)
  203. {
  204. /* function ptukey() [was qprob() ]:
  205. q = value of studentized range
  206. rr = no. of rows or groups
  207. cc = no. of columns or treatments
  208. df = degrees of freedom of error term
  209. ir[0] = error flag = 1 if wprob probability > 1
  210. ir[1] = error flag = 1 if qprob probability > 1
  211. qprob = returned probability integral over [0, q]
  212. The program will not terminate if ir[0] or ir[1] are raised.
  213. All references in wprob to Abramowitz and Stegun
  214. are from the following reference:
  215. Abramowitz, Milton and Stegun, Irene A.
  216. Handbook of Mathematical Functions.
  217. New York: Dover publications, Inc. (1970).
  218. All constants taken from this text are
  219. given to 25 significant digits.
  220. nlegq = order of legendre quadrature
  221. ihalfq = int ((nlegq + 1) / 2)
  222. eps = max. allowable value of integral
  223. eps1 & eps2 = values below which there is
  224. no contribution to integral.
  225. d.f. <= dhaf: integral is divided into ulen1 length intervals. else
  226. d.f. <= dquar: integral is divided into ulen2 length intervals. else
  227. d.f. <= deigh: integral is divided into ulen3 length intervals. else
  228. d.f. <= dlarg: integral is divided into ulen4 length intervals.
  229. d.f. > dlarg: the range is used to calculate integral.
  230. M_LN2 = log(2)
  231. xlegq = legendre 16-point nodes
  232. alegq = legendre 16-point coefficients
  233. The coefficients and nodes for the legendre quadrature used in
  234. qprob and wprob were calculated using the algorithms found in:
  235. Stroud, A. H. and Secrest, D.
  236. Gaussian Quadrature Formulas.
  237. Englewood Cliffs,
  238. New Jersey: Prentice-Hall, Inc, 1966.
  239. All values matched the tables (provided in same reference)
  240. to 30 significant digits.
  241. f(x) = .5 + erf(x / sqrt(2)) / 2 for x > 0
  242. f(x) = erfc( -x / sqrt(2)) / 2 for x < 0
  243. where f(x) is standard normal c. d. f.
  244. if degrees of freedom large, approximate integral
  245. with range distribution.
  246. */
  247. #define nlegq 16
  248. #define ihalfq 8
  249. /* const double eps = 1.0; not used if = 1 */
  250. const static double eps1 = -30.0;
  251. const static double eps2 = 1.0e-14;
  252. const static double dhaf = 100.0;
  253. const static double dquar = 800.0;
  254. const static double deigh = 5000.0;
  255. const static double dlarg = 25000.0;
  256. const static double ulen1 = 1.0;
  257. const static double ulen2 = 0.5;
  258. const static double ulen3 = 0.25;
  259. const static double ulen4 = 0.125;
  260. const static double xlegq[ihalfq] = {
  261. 0.989400934991649932596154173450,
  262. 0.944575023073232576077988415535,
  263. 0.865631202387831743880467897712,
  264. 0.755404408355003033895101194847,
  265. 0.617876244402643748446671764049,
  266. 0.458016777657227386342419442984,
  267. 0.281603550779258913230460501460,
  268. 0.950125098376374401853193354250e-1
  269. };
  270. const static double alegq[ihalfq] = {
  271. 0.271524594117540948517805724560e-1,
  272. 0.622535239386478928628438369944e-1,
  273. 0.951585116824927848099251076022e-1,
  274. 0.124628971255533872052476282192,
  275. 0.149595988816576732081501730547,
  276. 0.169156519395002538189312079030,
  277. 0.182603415044923588866763667969,
  278. 0.189450610455068496285396723208
  279. };
  280. double ans, f2, f21, f2lf, ff4, otsum, qsqz, rotsum, t1, twa1, ulen, wprb;
  281. int i, j, jj;
  282. if (isundef (q) || isundef (rr) || isundef (cc) || isundef (df)) {
  283. return undefined;
  284. }
  285. if (q <= 0.0)
  286. return R_DT_0;
  287. /* df should be > 1 */
  288. /* there should be at least two values */
  289. if (df < 2 || rr < 1 || cc < 2) {
  290. return undefined;
  291. }
  292. // if (isundef (q) { return R_DT_1; }
  293. if (df > dlarg)
  294. return R_DT_val(wprob(q, rr, cc));
  295. /* calculate leading constant */
  296. f2 = df * 0.5;
  297. /* lgammafn(u) = log(gamma(u)) */
  298. f2lf = ((f2 * log(df)) - (df * NUMln2)) - NUMlnGamma (f2); //lgammafn(f2);
  299. f21 = f2 - 1.0;
  300. /* integral is divided into unit, half-unit, quarter-unit, or */
  301. /* eighth-unit length intervals depending on the value of the */
  302. /* degrees of freedom. */
  303. ff4 = df * 0.25;
  304. if (df <= dhaf) ulen = ulen1;
  305. else if (df <= dquar) ulen = ulen2;
  306. else if (df <= deigh) ulen = ulen3;
  307. else ulen = ulen4;
  308. f2lf += log (ulen);
  309. /* integrate over each subinterval */
  310. ans = 0.0;
  311. for (i = 1; i <= 50; i++) {
  312. otsum = 0.0;
  313. /* legendre quadrature with order = nlegq */
  314. /* nodes (stored in xlegq) are symmetric around zero. */
  315. twa1 = (2 * i - 1) * ulen;
  316. for (jj = 1; jj <= nlegq; jj ++) {
  317. if (ihalfq < jj) {
  318. j = jj - ihalfq - 1;
  319. t1 = f2lf + f21 * log (twa1 + xlegq[j] * ulen) - (xlegq[j] * ulen + twa1) * ff4;
  320. } else {
  321. j = jj - 1;
  322. t1 = f2lf + f21 * log (twa1 - xlegq[j] * ulen) + (xlegq[j] * ulen - twa1) * ff4;
  323. }
  324. /* if exp(t1) < 9e-14, then doesn't contribute to integral */
  325. if (t1 >= eps1) {
  326. if (ihalfq < jj) {
  327. qsqz = q * sqrt ((xlegq[j] * ulen + twa1) * 0.5);
  328. } else {
  329. qsqz = q * sqrt ((-(xlegq[j] * ulen) + twa1) * 0.5);
  330. }
  331. /* call wprob to find integral of range portion */
  332. wprb = wprob (qsqz, rr, cc);
  333. rotsum = wprb * alegq [j] * exp (t1);
  334. otsum += rotsum;
  335. }
  336. /* end legendre integral for interval i */
  337. /* L200: */
  338. }
  339. /* if integral for interval i < 1e-14, then stop.
  340. * However, in order to avoid small area under left tail,
  341. * at least 1 / ulen intervals are calculated.
  342. */
  343. if (i * ulen >= 1.0 && otsum <= eps2)
  344. break;
  345. /* end of interval i */
  346. /* L330: */
  347. ans += otsum;
  348. }
  349. if (otsum > eps2) { /* not converged */
  350. Melder_throw (U"Not converged");
  351. }
  352. if (ans > 1.)
  353. ans = 1.;
  354. return R_DT_val(ans);
  355. }
  356. /*
  357. * Mathlib : A C Library of Special Functions
  358. * Copyright (C) 1998 Ross Ihaka
  359. * Copyright (C) 2000--2005 The R Core Team
  360. * based in part on AS70 (C) 1974 Royal Statistical Society
  361. *
  362. * This program is free software; you can redistribute it and/or modify
  363. * it under the terms of the GNU General Public License as published by
  364. * the Free Software Foundation; either version 2 of the License, or
  365. * (at your option) any later version.
  366. *
  367. * This program is distributed in the hope that it will be useful,
  368. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  369. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  370. * GNU General Public License for more details.
  371. *
  372. * You should have received a copy of the GNU General Public License
  373. * along with this program; if not, a copy is available at
  374. * http://www.r-project.org/Licenses/
  375. *
  376. * SYNOPSIS
  377. *
  378. * double qtukey(p, rr, cc, df, lower_tail, log_p);
  379. *
  380. * DESCRIPTION
  381. *
  382. * Computes the quantiles of the maximum of rr studentized
  383. * ranges, each based on cc means and with df degrees of freedom
  384. * for the standard error, is less than q.
  385. *
  386. * The algorithm is based on that of the reference.
  387. *
  388. * REFERENCE
  389. *
  390. * Copenhaver, Margaret Diponzio & Holland, Burt S.
  391. * Multiple comparisons of simple effects in
  392. * the two-way analysis of variance with fixed effects.
  393. * Journal of Statistical Computation and Simulation,
  394. * Vol.30, pp.1-15, 1988.
  395. */
  396. /* qinv() :
  397. * this function finds percentage point of the studentized range
  398. * which is used as initial estimate for the secant method.
  399. * function is adapted from portion of algorithm as 70
  400. * from applied statistics (1974) ,vol. 23, no. 1
  401. * by odeh, r. e. and evans, j. o.
  402. *
  403. * p = percentage point
  404. * c = no. of columns or treatments
  405. * v = degrees of freedom
  406. * qinv = returned initial estimate
  407. *
  408. * vmax is cutoff above which degrees of freedom
  409. * is treated as infinity.
  410. */
  411. static double qinv(double p, double c, double v)
  412. {
  413. const static double p0 = 0.322232421088;
  414. const static double q0 = 0.993484626060e-01;
  415. const static double p1 = -1.0;
  416. const static double q1 = 0.588581570495;
  417. const static double p2 = -0.342242088547;
  418. const static double q2 = 0.531103462366;
  419. const static double p3 = -0.204231210125;
  420. const static double q3 = 0.103537752850;
  421. const static double p4 = -0.453642210148e-04;
  422. const static double q4 = 0.38560700634e-02;
  423. const static double c1 = 0.8832;
  424. const static double c2 = 0.2368;
  425. const static double c3 = 1.214;
  426. const static double c4 = 1.208;
  427. const static double c5 = 1.4142;
  428. const static double vmax = 120.0;
  429. double ps, q, t, yi;
  430. ps = 0.5 - 0.5 * p;
  431. yi = sqrt (log (1.0 / (ps * ps)));
  432. t = yi + (((( yi * p4 + p3) * yi + p2) * yi + p1) * yi + p0)
  433. / (((( yi * q4 + q3) * yi + q2) * yi + q1) * yi + q0);
  434. if (v < vmax) t += (t * t * t + t) / v / 4.0;
  435. q = c1 - c2 * t;
  436. if (v < vmax) q += -c3 / v + c4 * t / v;
  437. return t * (q * log (c - 1.0) + c5);
  438. }
  439. /*
  440. * Copenhaver, Margaret Diponzio & Holland, Burt S.
  441. * Multiple comparisons of simple effects in
  442. * the two-way analysis of variance with fixed effects.
  443. * Journal of Statistical Computation and Simulation,
  444. * Vol.30, pp.1-15, 1988.
  445. *
  446. * Uses the secant method to find critical values.
  447. *
  448. * p = confidence level (1 - alpha)
  449. * rr = no. of rows or groups
  450. * cc = no. of columns or treatments
  451. * df = degrees of freedom of error term
  452. *
  453. * ir(1) = error flag = 1 if wprob probability > 1
  454. * ir(2) = error flag = 1 if ptukey probability > 1
  455. * ir(3) = error flag = 1 if convergence not reached in 50 iterations
  456. * = 2 if df < 2
  457. *
  458. * qtukey = returned critical value
  459. *
  460. * If the difference between successive iterates is less than eps,
  461. * the search is terminated
  462. */
  463. static double qtukey(double p, double rr, double cc, double df, int lower_tail, int log_p) {
  464. const static double eps = 0.0001;
  465. const int maxiter = 50;
  466. double ans = 0.0, valx0, valx1, x0, x1, xabs;
  467. int iter;
  468. if (isundef (p) || isundef (rr) || isundef (cc) || isundef (df)) {
  469. return undefined;
  470. }
  471. /* df should be > 1 ; there should be at least two values */
  472. if (df < 2.0 || rr < 1.0 || cc < 2.0) {
  473. return undefined;
  474. }
  475. //R_Q_P01_boundaries (p, 0.0, ML_POSINF);
  476. R_Q_P01_boundaries (p, 0.0, undefined);
  477. p = R_DT_qIv (p); /* lower_tail,non-log "p" */
  478. /* Initial value */
  479. x0 = qinv (p, cc, df);
  480. /* Find prob(value < x0) */
  481. valx0 = ptukey (x0, rr, cc, df, /*LOWER*/true, /*LOG_P*/false) - p;
  482. /* Find the second iterate and prob(value < x1). */
  483. /* If the first iterate has probability value */
  484. /* exceeding p then second iterate is 1 less than */
  485. /* first iterate; otherwise it is 1 greater. */
  486. if (valx0 > 0.0)
  487. x1 = ( x0 > 1.0 ? x0 - 1.0 : 0.0 ); // djmw: fmax2 (0.0, x0 - 1.0);
  488. else
  489. x1 = x0 + 1.0;
  490. valx1 = ptukey (x1, rr, cc, df, /*LOWER*/true, /*LOG_P*/false) - p;
  491. /* Find new iterate */
  492. for (iter = 1 ; iter < maxiter; iter ++) {
  493. ans = x1 - ((valx1 * (x1 - x0)) / (valx1 - valx0));
  494. valx0 = valx1;
  495. /* New iterate should be >= 0 */
  496. x0 = x1;
  497. if (ans < 0.0) {
  498. ans = 0.0;
  499. valx1 = -p;
  500. }
  501. /* Find prob(value < new iterate) */
  502. valx1 = ptukey (ans, rr, cc, df, /*LOWER*/true, /*LOG_P*/false) - p;
  503. x1 = ans;
  504. /* If the difference between two successive */
  505. /* iterates is less than eps, stop */
  506. xabs = fabs (x1 - x0);
  507. if (xabs < eps)
  508. return ans;
  509. }
  510. /* The process did not converge in 'maxiter' iterations */
  511. Melder_warning (U"Maximum number of iterations exceeded.");
  512. return ans;
  513. }
  514. double NUMinvTukeyQ (double p, double cc, double df, double rr) {
  515. return qtukey (p, rr, cc, df, 0, 0);
  516. }
  517. double NUMtukeyQ (double q, double cc, double df, double rr) {
  518. return ptukey (q, rr, cc, df, 0, 0);
  519. }