ellie.c 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  1. /* ellie.c
  2. *
  3. * Incomplete elliptic integral of the second kind
  4. *
  5. *
  6. *
  7. * SYNOPSIS:
  8. *
  9. * double phi, m, y, ellie();
  10. *
  11. * y = ellie( phi, m );
  12. *
  13. *
  14. *
  15. * DESCRIPTION:
  16. *
  17. * Approximates the integral
  18. *
  19. *
  20. * phi
  21. * -
  22. * | |
  23. * | 2
  24. * E(phi_\m) = | sqrt( 1 - m sin t ) dt
  25. * |
  26. * | |
  27. * -
  28. * 0
  29. *
  30. * of amplitude phi and modulus m, using the arithmetic -
  31. * geometric mean algorithm.
  32. *
  33. *
  34. *
  35. * ACCURACY:
  36. *
  37. * Tested at random arguments with phi in [-10, 10] and m in
  38. * [0, 1].
  39. * Relative error:
  40. * arithmetic domain # trials peak rms
  41. * DEC 0,2 2000 1.9e-16 3.4e-17
  42. * IEEE -10,10 150000 3.3e-15 1.4e-16
  43. *
  44. *
  45. */
  46. /*
  47. Cephes Math Library Release 2.8: June, 2000
  48. Copyright 1984, 1987, 1993, 2000 by Stephen L. Moshier
  49. */
  50. /* Incomplete elliptic integral of second kind */
  51. #include "mconf.h"
  52. extern double PI, PIO2, MACHEP;
  53. #ifdef ANSIPROT
  54. extern double sqrt(double);
  55. extern double fabs(double);
  56. extern double log(double);
  57. extern double sin(double x);
  58. extern double tan(double x);
  59. extern double atan(double);
  60. extern double floor(double);
  61. extern double ellpe(double);
  62. extern double ellpk(double);
  63. double ellie(double, double);
  64. #else
  65. double sqrt(), fabs(), log(), sin(), tan(), atan(), floor();
  66. double ellpe(), ellpk(), ellie();
  67. #endif
  68. double ellie(phi, m) double phi, m;
  69. {
  70. double a, b, c, e, temp;
  71. double lphi, t, E;
  72. int d, mod, npio2, sign;
  73. if (m == 0.0)
  74. return (phi);
  75. lphi = phi;
  76. npio2 = floor(lphi / PIO2);
  77. if (npio2 & 1)
  78. npio2 += 1;
  79. lphi = lphi - npio2 * PIO2;
  80. if (lphi < 0.0) {
  81. lphi = -lphi;
  82. sign = -1;
  83. } else {
  84. sign = 1;
  85. }
  86. a = 1.0 - m;
  87. E = ellpe(a);
  88. if (a == 0.0) {
  89. temp = sin(lphi);
  90. goto done;
  91. }
  92. t = tan(lphi);
  93. b = sqrt(a);
  94. /* Thanks to Brian Fitzgerald <fitzgb@mml0.meche.rpi.edu>
  95. for pointing out an instability near odd multiples of pi/2. */
  96. if (fabs(t) > 10.0) {
  97. /* Transform the amplitude */
  98. e = 1.0 / (b * t);
  99. /* ... but avoid multiple recursions. */
  100. if (fabs(e) < 10.0) {
  101. e = atan(e);
  102. temp = E + m * sin(lphi) * sin(e) - ellie(e, m);
  103. goto done;
  104. }
  105. }
  106. c = sqrt(m);
  107. a = 1.0;
  108. d = 1;
  109. e = 0.0;
  110. mod = 0;
  111. while (fabs(c / a) > MACHEP) {
  112. temp = b / a;
  113. lphi = lphi + atan(t * temp) + mod * PI;
  114. mod = (lphi + PIO2) / PI;
  115. t = t * (1.0 + temp) / (1.0 - temp * t * t);
  116. c = (a - b) / 2.0;
  117. temp = sqrt(a * b);
  118. a = (a + b) / 2.0;
  119. b = temp;
  120. d += d;
  121. e += c * sin(lphi);
  122. }
  123. temp = E / ellpk(1.0 - m);
  124. temp *= (atan(t) + mod * PI) / (d * a);
  125. temp += e;
  126. done:
  127. if (sign < 0)
  128. temp = -temp;
  129. temp += npio2 * E;
  130. return (temp);
  131. }