ellpjl.c 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  1. /* ellpjl.c
  2. *
  3. * Jacobian Elliptic Functions
  4. *
  5. *
  6. *
  7. * SYNOPSIS:
  8. *
  9. * long double u, m, sn, cn, dn, phi;
  10. * int ellpjl();
  11. *
  12. * ellpjl( 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-12 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. * IEEE sn 10000 1.7e-18 2.3e-19
  44. * IEEE cn 20000 1.6e-18 2.2e-19
  45. * IEEE dn 10000 4.7e-15 2.7e-17
  46. * IEEE phi 10000 4.0e-19* 6.6e-20*
  47. *
  48. * Accuracy deteriorates when u is large.
  49. *
  50. */
  51. /*
  52. Cephes Math Library Release 2.3: November, 1995
  53. Copyright 1984, 1987, 1995 by Stephen L. Moshier
  54. */
  55. #include <math.h>
  56. #ifdef ANSIPROT
  57. extern long double sqrtl ( long double );
  58. extern long double fabsl ( long double );
  59. extern long double sinl ( long double );
  60. extern long double cosl ( long double );
  61. extern long double asinl ( long double );
  62. extern long double tanhl ( long double );
  63. extern long double sinhl ( long double );
  64. extern long double coshl ( long double );
  65. extern long double atanl ( long double );
  66. extern long double expl ( long double );
  67. #else
  68. long double sqrtl(), fabsl(), sinl(), cosl(), asinl(), tanhl();
  69. long double sinhl(), coshl(), atanl(), expl();
  70. #endif
  71. extern long double PIO2L, MACHEPL;
  72. int ellpjl( u, m, sn, cn, dn, ph )
  73. long double u, m;
  74. long double *sn, *cn, *dn, *ph;
  75. {
  76. long double ai, b, phi, t, twon;
  77. long double a[9], c[9];
  78. int i;
  79. /* Check for special cases */
  80. if( m < 0.0L || m > 1.0L )
  81. {
  82. mtherr( "ellpjl", DOMAIN );
  83. *sn = 0.0L;
  84. *cn = 0.0L;
  85. *ph = 0.0L;
  86. *dn = 0.0L;
  87. return(-1);
  88. }
  89. if( m < 1.0e-12L )
  90. {
  91. t = sinl(u);
  92. b = cosl(u);
  93. ai = 0.25L * m * (u - t*b);
  94. *sn = t - ai*b;
  95. *cn = b + ai*t;
  96. *ph = u - ai;
  97. *dn = 1.0L - 0.5L*m*t*t;
  98. return(0);
  99. }
  100. if( m >= 0.999999999999L )
  101. {
  102. ai = 0.25L * (1.0L-m);
  103. b = coshl(u);
  104. t = tanhl(u);
  105. phi = 1.0L/b;
  106. twon = b * sinhl(u);
  107. *sn = t + ai * (twon - u)/(b*b);
  108. *ph = 2.0L*atanl(expl(u)) - PIO2L + ai*(twon - u)/b;
  109. ai *= t * phi;
  110. *cn = phi - ai * (twon - u);
  111. *dn = phi + ai * (twon + u);
  112. return(0);
  113. }
  114. /* A. G. M. scale */
  115. a[0] = 1.0L;
  116. b = sqrtl(1.0L - m);
  117. c[0] = sqrtl(m);
  118. twon = 1.0L;
  119. i = 0;
  120. while( fabsl(c[i]/a[i]) > MACHEPL )
  121. {
  122. if( i > 7 )
  123. {
  124. mtherr( "ellpjl", OVERFLOW );
  125. goto done;
  126. }
  127. ai = a[i];
  128. ++i;
  129. c[i] = 0.5L * ( ai - b );
  130. t = sqrtl( ai * b );
  131. a[i] = 0.5L * ( ai + b );
  132. b = t;
  133. twon *= 2.0L;
  134. }
  135. done:
  136. /* backward recurrence */
  137. phi = twon * a[i] * u;
  138. do
  139. {
  140. t = c[i] * sinl(phi) / a[i];
  141. b = phi;
  142. phi = 0.5L * (asinl(t) + phi);
  143. }
  144. while( --i );
  145. *sn = sinl(phi);
  146. t = cosl(phi);
  147. *cn = t;
  148. *dn = t/cosl(phi-b);
  149. *ph = phi;
  150. return(0);
  151. }