summaryrefslogtreecommitdiff
path: root/libm/float/asinf.c
diff options
context:
space:
mode:
Diffstat (limited to 'libm/float/asinf.c')
-rw-r--r--libm/float/asinf.c186
1 files changed, 186 insertions, 0 deletions
diff --git a/libm/float/asinf.c b/libm/float/asinf.c
new file mode 100644
index 000000000..c96d75acb
--- /dev/null
+++ b/libm/float/asinf.c
@@ -0,0 +1,186 @@
+/* asinf.c
+ *
+ * Inverse circular sine
+ *
+ *
+ *
+ * SYNOPSIS:
+ *
+ * float x, y, asinf();
+ *
+ * y = asinf( x );
+ *
+ *
+ *
+ * DESCRIPTION:
+ *
+ * Returns radian angle between -pi/2 and +pi/2 whose sine is x.
+ *
+ * A polynomial of the form x + x**3 P(x**2)
+ * is used for |x| in the interval [0, 0.5]. If |x| > 0.5 it is
+ * transformed by the identity
+ *
+ * asin(x) = pi/2 - 2 asin( sqrt( (1-x)/2 ) ).
+ *
+ *
+ * ACCURACY:
+ *
+ * Relative error:
+ * arithmetic domain # trials peak rms
+ * IEEE -1, 1 100000 2.5e-7 5.0e-8
+ *
+ *
+ * ERROR MESSAGES:
+ *
+ * message condition value returned
+ * asinf domain |x| > 1 0.0
+ *
+ */
+ /* acosf()
+ *
+ * Inverse circular cosine
+ *
+ *
+ *
+ * SYNOPSIS:
+ *
+ * float x, y, acosf();
+ *
+ * y = acosf( x );
+ *
+ *
+ *
+ * DESCRIPTION:
+ *
+ * Returns radian angle between -pi/2 and +pi/2 whose cosine
+ * is x.
+ *
+ * Analytically, acos(x) = pi/2 - asin(x). However if |x| is
+ * near 1, there is cancellation error in subtracting asin(x)
+ * from pi/2. Hence if x < -0.5,
+ *
+ * acos(x) = pi - 2.0 * asin( sqrt((1+x)/2) );
+ *
+ * or if x > +0.5,
+ *
+ * acos(x) = 2.0 * asin( sqrt((1-x)/2) ).
+ *
+ *
+ * ACCURACY:
+ *
+ * Relative error:
+ * arithmetic domain # trials peak rms
+ * IEEE -1, 1 100000 1.4e-7 4.2e-8
+ *
+ *
+ * ERROR MESSAGES:
+ *
+ * message condition value returned
+ * acosf domain |x| > 1 0.0
+ */
+
+/* asin.c */
+
+/*
+Cephes Math Library Release 2.2: June, 1992
+Copyright 1984, 1987, 1992 by Stephen L. Moshier
+Direct inquiries to 30 Frost Street, Cambridge, MA 02140
+*/
+
+/* Single precision circular arcsine
+ * test interval: [-0.5, +0.5]
+ * trials: 10000
+ * peak relative error: 6.7e-8
+ * rms relative error: 2.5e-8
+ */
+#include <math.h>
+extern float PIF, PIO2F;
+
+float sqrtf( float );
+
+float asinf( float xx )
+{
+float a, x, z;
+int sign, flag;
+
+x = xx;
+
+if( x > 0 )
+ {
+ sign = 1;
+ a = x;
+ }
+else
+ {
+ sign = -1;
+ a = -x;
+ }
+
+if( a > 1.0 )
+ {
+ mtherr( "asinf", DOMAIN );
+ return( 0.0 );
+ }
+
+if( a < 1.0e-4 )
+ {
+ z = a;
+ goto done;
+ }
+
+if( a > 0.5 )
+ {
+ z = 0.5 * (1.0 - a);
+ x = sqrtf( z );
+ flag = 1;
+ }
+else
+ {
+ x = a;
+ z = x * x;
+ flag = 0;
+ }
+
+z =
+(((( 4.2163199048E-2 * z
+ + 2.4181311049E-2) * z
+ + 4.5470025998E-2) * z
+ + 7.4953002686E-2) * z
+ + 1.6666752422E-1) * z * x
+ + x;
+
+if( flag != 0 )
+ {
+ z = z + z;
+ z = PIO2F - z;
+ }
+done:
+if( sign < 0 )
+ z = -z;
+return( z );
+}
+
+
+
+
+float acosf( float x )
+{
+
+if( x < -1.0 )
+ goto domerr;
+
+if( x < -0.5)
+ return( PIF - 2.0 * asinf( sqrtf(0.5*(1.0+x)) ) );
+
+if( x > 1.0 )
+ {
+domerr: mtherr( "acosf", DOMAIN );
+ return( 0.0 );
+ }
+
+if( x > 0.5 )
+ return( 2.0 * asinf( sqrtf(0.5*(1.0-x) ) ) );
+
+return( PIO2F - asinf(x) );
+}
+