as177.c 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194
  1. /*-Algorithm AS 177
  2. * Expected Normal Order Statistics (Exact and Approximate),
  3. * by J.P. Royston, 1982.
  4. * Applied Statistics, 31(2):161-165.
  5. *
  6. * Translation to C by James Darrell McCauley, mccauley@ecn.purdue.edu.
  7. *
  8. * The functions Cdhc_nscor1() and Cdhc_nscor2() calculate the expected values of
  9. * normal order statistics in exact or approximate form, respectively.
  10. *
  11. */
  12. #define NSTEP 721
  13. #define H 0.025
  14. #include <math.h>
  15. #include <stdio.h>
  16. #include "local_proto.h"
  17. /* Local function prototypes */
  18. static double Cdhc_alnfac(int j);
  19. static double Cdhc_correc(int i, int n);
  20. /* exact calculation of normal scores */
  21. void Cdhc_nscor1(double s[], int n, int n2, double work[], int *ifault)
  22. {
  23. double ani, c, c1, d, scor;
  24. int i, j;
  25. *ifault = 3;
  26. if (n2 != n / 2)
  27. return;
  28. *ifault = 1;
  29. if (n <= 1)
  30. return;
  31. *ifault = 0;
  32. if (n > 2000)
  33. *ifault = 2;
  34. /* calculate the natural log of factorial(n) */
  35. c1 = Cdhc_alnfac(n);
  36. d = c1 - log((double)n);
  37. /* accumulate ordinates for calculation of integral for rankits */
  38. for (i = 0; i < n2; ++i) {
  39. ani = (double)n - i - 1;
  40. c = c1 - d;
  41. for (scor = 0.0, j = 0; j < NSTEP; ++j)
  42. scor += work[0 * NSTEP + j] *
  43. exp(work[1 * NSTEP + j] + work[2 * NSTEP + j] * i
  44. + work[3 * NSTEP + j] * ani + c);
  45. s[i] = scor * H;
  46. d += log((double)(i + 1.0) / ani);
  47. }
  48. return;
  49. }
  50. void init(double work[])
  51. {
  52. double xstart = -9.0, pi2 = -0.918938533, xx;
  53. int i;
  54. xx = xstart;
  55. /* set up arrays for calculation of integral */
  56. for (i = 0; i < NSTEP; ++i) {
  57. work[0 * NSTEP + i] = xx;
  58. work[1 * NSTEP + i] = pi2 - xx * xx * 0.5;
  59. work[2 * NSTEP + i] = log(Cdhc_alnorm(xx, 1));
  60. work[3 * NSTEP + i] = log(Cdhc_alnorm(xx, 0));
  61. xx = xstart + H * (i + 1.0);
  62. }
  63. return;
  64. }
  65. /*-Algorithm AS 177.2 Appl. Statist. (1982) Vol.31, No.2
  66. * Natural logarithm of factorial for non-negative argument
  67. */
  68. static double Cdhc_alnfac(int j)
  69. {
  70. static double r[7] = { 0.0, 0.0, 0.69314718056, 1.79175946923,
  71. 3.17805383035, 4.78749174278, 6.57925121101
  72. };
  73. double w, z;
  74. if (j == 1)
  75. return (double)1.0;
  76. else if (j <= 7)
  77. return r[j];
  78. w = (double)j + 1;
  79. z = 1.0 / (w * w);
  80. return (w - 0.5) * log(w) - w + 0.918938522305 +
  81. (((4.0 - 3.0 * z) * z - 14.0) * z + 420.0) / (5040.0 * w);
  82. }
  83. /*-Algorithm AS 177.3 Appl. Statist. (1982) Vol.31, No.2
  84. * Approximation for Rankits
  85. */
  86. void Cdhc_nscor2(double s[], int n, int n2, int *ifault)
  87. {
  88. static double eps[4] = { 0.419885, 0.450536, 0.456936, 0.468488 };
  89. static double dl1[4] = { 0.112063, 0.121770, 0.239299, 0.215159 };
  90. static double dl2[4] = { 0.080122, 0.111348, -0.211867, -0.115049 };
  91. static double gam[4] = { 0.474798, 0.469051, 0.208597, 0.259784 };
  92. static double lam[4] = { 0.282765, 0.304856, 0.407708, 0.414093 };
  93. static double bb = -0.283833, d = -0.106136, b1 = 0.5641896;
  94. double e1, e2, l1;
  95. int i, k;
  96. *ifault = 3;
  97. if (n2 != n / 2)
  98. return;
  99. *ifault = 1;
  100. if (n <= 1)
  101. return;
  102. *ifault = 0;
  103. if (n > 2000)
  104. *ifault = 2;
  105. s[0] = b1;
  106. if (n == 2)
  107. return;
  108. /* calculate normal areas for 3 largest rankits */
  109. k = (n2 < 3) ? n2 : 3;
  110. for (i = 0; i < k; ++i) {
  111. e1 = (1.0 + i - eps[i]) / (n + gam[i]);
  112. e2 = pow(e1, lam[i]);
  113. s[i] = e1 + e2 * (dl1[i] + e2 * dl2[i]) / n - Cdhc_correc(1 + i, n);
  114. }
  115. if (n2 != k) {
  116. /* calculate normal areas for remaining rankits */
  117. for (i = 3; i < n2; ++i) {
  118. l1 = lam[3] + bb / (1.0 + i + d);
  119. e1 = (1.0 + i - eps[3]) / (n + gam[3]);
  120. e2 = pow(e1, l1);
  121. s[i] = e1 + e2 * (dl1[3] + e2 * dl2[3]) / n - Cdhc_correc(1 + i, n);
  122. }
  123. }
  124. /* convert normal tail areas to normal deviates */
  125. for (i = 0; i < n2; ++i)
  126. s[i] = -ppnd16(s[i]);
  127. return;
  128. }
  129. /*-Algorithm AS 177.4 Appl. Statist. (1982) Vol.31, No.2
  130. * Calculates Cdhc_correction for tail area of noraml distribution
  131. * corresponding to ith largest rankit in sample size n.
  132. */
  133. static double Cdhc_correc(int i, int n)
  134. {
  135. static double c1[7] = { 9.5, 28.7, 1.9, 0.0, -7.0, -6.2, -1.6 };
  136. static double c2[7] = { -6.195e3, -9.569e3, -6.728e3, -17.614e3,
  137. -8.278e3, -3.570e3, 1.075e3
  138. };
  139. static double c3[7] = { 9.338e4, 1.7516e5, 4.1040e5, 2.157e6,
  140. 2.376e6, 2.065e6, 2.065e6
  141. };
  142. static double mic = 1.0e-6, c14 = 1.9e-5;
  143. double an;
  144. if (i * n == 4)
  145. return c14;
  146. if (i < 1 || i > 7)
  147. return 0.0;
  148. else if (i != 4 && n > 20)
  149. return 0.0;
  150. else if (i == 4 && n > 40)
  151. return 0.0;
  152. /* else */
  153. an = 1.0 / (double)(n * n);
  154. return (c1[i - 1] + an * (c2[i - 1] + an * c3[i - 1])) * mic;
  155. }