summaryrefslogtreecommitdiff
path: root/libm/float/ellpjf.c
diff options
context:
space:
mode:
Diffstat (limited to 'libm/float/ellpjf.c')
-rw-r--r--libm/float/ellpjf.c161
1 files changed, 161 insertions, 0 deletions
diff --git a/libm/float/ellpjf.c b/libm/float/ellpjf.c
new file mode 100644
index 000000000..552f5ffe4
--- /dev/null
+++ b/libm/float/ellpjf.c
@@ -0,0 +1,161 @@
+/* ellpjf.c
+ *
+ * Jacobian Elliptic Functions
+ *
+ *
+ *
+ * SYNOPSIS:
+ *
+ * float u, m, sn, cn, dn, phi;
+ * int ellpj();
+ *
+ * ellpj( u, m, _&sn, _&cn, _&dn, _&phi );
+ *
+ *
+ *
+ * DESCRIPTION:
+ *
+ *
+ * Evaluates the Jacobian elliptic functions sn(u|m), cn(u|m),
+ * and dn(u|m) of parameter m between 0 and 1, and real
+ * argument u.
+ *
+ * These functions are periodic, with quarter-period on the
+ * real axis equal to the complete elliptic integral
+ * ellpk(1.0-m).
+ *
+ * Relation to incomplete elliptic integral:
+ * If u = ellik(phi,m), then sn(u|m) = sin(phi),
+ * and cn(u|m) = cos(phi). Phi is called the amplitude of u.
+ *
+ * Computation is by means of the arithmetic-geometric mean
+ * algorithm, except when m is within 1e-9 of 0 or 1. In the
+ * latter case with m close to 1, the approximation applies
+ * only for phi < pi/2.
+ *
+ * ACCURACY:
+ *
+ * Tested at random points with u between 0 and 10, m between
+ * 0 and 1.
+ *
+ * Absolute error (* = relative error):
+ * arithmetic function # trials peak rms
+ * IEEE sn 10000 1.7e-6 2.2e-7
+ * IEEE cn 10000 1.6e-6 2.2e-7
+ * IEEE dn 10000 1.4e-3 1.9e-5
+ * IEEE phi 10000 3.9e-7* 6.7e-8*
+ *
+ * Peak error observed in consistency check using addition
+ * theorem for sn(u+v) was 4e-16 (absolute). Also tested by
+ * the above relation to the incomplete elliptic integral.
+ * Accuracy deteriorates when u is large.
+ *
+ */
+
+/* ellpj.c */
+
+
+/*
+Cephes Math Library Release 2.2: July, 1992
+Copyright 1984, 1987, 1992 by Stephen L. Moshier
+Direct inquiries to 30 Frost Street, Cambridge, MA 02140
+*/
+
+#include <math.h>
+extern float PIO2F, MACHEPF;
+
+#define fabsf(x) ( (x) < 0 ? -(x) : (x) )
+
+#ifdef ANSIC
+float sqrtf(float), sinf(float), cosf(float), asinf(float), tanhf(float);
+float sinhf(float), coshf(float), atanf(float), expf(float);
+#else
+float sqrtf(), sinf(), cosf(), asinf(), tanhf();
+float sinhf(), coshf(), atanf(), expf();
+#endif
+
+int ellpjf( float uu, float mm,
+ float *sn, float *cn, float *dn, float *ph )
+{
+float u, m, ai, b, phi, t, twon;
+float a[10], c[10];
+int i;
+
+u = uu;
+m = mm;
+/* Check for special cases */
+
+if( m < 0.0 || m > 1.0 )
+ {
+ mtherr( "ellpjf", DOMAIN );
+ return(-1);
+ }
+if( m < 1.0e-5 )
+ {
+ t = sinf(u);
+ b = cosf(u);
+ ai = 0.25 * m * (u - t*b);
+ *sn = t - ai*b;
+ *cn = b + ai*t;
+ *ph = u - ai;
+ *dn = 1.0 - 0.5*m*t*t;
+ return(0);
+ }
+
+if( m >= 0.99999 )
+ {
+ ai = 0.25 * (1.0-m);
+ b = coshf(u);
+ t = tanhf(u);
+ phi = 1.0/b;
+ twon = b * sinhf(u);
+ *sn = t + ai * (twon - u)/(b*b);
+ *ph = 2.0*atanf(expf(u)) - PIO2F + ai*(twon - u)/b;
+ ai *= t * phi;
+ *cn = phi - ai * (twon - u);
+ *dn = phi + ai * (twon + u);
+ return(0);
+ }
+
+
+/* A. G. M. scale */
+a[0] = 1.0;
+b = sqrtf(1.0 - m);
+c[0] = sqrtf(m);
+twon = 1.0;
+i = 0;
+
+while( fabsf( (c[i]/a[i]) ) > MACHEPF )
+ {
+ if( i > 8 )
+ {
+/* mtherr( "ellpjf", OVERFLOW );*/
+ break;
+ }
+ ai = a[i];
+ ++i;
+ c[i] = 0.5 * ( ai - b );
+ t = sqrtf( ai * b );
+ a[i] = 0.5 * ( ai + b );
+ b = t;
+ twon += twon;
+ }
+
+
+/* backward recurrence */
+phi = twon * a[i] * u;
+do
+ {
+ t = c[i] * sinf(phi) / a[i];
+ b = phi;
+ phi = 0.5 * (asinf(t) + phi);
+ }
+while( --i );
+
+*sn = sinf(phi);
+t = cosf(phi);
+*cn = t;
+*dn = t/cosf(phi-b);
+*ph = phi;
+return(0);
+}