ellpjf.c 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  1. /* ellpjf.c
  2. *
  3. * Jacobian Elliptic Functions
  4. *
  5. *
  6. *
  7. * SYNOPSIS:
  8. *
  9. * float 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. * IEEE sn 10000 1.7e-6 2.2e-7
  44. * IEEE cn 10000 1.6e-6 2.2e-7
  45. * IEEE dn 10000 1.4e-3 1.9e-5
  46. * IEEE phi 10000 3.9e-7* 6.7e-8*
  47. *
  48. * Peak error observed in consistency check using addition
  49. * theorem for sn(u+v) was 4e-16 (absolute). Also tested by
  50. * the above relation to the incomplete elliptic integral.
  51. * Accuracy deteriorates when u is large.
  52. *
  53. */
  54. /* ellpj.c */
  55. /*
  56. Cephes Math Library Release 2.2: July, 1992
  57. Copyright 1984, 1987, 1992 by Stephen L. Moshier
  58. Direct inquiries to 30 Frost Street, Cambridge, MA 02140
  59. */
  60. #include <math.h>
  61. extern float PIO2F, MACHEPF;
  62. #define fabsf(x) ( (x) < 0 ? -(x) : (x) )
  63. #ifdef ANSIC
  64. float sqrtf(float), sinf(float), cosf(float), asinf(float), tanhf(float);
  65. float sinhf(float), coshf(float), atanf(float), expf(float);
  66. #else
  67. float sqrtf(), sinf(), cosf(), asinf(), tanhf();
  68. float sinhf(), coshf(), atanf(), expf();
  69. #endif
  70. int ellpjf( float uu, float mm,
  71. float *sn, float *cn, float *dn, float *ph )
  72. {
  73. float u, m, ai, b, phi, t, twon;
  74. float a[10], c[10];
  75. int i;
  76. u = uu;
  77. m = mm;
  78. /* Check for special cases */
  79. if( m < 0.0 || m > 1.0 )
  80. {
  81. mtherr( "ellpjf", DOMAIN );
  82. return(-1);
  83. }
  84. if( m < 1.0e-5 )
  85. {
  86. t = sinf(u);
  87. b = cosf(u);
  88. ai = 0.25 * m * (u - t*b);
  89. *sn = t - ai*b;
  90. *cn = b + ai*t;
  91. *ph = u - ai;
  92. *dn = 1.0 - 0.5*m*t*t;
  93. return(0);
  94. }
  95. if( m >= 0.99999 )
  96. {
  97. ai = 0.25 * (1.0-m);
  98. b = coshf(u);
  99. t = tanhf(u);
  100. phi = 1.0/b;
  101. twon = b * sinhf(u);
  102. *sn = t + ai * (twon - u)/(b*b);
  103. *ph = 2.0*atanf(expf(u)) - PIO2F + ai*(twon - u)/b;
  104. ai *= t * phi;
  105. *cn = phi - ai * (twon - u);
  106. *dn = phi + ai * (twon + u);
  107. return(0);
  108. }
  109. /* A. G. M. scale */
  110. a[0] = 1.0;
  111. b = sqrtf(1.0 - m);
  112. c[0] = sqrtf(m);
  113. twon = 1.0;
  114. i = 0;
  115. while( fabsf( (c[i]/a[i]) ) > MACHEPF )
  116. {
  117. if( i > 8 )
  118. {
  119. /* mtherr( "ellpjf", OVERFLOW );*/
  120. break;
  121. }
  122. ai = a[i];
  123. ++i;
  124. c[i] = 0.5 * ( ai - b );
  125. t = sqrtf( ai * b );
  126. a[i] = 0.5 * ( ai + b );
  127. b = t;
  128. twon += twon;
  129. }
  130. /* backward recurrence */
  131. phi = twon * a[i] * u;
  132. do
  133. {
  134. t = c[i] * sinf(phi) / a[i];
  135. b = phi;
  136. phi = 0.5 * (asinf(t) + phi);
  137. }
  138. while( --i );
  139. *sn = sinf(phi);
  140. t = cosf(phi);
  141. *cn = t;
  142. *dn = t/cosf(phi-b);
  143. *ph = phi;
  144. return(0);
  145. }