ellpj.c 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  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 10000 1.3e-12 1.8e-14
  48. *
  49. * Peak error observed in consistency check using addition
  50. * theorem for sn(u+v) was 4e-16 (absolute). Also tested by
  51. * the above relation to the incomplete elliptic integral.
  52. * Accuracy deteriorates when u is large.
  53. *
  54. */
  55. /* ellpj.c */
  56. /*
  57. Cephes Math Library Release 2.8: June, 2000
  58. Copyright 1984, 1987, 2000 by Stephen L. Moshier
  59. */
  60. #include <math.h>
  61. #ifdef ANSIPROT
  62. extern double sqrt ( double );
  63. extern double fabs ( double );
  64. extern double sin ( double );
  65. extern double cos ( double );
  66. extern double asin ( double );
  67. extern double tanh ( double );
  68. extern double sinh ( double );
  69. extern double cosh ( double );
  70. extern double atan ( double );
  71. extern double exp ( double );
  72. #else
  73. double sqrt(), fabs(), sin(), cos(), asin(), tanh();
  74. double sinh(), cosh(), atan(), exp();
  75. #endif
  76. extern double PIO2, MACHEP;
  77. int ellpj( u, m, sn, cn, dn, ph )
  78. 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. {
  87. mtherr( "ellpj", DOMAIN );
  88. *sn = 0.0;
  89. *cn = 0.0;
  90. *ph = 0.0;
  91. *dn = 0.0;
  92. return(-1);
  93. }
  94. if( m < 1.0e-9 )
  95. {
  96. t = sin(u);
  97. b = cos(u);
  98. ai = 0.25 * m * (u - t*b);
  99. *sn = t - ai*b;
  100. *cn = b + ai*t;
  101. *ph = u - ai;
  102. *dn = 1.0 - 0.5*m*t*t;
  103. return(0);
  104. }
  105. if( m >= 0.9999999999 )
  106. {
  107. ai = 0.25 * (1.0-m);
  108. b = cosh(u);
  109. t = tanh(u);
  110. phi = 1.0/b;
  111. twon = b * sinh(u);
  112. *sn = t + ai * (twon - u)/(b*b);
  113. *ph = 2.0*atan(exp(u)) - PIO2 + ai*(twon - u)/b;
  114. ai *= t * phi;
  115. *cn = phi - ai * (twon - u);
  116. *dn = phi + ai * (twon + u);
  117. return(0);
  118. }
  119. /* A. G. M. scale */
  120. a[0] = 1.0;
  121. b = sqrt(1.0 - m);
  122. c[0] = sqrt(m);
  123. twon = 1.0;
  124. i = 0;
  125. while( fabs(c[i]/a[i]) > MACHEP )
  126. {
  127. if( i > 7 )
  128. {
  129. mtherr( "ellpj", OVERFLOW );
  130. goto done;
  131. }
  132. ai = a[i];
  133. ++i;
  134. c[i] = ( ai - b )/2.0;
  135. t = sqrt( ai * b );
  136. a[i] = ( ai + b )/2.0;
  137. b = t;
  138. twon *= 2.0;
  139. }
  140. done:
  141. /* backward recurrence */
  142. phi = twon * a[i] * u;
  143. do
  144. {
  145. t = c[i] * sin(phi) / a[i];
  146. b = phi;
  147. phi = (asin(t) + phi)/2.0;
  148. }
  149. while( --i );
  150. *sn = sin(phi);
  151. t = cos(phi);
  152. *cn = t;
  153. *dn = t/cos(phi-b);
  154. *ph = phi;
  155. return(0);
  156. }