/* * R : A Computer Language for Statistical Data Analysis * Copyright (C) 2000-2016 The R Core Team * Copyright (C) 2003 The R Foundation * based on AS 89 (C) 1975 Royal Statistical Society * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, a copy is available at * https://www.R-project.org/Licenses/ * */ #include #include /* Was double precision function prho(n, is, ifault) Changed to subroutine by KH to allow for .Fortran interfacing. Also, change `prho' argument in the code to `pv'. And, fix a bug. From R ver. 1.1.x [March, 2000] by MM: - Translate Fortran to C - use pnorm() instead of less precise alnorm(). - new argument lower_tail --> potentially increased precision in extreme cases. */ void prho(int n, double is, double *pv, int ifault, int lower_tail) { /* Algorithm AS 89 Appl. Statist. (1975) Vol.24, No. 3, P377. To evaluate the probability Pr[ S >= is ] {or Pr [ S < is] if(lower_tail) }, where S = (n^3 - n) * (1-R)/6, is = (n^3 - n) * (1-r)/6, R,r = Spearman's rho (r.v. and observed), and n >= 2 */ /* Edgeworth coefficients : */ const double c1 = .2274, c2 = .2531, c3 = .1745, c4 = .0758, c5 = .1033, c6 = .3932, c7 = .0879, c8 = .0151, c9 = .0072, c10= .0831, c11= .0131, c12= 4.6e-4; /* Local variables */ double b, u, x, y, n3;/*, js */ #define n_small 9 /* originally: n_small = 6 (speed!); * even n_small = 10 (and n = 10) needs quite a bit longer than the approx! * larger than 12 ==> integer overflow in nfac and (probably) ifr */ int l[n_small]; int nfac, i, m, mt, ifr, ise, n1; /* Test admissibility of arguments and initialize */ *pv = lower_tail ? 0. : 1.; if (n <= 1) { ifault = 1; return; } ifault = 0; if (is <= 0.) return;/* with p = 1 */ n3 = (double)n; n3 *= (n3 * n3 - 1.) / 3.;/* = (n^3 - n)/3 */ if (is > n3) { /* larger than maximal value */ *pv = 1 - *pv; return; } /* NOT rounding to even anymore: with ties, S, may even be non-integer! * js = is; * if(fmod(js, 2.) != 0.) ++js; */ if (n <= n_small) { /* 2 <= n <= n_small : * Exact evaluation of probability */ nfac = 1.; for (i = 1; i <= n; ++i) { nfac *= i; l[i - 1] = i; } /* KH mod next line: was `!=' in the code but `.eq.' in the paper */ if (is == n3) { ifr = 1; } else { ifr = 0; for (m = 0; m < nfac; ++m) { ise = 0; for (i = 0; i < n; ++i) { n1 = i + 1 - l[i]; ise += n1 * n1; } if (is <= ise) ++ifr; n1 = n; do { mt = l[0]; for (i = 1; i < n1; ++i) l[i - 1] = l[i]; --n1; l[n1] = mt; } while (mt == n1+1 && n1 > 1); } } *pv = (lower_tail ? nfac-ifr : ifr) / (double) nfac; } /* exact for n <= n_small */ else { /* n >= 7 : Evaluation by Edgeworth series expansion */ y = (double) n; b = 1 / y; x = (6. * (is - 1) * b / (y * y - 1) - 1) * sqrt(y - 1); /* = rho * sqrt(n-1) == rho / sqrt(var(rho)) ~ (0,1) */ y = x * x; u = x * b * (c1 + b * (c2 + c3 * b) + y * (-c4 + b * (c5 + c6 * b) - y * b * (c7 + c8 * b - y * (c9 - c10 * b + y * b * (c11 - c12 * y)) ))); y = u / exp(y / 2.); *pv = (lower_tail ? -y : y) + pnorm(x, 0., 1., lower_tail, /*log_p = */FALSE); /* above was call to alnorm() [algorithm AS 66] */ if (*pv < 0) *pv = 0.; if (*pv > 1) *pv = 1.; } return; } /* prho */ #include SEXP pRho(SEXP q, SEXP sn, SEXP lower) { double s = asReal(q), p; int n = asInteger(sn), ltail = asInteger(lower), ifault = 0; prho(n, s, &p, ifault, ltail); return ScalarReal(p); }