summaryrefslogtreecommitdiff
path: root/libm/ldouble/sqrtl.c
diff options
context:
space:
mode:
Diffstat (limited to 'libm/ldouble/sqrtl.c')
-rw-r--r--libm/ldouble/sqrtl.c172
1 files changed, 172 insertions, 0 deletions
diff --git a/libm/ldouble/sqrtl.c b/libm/ldouble/sqrtl.c
new file mode 100644
index 000000000..a3b17175f
--- /dev/null
+++ b/libm/ldouble/sqrtl.c
@@ -0,0 +1,172 @@
+/* sqrtl.c
+ *
+ * Square root, long double precision
+ *
+ *
+ *
+ * SYNOPSIS:
+ *
+ * long double x, y, sqrtl();
+ *
+ * y = sqrtl( x );
+ *
+ *
+ *
+ * DESCRIPTION:
+ *
+ * Returns the square root of x.
+ *
+ * Range reduction involves isolating the power of two of the
+ * argument and using a polynomial approximation to obtain
+ * a rough value for the square root. Then Heron's iteration
+ * is used three times to converge to an accurate value.
+ *
+ * Note, some arithmetic coprocessors such as the 8087 and
+ * 68881 produce correctly rounded square roots, which this
+ * routine will not.
+ *
+ * ACCURACY:
+ *
+ *
+ * Relative error:
+ * arithmetic domain # trials peak rms
+ * IEEE 0,10 30000 8.1e-20 3.1e-20
+ *
+ *
+ * ERROR MESSAGES:
+ *
+ * message condition value returned
+ * sqrt domain x < 0 0.0
+ *
+ */
+
+/*
+Cephes Math Library Release 2.2: December, 1990
+Copyright 1984, 1990 by Stephen L. Moshier
+Direct inquiries to 30 Frost Street, Cambridge, MA 02140
+*/
+
+
+#include <math.h>
+
+#define SQRT2 1.4142135623730950488017E0L
+#ifdef ANSIPROT
+extern long double frexpl ( long double, int * );
+extern long double ldexpl ( long double, int );
+#else
+long double frexpl(), ldexpl();
+#endif
+
+long double sqrtl(x)
+long double x;
+{
+int e;
+long double z, w;
+#ifndef UNK
+short *q;
+#endif
+
+if( x <= 0.0 )
+ {
+ if( x < 0.0 )
+ mtherr( "sqrtl", DOMAIN );
+ return( 0.0 );
+ }
+w = x;
+/* separate exponent and significand */
+#ifdef UNK
+z = frexpl( x, &e );
+#endif
+
+/* Note, frexp and ldexp are used in order to
+ * handle denormal numbers properly.
+ */
+#ifdef IBMPC
+z = frexpl( x, &e );
+q = (short *)&x; /* point to the exponent word */
+q += 4;
+/*
+e = ((*q >> 4) & 0x0fff) - 0x3fe;
+*q &= 0x000f;
+*q |= 0x3fe0;
+z = x;
+*/
+#endif
+#ifdef MIEEE
+z = frexpl( x, &e );
+q = (short *)&x;
+/*
+e = ((*q >> 4) & 0x0fff) - 0x3fe;
+*q &= 0x000f;
+*q |= 0x3fe0;
+z = x;
+*/
+#endif
+
+/* approximate square root of number between 0.5 and 1
+ * relative error of linear approximation = 7.47e-3
+ */
+/*
+x = 0.4173075996388649989089L + 0.59016206709064458299663L * z;
+*/
+
+/* quadratic approximation, relative error 6.45e-4 */
+x = ( -0.20440583154734771959904L * z
+ + 0.89019407351052789754347L) * z
+ + 0.31356706742295303132394L;
+
+/* adjust for odd powers of 2 */
+if( (e & 1) != 0 )
+ x *= SQRT2;
+
+/* re-insert exponent */
+#ifdef UNK
+x = ldexpl( x, (e >> 1) );
+#endif
+#ifdef IBMPC
+x = ldexpl( x, (e >> 1) );
+/*
+*q += ((e >>1) & 0x7ff) << 4;
+*q &= 077777;
+*/
+#endif
+#ifdef MIEEE
+x = ldexpl( x, (e >> 1) );
+/*
+*q += ((e >>1) & 0x7ff) << 4;
+*q &= 077777;
+*/
+#endif
+
+/* Newton iterations: */
+#ifdef UNK
+x += w/x;
+x = ldexpl( x, -1 ); /* divide by 2 */
+x += w/x;
+x = ldexpl( x, -1 );
+x += w/x;
+x = ldexpl( x, -1 );
+#endif
+
+/* Note, assume the square root cannot be denormal,
+ * so it is safe to use integer exponent operations here.
+ */
+#ifdef IBMPC
+x += w/x;
+*q -= 1;
+x += w/x;
+*q -= 1;
+x += w/x;
+*q -= 1;
+#endif
+#ifdef MIEEE
+x += w/x;
+*q -= 1;
+x += w/x;
+*q -= 1;
+x += w/x;
+*q -= 1;
+#endif
+
+return(x);
+}