gonzui


Format: Advanced Search

t2ex/bsd_source/lib/libc/src_bsd/math/e_asin.cbare sourcepermlink (0.01 seconds)

Search this content:

    1: /* @(#)e_asin.c 5.1 93/09/24 */
    2: /*
    3:  * ====================================================
    4:  * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
    5:  *
    6:  * Developed at SunPro, a Sun Microsystems, Inc. business.
    7:  * Permission to use, copy, modify, and distribute this
    8:  * software is freely granted, provided that this notice 
    9:  * is preserved.
   10:  * ====================================================
   11:  */
   12: 
   13: /* asin(x)
   14:  * Method :                  
   15:  *      Since  asin(x) = x + x^3/6 + x^5*3/40 + x^7*15/336 + ...
   16:  *      we approximate asin(x) on [0,0.5] by
   17:  *              asin(x) = x + x*x^2*R(x^2)
   18:  *      where
   19:  *              R(x^2) is a rational approximation of (asin(x)-x)/x^3 
   20:  *      and its Remes error is bounded by
   21:  *              |(asin(x)-x)/x^3 - R(x^2)| < 2^(-58.75)
   22:  *
   23:  *      For x in [0.5,1]
   24:  *              asin(x) = pi/2-2*asin(sqrt((1-x)/2))
   25:  *      Let y = (1-x), z = y/2, s := sqrt(z), and pio2_hi+pio2_lo=pi/2;
   26:  *      then for x>0.98
   27:  *              asin(x) = pi/2 - 2*(s+s*z*R(z))
   28:  *                      = pio2_hi - (2*(s+s*z*R(z)) - pio2_lo)
   29:  *      For x<=0.98, let pio4_hi = pio2_hi/2, then
   30:  *              f = hi part of s;
   31:  *              c = sqrt(z) - f = (z-f*f)/(s+f)     ...f+c=sqrt(z)
   32:  *      and
   33:  *              asin(x) = pi/2 - 2*(s+s*z*R(z))
   34:  *                      = pio4_hi+(pio4-2s)-(2s*z*R(z)-pio2_lo)
   35:  *                      = pio4_hi+(pio4-2f)-(2s*z*R(z)-(pio2_lo+2c))
   36:  *
   37:  * Special cases:
   38:  *      if x is NaN, return x itself;
   39:  *      if |x|>1, return NaN with invalid signal.
   40:  *
   41:  */
   42: 
   43: /* LINTLIBRARY */
   44: 
   45: #include <sys/cdefs.h>
   46: #include <float.h>
   47: #include <math.h>
   48: 
   49: #include "math_private.h"
   50: 
   51: static const double 
   52: one =  1.00000000000000000000e+00, /* 0x3FF00000, 0x00000000 */
   53: huge =  1.000e+300,
   54: pio2_hi =  1.57079632679489655800e+00, /* 0x3FF921FB, 0x54442D18 */
   55: pio2_lo =  6.12323399573676603587e-17, /* 0x3C91A626, 0x33145C07 */
   56: pio4_hi =  7.85398163397448278999e-01, /* 0x3FE921FB, 0x54442D18 */
   57:         /* coefficient for R(x^2) */
   58: pS0 =  1.66666666666666657415e-01, /* 0x3FC55555, 0x55555555 */
   59: pS1 = -3.25565818622400915405e-01, /* 0xBFD4D612, 0x03EB6F7D */
   60: pS2 =  2.01212532134862925881e-01, /* 0x3FC9C155, 0x0E884455 */
   61: pS3 = -4.00555345006794114027e-02, /* 0xBFA48228, 0xB5688F3B */
   62: pS4 =  7.91534994289814532176e-04, /* 0x3F49EFE0, 0x7501B288 */
   63: pS5 =  3.47933107596021167570e-05, /* 0x3F023DE1, 0x0DFDF709 */
   64: qS1 = -2.40339491173441421878e+00, /* 0xC0033A27, 0x1C8A2D4B */
   65: qS2 =  2.02094576023350569471e+00, /* 0x40002AE5, 0x9C598AC8 */
   66: qS3 = -6.88283971605453293030e-01, /* 0xBFE6066C, 0x1B8D0159 */
   67: qS4 =  7.70381505559019352791e-02; /* 0x3FB3B8C5, 0xB12E9282 */
   68: 
   69: double
   70: asin(double x)
   71: {
   72:         double t,w,p,q,c,r,s;
   73:         int32_t hx,ix;
   74:         GET_HIGH_WORD(hx,x);
   75:         ix = hx&0x7fffffff;
   76:         if(ix>= 0x3ff00000) {          /* |x|>= 1 */
   77:             u_int32_t lx;
   78:             GET_LOW_WORD(lx,x);
   79:             if(((ix-0x3ff00000)|lx)==0)
   80:                     /* asin(1)=+-pi/2 with inexact */
   81:                 return x*pio2_hi+x*pio2_lo;   
   82:             return (x-x)/(x-x);                /* asin(|x|>1) is NaN */   
   83:         } else if (ix<0x3fe00000) {    /* |x|<0.5 */
   84:             if(ix<0x3e400000) {                /* if |x| < 2**-27 */
   85:                 if(huge+x>one) return x;/* return x with inexact if x!=0*/
   86:             } else 
   87:                 t = x*x;
   88:                 p = t*(pS0+t*(pS1+t*(pS2+t*(pS3+t*(pS4+t*pS5)))));
   89:                 q = one+t*(qS1+t*(qS2+t*(qS3+t*qS4)));
   90:                 w = p/q;
   91:                 return x+x*w;
   92:         }
   93:         /* 1> |x|>= 0.5 */
   94:         w = one-fabs(x);
   95:         t = w*0.5;
   96:         p = t*(pS0+t*(pS1+t*(pS2+t*(pS3+t*(pS4+t*pS5)))));
   97:         q = one+t*(qS1+t*(qS2+t*(qS3+t*qS4)));
   98:         s = sqrt(t);
   99:         if(ix>=0x3FEF3333) {   /* if |x| > 0.975 */
  100:             w = p/q;
  101:             t = pio2_hi-(2.0*(s+s*w)-pio2_lo);
  102:         } else {
  103:             w  = s;
  104:             SET_LOW_WORD(w,0);
  105:             c  = (t-w*w)/(s+w);
  106:             r  = p/q;
  107:             p  = 2.0*s*r-(pio2_lo-2.0*c);
  108:             q  = pio4_hi-2.0*w;
  109:             t  = pio4_hi-(p-q);
  110:         }    
  111:         if(hx>0) return t; else return -t;    
  112: }
  113: 
  114: #if     LDBL_MANT_DIG == 53
  115: #ifdef  lint
  116: /* PROTOLIB1 */
  117: long double asinl(long double);
  118: #else   /* lint */
  119: __weak_alias(asinl, asin);
  120: #endif  /* lint */
  121: #endif  /* LDBL_MANT_DIG == 53 */