ellpj.c 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  1. /* ellpj.c
  2. *
  3. * Jacobian Elliptic Functions
  4. *
  5. *
  6. *
  7. * SYNOPSIS:
  8. *
  9. * double u, m, sn, cn, dn, phi;
  10. * int ellpj();
  11. *
  12. * ellpj( u, m, _&sn, _&cn, _&dn, _&phi );
  13. *
  14. *
  15. *
  16. * DESCRIPTION:
  17. *
  18. *
  19. * Evaluates the Jacobian elliptic functions sn(u|m), cn(u|m),
  20. * and dn(u|m) of parameter m between 0 and 1, and real
  21. * argument u.
  22. *
  23. * These functions are periodic, with quarter-period on the
  24. * real axis equal to the complete elliptic integral
  25. * ellpk(1.0-m).
  26. *
  27. * Relation to incomplete elliptic integral:
  28. * If u = ellik(phi,m), then sn(u|m) = sin(phi),
  29. * and cn(u|m) = cos(phi). Phi is called the amplitude of u.
  30. *
  31. * Computation is by means of the arithmetic-geometric mean
  32. * algorithm, except when m is within 1e-9 of 0 or 1. In the
  33. * latter case with m close to 1, the approximation applies
  34. * only for phi < pi/2.
  35. *
  36. * ACCURACY:
  37. *
  38. * Tested at random points with u between 0 and 10, m between
  39. * 0 and 1.
  40. *
  41. * Absolute error (* = relative error):
  42. * arithmetic function # trials peak rms
  43. * DEC sn 1800 4.5e-16 8.7e-17
  44. * IEEE phi 10000 9.2e-16* 1.4e-16*
  45. * IEEE sn 50000 4.1e-15 4.6e-16
  46. * IEEE cn 40000 3.6e-15 4.4e-16
  47. * IEEE dn 100000 3.9e-15 1.7e-16
  48. *
  49. * Larger errors occur for m near 1.
  50. * Peak error observed in consistency check using addition
  51. * theorem for sn(u+v) was 4e-16 (absolute). Also tested by
  52. * the above relation to the incomplete elliptic integral.
  53. * Accuracy deteriorates when u is large.
  54. *
  55. */
  56. /* ellpj.c */
  57. /*
  58. Cephes Math Library Release 2.8: June, 2000
  59. Copyright 1984, 1987, 2000, 2014 by Stephen L. Moshier
  60. */
  61. #include "mconf.h"
  62. #ifdef ANSIPROT
  63. extern double sqrt(double);
  64. extern double fabs(double);
  65. extern double sin(double);
  66. extern double cos(double);
  67. extern double asin(double);
  68. extern double tanh(double);
  69. extern double sinh(double);
  70. extern double cosh(double);
  71. extern double atan(double);
  72. extern double exp(double);
  73. #else
  74. double sqrt(), fabs(), sin(), cos(), asin(), tanh();
  75. double sinh(), cosh(), atan(), exp();
  76. #endif
  77. extern double PIO2, MACHEP;
  78. int ellpj(u, m, sn, cn, dn, ph) double u, m;
  79. double *sn, *cn, *dn, *ph;
  80. {
  81. double ai, b, phi, t, twon;
  82. double a[9], c[9];
  83. int i;
  84. /* Check for special cases */
  85. if (m < 0.0 || m > 1.0) {
  86. mtherr("ellpj", DOMAIN);
  87. *sn = 0.0;
  88. *cn = 0.0;
  89. *ph = 0.0;
  90. *dn = 0.0;
  91. return (-1);
  92. }
  93. if (m < 1.0e-9) {
  94. t = sin(u);
  95. b = cos(u);
  96. ai = 0.25 * m * (u - t * b);
  97. *sn = t - ai * b;
  98. *cn = b + ai * t;
  99. *ph = u - ai;
  100. *dn = 1.0 - 0.5 * m * t * t;
  101. return (0);
  102. }
  103. if (m >= 0.9999999999) {
  104. ai = 0.25 * (1.0 - m);
  105. b = cosh(u);
  106. t = tanh(u);
  107. phi = 1.0 / b;
  108. twon = b * sinh(u);
  109. *sn = t + ai * (twon - u) / (b * b);
  110. *ph = 2.0 * atan(exp(u)) - PIO2 + ai * (twon - u) / b;
  111. ai *= t * phi;
  112. *cn = phi - ai * (twon - u);
  113. *dn = phi + ai * (twon + u);
  114. return (0);
  115. }
  116. /* A. G. M. scale */
  117. a[0] = 1.0;
  118. b = sqrt(1.0 - m);
  119. c[0] = sqrt(m);
  120. twon = 1.0;
  121. i = 0;
  122. while (fabs(c[i] / a[i]) > MACHEP) {
  123. if (i > 7) {
  124. mtherr("ellpj", OVERFLOW);
  125. goto done;
  126. }
  127. ai = a[i];
  128. ++i;
  129. c[i] = (ai - b) / 2.0;
  130. t = sqrt(ai * b);
  131. a[i] = (ai + b) / 2.0;
  132. b = t;
  133. twon *= 2.0;
  134. }
  135. done:
  136. /* backward recurrence */
  137. phi = twon * a[i] * u;
  138. do {
  139. t = c[i] * sin(phi) / a[i];
  140. b = phi;
  141. phi = (asin(t) + phi) / 2.0;
  142. } while (--i);
  143. t = sin(phi);
  144. *sn = t;
  145. *cn = cos(phi);
  146. /* Thanks to Hartmut Henkel for reporting a bug here: */
  147. *dn = sqrt(1.0 - m * t * t);
  148. *ph = phi;
  149. return (0);
  150. }