math: use the rounding idiom consistently
[musl] / src / math / asinl.c
index ddd807e..347c535 100644 (file)
@@ -23,56 +23,49 @@ long double asinl(long double x)
 }
 #elif (LDBL_MANT_DIG == 64 || LDBL_MANT_DIG == 113) && LDBL_MAX_EXP == 16384
 #include "__invtrigl.h"
-static const long double huge = 1.000e+300;
+#if LDBL_MANT_DIG == 64
+#define CLOSETO1(u) (u.i.m>>56 >= 0xf7)
+#define CLEARBOTTOM(u) (u.i.m &= -1ULL << 32)
+#elif LDBL_MANT_DIG == 113
+#define CLOSETO1(u) (u.i.top >= 0xee00)
+#define CLEARBOTTOM(u) (u.i.lo = 0)
+#endif
 
 long double asinl(long double x)
 {
-       union IEEEl2bits u;
-       long double t=0.0,w,p,q,c,r,s;
-       int16_t expsign, expt;
+       union ldshape u = {x};
+       long double z, r, s;
+       uint16_t e = u.i.se & 0x7fff;
+       int sign = u.i.se >> 15;
 
-       u.e = x;
-       expsign = u.xbits.expsign;
-       expt = expsign & 0x7fff;
-       if (expt >= BIAS) {          /* |x|>= 1 */
-               if (expt == BIAS &&
-                   ((u.bits.manh&~LDBL_NBIT)|u.bits.manl) == 0)
-                       /* asin(1)=+-pi/2 with inexact */
-                       return x*pio2_hi + x*pio2_lo;
-               return (x-x)/(x-x);  /* asin(|x|>1) is NaN */
-       } else if (expt < BIAS-1) {  /* |x|<0.5 */
-               if (expt < ASIN_LINEAR) {  /* if |x| is small, asinl(x)=x */
+       if (e >= 0x3fff) {   /* |x| >= 1 or nan */
+               /* asin(+-1)=+-pi/2 with inexact */
+               if (x == 1 || x == -1)
+                       return x*pio2_hi + 0x1p-120f;
+               return 0/(x-x);
+       }
+       if (e < 0x3fff - 1) {  /* |x| < 0.5 */
+               if (e < 0x3fff - (LDBL_MANT_DIG+1)/2) {
                        /* return x with inexact if x!=0 */
-                       if (huge+x > 1.0)
-                               return x;
+                       FORCE_EVAL(x + 0x1p120f);
+                       return x;
                }
-               t = x*x;
-               p = P(t);
-               q = Q(t);
-               w = p/q;
-               return x + x*w;
+               return x + x*__invtrigl_R(x*x);
        }
        /* 1 > |x| >= 0.5 */
-       w = 1.0 - fabsl(x);
-       t = w*0.5;
-       p = P(t);
-       q = Q(t);
-       s = sqrtl(t);
-       if (u.bits.manh >= THRESH) { /* if |x| is close to 1 */
-               w = p/q;
-               t = pio2_hi-(2.0*(s+s*w)-pio2_lo);
+       z = (1.0 - fabsl(x))*0.5;
+       s = sqrtl(z);
+       r = __invtrigl_R(z);
+       if (CLOSETO1(u)) {
+               x = pio2_hi - (2*(s+s*r)-pio2_lo);
        } else {
-               u.e = s;
-               u.bits.manl = 0;
-               w = u.e;
-               c = (t-w*w)/(s+w);
-               r = p/q;
-               p = 2.0*s*r-(pio2_lo-2.0*c);
-               q = pio4_hi-2.0*w;
-               t = pio4_hi-(p-q);
+               long double f, c;
+               u.f = s;
+               CLEARBOTTOM(u);
+               f = u.f;
+               c = (z - f*f)/(s + f);
+               x = 0.5*pio2_hi-(2*s*r - (pio2_lo-2*c) - (0.5*pio2_hi-2*f));
        }
-       if (expsign > 0)
-               return t;
-       return -t;
+       return sign ? -x : x;
 }
 #endif