예제 #1
0
long double
__ieee754_acoshl(long double x)
{
	long double t;
	int64_t hx;
	uint64_t lx;
	double xhi, xlo;

	ldbl_unpack (x, &xhi, &xlo);
	EXTRACT_WORDS64 (hx, xhi);
	EXTRACT_WORDS64 (lx, xlo);
	if(hx<0x3ff0000000000000LL) {		/* x < 1 */
	    return (x-x)/(x-x);
	} else if(hx >=0x41b0000000000000LL) {	/* x > 2**28 */
	    if(hx >=0x7ff0000000000000LL) {	/* x is inf of NaN */
		return x+x;
	    } else
		return __ieee754_logl(x)+ln2;	/* acosh(huge)=log(2x) */
	} else if (((hx-0x3ff0000000000000LL)|(lx&0x7fffffffffffffffLL))==0) {
	    return 0.0;			/* acosh(1) = 0 */
	} else if (hx > 0x4000000000000000LL) {	/* 2**28 > x > 2 */
	    t=x*x;
	    return __ieee754_logl(2.0*x-one/(x+__ieee754_sqrtl(t-one)));
	} else {			/* 1<x<2 */
	    t = x-one;
	    return __log1pl(t+__ieee754_sqrtl(2.0*t+t*t));
	}
}
예제 #2
0
int
FUNC (long double *x, long double payload)
{
  double hi, lo;
  uint64_t hx, lx;

  ldbl_unpack (payload, &hi, &lo);
  EXTRACT_WORDS64 (hx, hi);
  EXTRACT_WORDS64 (lx, lo);
  int exponent = hx >> EXPLICIT_MANT_DIG;
  /* Test if argument is (a) negative or too large; (b) too small,
     except for 0 when allowed; (c) not an integer.  All valid
     arguments have the low part zero.  */
  if ((lx & 0x7fffffffffffffffULL) != 0
      || exponent >= BIAS + PAYLOAD_DIG
      || (exponent < BIAS && !(SET_HIGH_BIT && hx == 0))
      || (hx & ((1ULL << (BIAS + EXPLICIT_MANT_DIG - exponent)) - 1)) != 0)
    {
      *x = 0.0L;
      return 1;
    }
  if (hx != 0)
    {
      hx &= (1ULL << EXPLICIT_MANT_DIG) - 1;
      hx |= 1ULL << EXPLICIT_MANT_DIG;
      hx >>= BIAS + EXPLICIT_MANT_DIG - exponent;
    }
예제 #3
0
double
__ieee754_log10 (double x)
{
    double y, z;
    int64_t i, hx;
    int32_t k;

    EXTRACT_WORDS64 (hx, x);

    k = 0;
    if (hx < INT64_C(0x0010000000000000))
    {   /* x < 2**-1022  */
        if (__builtin_expect ((hx & UINT64_C(0x7fffffffffffffff)) == 0, 0))
            return -two54 / (x - x);	/* log(+-0)=-inf */
        if (__builtin_expect (hx < 0, 0))
            return (x - x) / (x - x);	/* log(-#) = NaN */
        k -= 54;
        x *= two54;		/* subnormal number, scale up x */
        EXTRACT_WORDS64 (hx, x);
    }
    /* scale up resulted in a NaN number  */
    if (__builtin_expect (hx >= UINT64_C(0x7ff0000000000000), 0))
        return x + x;
    k += (hx >> 52) - 1023;
    i = ((uint64_t) k & UINT64_C(0x8000000000000000)) >> 63;
    hx = (hx & UINT64_C(0x000fffffffffffff)) | ((0x3ff - i) << 52);
    y = (double) (k + i);
    INSERT_WORDS64 (x, hx);
    z = y * log10_2lo + ivln10 * __ieee754_log (x);
    return z + y * log10_2hi;
}
예제 #4
0
long double
__ieee754_remainderl(long double x, long double p)
{
	int64_t hx,hp;
	u_int64_t sx,lx,lp;
	long double p_half;
	double xhi, xlo, phi, plo;

	ldbl_unpack (x, &xhi, &xlo);
	EXTRACT_WORDS64 (hx, xhi);
	EXTRACT_WORDS64 (lx, xlo);
	ldbl_unpack (p, &phi, &plo);
	EXTRACT_WORDS64 (hp, phi);
	EXTRACT_WORDS64 (lp, plo);
	sx = hx&0x8000000000000000ULL;
	lp ^= hp & 0x8000000000000000ULL;
	hp &= 0x7fffffffffffffffLL;
	lx ^= sx;
	hx &= 0x7fffffffffffffffLL;
	if (lp == 0x8000000000000000ULL)
	  lp = 0;
	if (lx == 0x8000000000000000ULL)
	  lx = 0;

    /* purge off exception values */
	if(hp==0) return (x*p)/(x*p);	/* p = 0 */
	if((hx>=0x7ff0000000000000LL)||			/* x not finite */
	   (hp>0x7ff0000000000000LL))			/* p is NaN */
	    return (x*p)/(x*p);


	if (hp<=0x7fdfffffffffffffLL) x = __ieee754_fmodl(x,p+p);	/* now x < 2p */
	if (((hx-hp)|(lx-lp))==0) return zero*x;
	x  = fabsl(x);
	p  = fabsl(p);
	if (hp<0x0020000000000000LL) {
	    if(x+x>p) {
		x-=p;
		if(x+x>=p) x -= p;
	    }
	} else {
	    p_half = 0.5L*p;
	    if(x>p_half) {
		x-=p;
		if(x>=p_half) x -= p;
	    }
	}
	if (sx)
	  x = -x;
	return x;
}
예제 #5
0
파일: s_fabsl.c 프로젝트: riscv/riscv-glibc
long double __fabsl(long double x)
{
	uint64_t hx, lx;
	double xhi, xlo;

	ldbl_unpack (x, &xhi, &xlo);
	EXTRACT_WORDS64 (hx, xhi);
	EXTRACT_WORDS64 (lx, xlo);
	lx = lx ^ ( hx & 0x8000000000000000LL );
	hx = hx & 0x7fffffffffffffffLL;
	INSERT_WORDS64 (xhi, hx);
	INSERT_WORDS64 (xlo, lx);
	x = ldbl_pack (xhi, xlo);
	return x;
}
예제 #6
0
파일: s_fpclassifyl.c 프로젝트: walac/glibc
int
___fpclassifyl (long double x)
{
  u_int64_t hx, lx;
  int retval = FP_NORMAL;
  double xhi, xlo;

  ldbl_unpack (x, &xhi, &xlo);
  EXTRACT_WORDS64 (hx, xhi);
  if ((hx & 0x7ff0000000000000ULL) == 0x7ff0000000000000ULL) {
      /* +/-NaN or +/-Inf */
      if (hx & 0x000fffffffffffffULL) {
	  /* +/-NaN */
	  retval = FP_NAN;
      } else {
	  retval = FP_INFINITE;
      }
  } else {
      /* +/-zero or +/- normal or +/- denormal */
      if (hx & 0x7fffffffffffffffULL) {
	  /* +/- normal or +/- denormal */
	  if ((hx & 0x7ff0000000000000ULL) > 0x0360000000000000ULL) {
	      /* +/- normal */
	      retval = FP_NORMAL;
	  } else {
	      if ((hx & 0x7ff0000000000000ULL) == 0x0360000000000000ULL) {
		  EXTRACT_WORDS64 (lx, xlo);
		  if ((lx & 0x7fffffffffffffff)	/* lower is non-zero */
		  && ((lx^hx) & 0x8000000000000000ULL)) { /* and sign differs */
		      /* +/- denormal */
		      retval = FP_SUBNORMAL;
		  } else {
		      /* +/- normal */
		      retval = FP_NORMAL;
		  }
	      } else {
		  /* +/- denormal */
		  retval = FP_SUBNORMAL;
	      }
	  }
      } else {
	  /* +/- zero */
	  retval = FP_ZERO;
      }
  }

  return retval;
}
예제 #7
0
float __nexttowardf(float x, long double y)
{
	int32_t hx,ix;
	int64_t hy,iy;
	double yhi;

	GET_FLOAT_WORD(hx,x);
	yhi = ldbl_high (y);
	EXTRACT_WORDS64 (hy, yhi);
	ix = hx&0x7fffffff;		/* |x| */
	iy = hy&0x7fffffffffffffffLL;	/* |y| */

	if((ix>0x7f800000) ||   /* x is nan */
	   (iy>0x7ff0000000000000LL))
				/* y is nan */
	   return x+y;
	if((long double) x==y) return y;	/* x=y, return y */
	if(ix==0) {				/* x == 0 */
	    float u;
	    SET_FLOAT_WORD(x,(u_int32_t)((hy>>32)&0x80000000)|1);/* return +-minsub*/
	    u = math_opt_barrier (x);
	    u = u * u;
	    math_force_eval (u);		/* raise underflow flag */
	    return x;
	}
예제 #8
0
double __nexttoward(double x, long double y)
{
	int32_t hx,ix;
	int64_t hy,iy;
	uint32_t lx;
	double yhi;

	EXTRACT_WORDS(hx,lx,x);
	yhi = ldbl_high (y);
	EXTRACT_WORDS64(hy,yhi);
	ix = hx&0x7fffffff;		/* |x| */
	iy = hy&0x7fffffffffffffffLL;	/* |y| */

	if(((ix>=0x7ff00000)&&((ix-0x7ff00000)|lx)!=0) ||   /* x is nan */
	   iy>0x7ff0000000000000LL)			    /* y is nan */
	   return x+y;
	if((long double) x==y) return y;	/* x=y, return y */
	if((ix|lx)==0) {			/* x == 0 */
	    double u;
	    INSERT_WORDS(x,(uint32_t)((hy>>32)&0x80000000),1);/* return +-minsub */
	    u = math_opt_barrier (x);
	    u = u * u;
	    math_force_eval (u);		/* raise underflow flag */
	    return x;
	}
예제 #9
0
static __always_inline int
__isinf_ns2 (double d)
{
  uint64_t di;
  EXTRACT_WORDS64 (di, d);
  return (di & 0x7fffffffffffffffull) == 0x7ff0000000000000ull;
}
예제 #10
0
double
__ieee754_acosh (double x)
{
  int64_t hx;
  EXTRACT_WORDS64 (hx, x);

  if (hx > INT64_C (0x4000000000000000))
    {
      if (__builtin_expect (hx >= INT64_C (0x41b0000000000000), 0))
	{
	  /* x > 2**28 */
	  if (hx >= INT64_C (0x7ff0000000000000))
	    /* x is inf of NaN */
	    return x + x;
	  else
	    return __ieee754_log (x) + ln2;/* acosh(huge)=log(2x) */
	}

      /* 2**28 > x > 2 */
      double t = x * x;
      return __ieee754_log (2.0 * x - one / (x + __ieee754_sqrt (t - one)));
    }
  else if (__builtin_expect (hx > INT64_C (0x3ff0000000000000), 1))
    {
      /* 1<x<2 */
      double t = x - one;
      return __log1p (t + __ieee754_sqrt (2.0 * t + t * t));
    }
  else if (__builtin_expect (hx == INT64_C (0x3ff0000000000000), 1))
    return 0.0;				/* acosh(1) = 0 */
  else					/* x < 1 */
    return (x - x) / (x - x);
}
예제 #11
0
파일: s_isinf_ns.c 프로젝트: dreal/tai
int
__isinf_ns (double x)
{
	int64_t ix;
	EXTRACT_WORDS64(ix,x);
	return (ix & UINT64_C(0x7fffffffffffffff)) == UINT64_C(0x7ff0000000000000);
}
예제 #12
0
static __always_inline int
__finite_inl (double d)
{
  uint64_t di;
  EXTRACT_WORDS64 (di, d);
  return (di & 0x7fffffffffffffffull) < 0x7ff0000000000000ull;
}
예제 #13
0
long double __asinhl(long double x)
{
	long double t,w;
	int64_t hx,ix;
	double xhi;

	xhi = ldbl_high (x);
	EXTRACT_WORDS64 (hx, xhi);
	ix = hx&0x7fffffffffffffffLL;
	if(ix>=0x7ff0000000000000LL) return x+x;	/* x is inf or NaN */
	if(ix< 0x3c70000000000000LL) {	/* |x|<2**-56 */
	    math_check_force_underflow (x);
	    if(huge+x>one) return x;	/* return x inexact except 0 */
	}
	if(ix>0x4370000000000000LL) {	/* |x| > 2**56 */
	    w = __ieee754_logl(fabsl(x))+ln2;
	} else if (ix>0x4000000000000000LL) {	/* 2**56 >= |x| > 2.0 */
	    t = fabs(x);
	    w = __ieee754_logl(2.0*t+one/(sqrtl(x*x+one)+t));
	} else {		/* 2.0 >= |x| >= 2**-56 */
	    t = x*x;
	    w =__log1pl(fabsl(x)+t/(one+sqrtl(one+t)));
	}
	if(hx>0) return w; else return -w;
}
예제 #14
0
int
__finite(double x)
{
  int64_t lx;
  EXTRACT_WORDS64(lx,x);
  return (int)((uint64_t)((lx&INT64_C(0x7ff0000000000000))-INT64_C(0x7ff0000000000000))>>63);
}
예제 #15
0
int
__isnan (double x)
{
  uint64_t ix;
  EXTRACT_WORDS64 (ix, x);
  return ix * 2 > 0xffe0000000000000ul;
}
예제 #16
0
int
__issignalingl (long double x)
{
  uint64_t xi;
  /* For inspecting NaN status, we only have to look at the first of the pair
     of IEEE 754 64-bit precision numbers.  */
  double xhi;

  xhi = ldbl_high (x);
  EXTRACT_WORDS64 (xi, xhi);
#ifdef HIGH_ORDER_BIT_IS_SET_FOR_SNAN
# error untested
  /* We only have to care about the high-order bit of x's significand, because
     having it set (sNaN) already makes the significand different from that
     used to designate infinity.  */
  return (xi & UINT64_C (0x7ff8000000000000)) == UINT64_C (0x7ff8000000000000);
#else
  /* To keep the following comparison simple, toggle the quiet/signaling bit,
     so that it is set for sNaNs.  This is inverse to IEEE 754-2008 (as well as
     common practice for IEEE 754-1985).  */
  xi ^= UINT64_C (0x0008000000000000);
  /* We have to compare for greater (instead of greater or equal), because x's
     significand being all-zero designates infinity not NaN.  */
  return (xi & UINT64_C (0x7fffffffffffffff)) > UINT64_C (0x7ff8000000000000);
#endif
}
예제 #17
0
파일: s_signbitl.c 프로젝트: AubrCool/glibc
int
___signbitl (long double x)
{
  int64_t e;
  double xhi;

  xhi = ldbl_high (x);
  EXTRACT_WORDS64 (e, xhi);
  return e < 0;
}
예제 #18
0
long double
getpayloadl (const long double *x)
{
  double xhi = ldbl_high (*x);
  uint64_t ix;
  EXTRACT_WORDS64 (ix, xhi);
  ix &= 0x7ffffffffffffULL;
  if (FIX_INT_FP_CONVERT_ZERO && ix == 0)
    return 0.0L;
  return (long double) ix;
}
예제 #19
0
int
__totalordermag (double x, double y)
{
  uint64_t ix, iy;
  EXTRACT_WORDS64 (ix, x);
  EXTRACT_WORDS64 (iy, y);
  ix &= 0x7fffffffffffffffULL;
  iy &= 0x7fffffffffffffffULL;
#if HIGH_ORDER_BIT_IS_SET_FOR_SNAN
  /* For the preferred quiet NaN convention, this operation is a
     comparison of the representations of the absolute values of the
     arguments.  If both arguments are NaNs, invert the
     quiet/signaling bit so comparing that way works.  */
  if (ix > 0x7ff0000000000000ULL && iy > 0x7ff0000000000000ULL)
    {
      ix ^= 0x0008000000000000ULL;
      iy ^= 0x0008000000000000ULL;
    }
#endif
  return ix <= iy;
}
예제 #20
0
파일: s_finitel.c 프로젝트: AubrCool/glibc
int
___finitel (long double x)
{
  uint64_t hx;
  double xhi;

  xhi = ldbl_high (x);
  EXTRACT_WORDS64 (hx, xhi);
  hx &= 0x7fffffffffffffffLL;
  hx -= 0x7ff0000000000000LL;
  return hx >> 63;
}
예제 #21
0
파일: s_logb.c 프로젝트: dreal/tai
double
__logb (double x)
{
  int64_t ix;

  EXTRACT_WORDS64 (ix, x);
  ix &= UINT64_C(0x7fffffffffffffff);
  if (ix == 0)
    return -1.0 / fabs (x);
  unsigned int ex = ix >> 52;
  if (ex == 0x7ff)
    return x * x;
  return ex == 0 ? -1022.0 : (double) (ex - 1023);
}
예제 #22
0
파일: e_cosh.c 프로젝트: AubrCool/glibc
double
__ieee754_cosh (double x)
{
	double t,w;
	int32_t ix;

    /* High word of |x|. */
	GET_HIGH_WORD(ix,x);
	ix &= 0x7fffffff;

    /* |x| in [0,22] */
	if (ix < 0x40360000) {
	    /* |x| in [0,0.5*ln2], return 1+expm1(|x|)^2/(2*exp(|x|)) */
		if(ix<0x3fd62e43) {
		    t = __expm1(fabs(x));
		    w = one+t;
		    if (ix<0x3c800000) return w;	/* cosh(tiny) = 1 */
		    return one+(t*t)/(w+w);
		}

	    /* |x| in [0.5*ln2,22], return (exp(|x|)+1/exp(|x|)/2; */
		t = __ieee754_exp(fabs(x));
		return half*t+half/t;
	}

    /* |x| in [22, log(maxdouble)] return half*exp(|x|) */
	if (ix < 0x40862e42)  return half*__ieee754_exp(fabs(x));

    /* |x| in [log(maxdouble), overflowthresold] */
	int64_t fix;
	EXTRACT_WORDS64(fix, x);
	fix &= UINT64_C(0x7fffffffffffffff);
	if (fix <= UINT64_C(0x408633ce8fb9f87d)) {
	    w = __ieee754_exp(half*fabs(x));
	    t = half*w;
	    return t*w;
	}

    /* x is INF or NaN */
	if(ix>=0x7ff00000) return x*x;

    /* |x| > overflowthresold, cosh(x) overflow */
	return huge*huge;
}
예제 #23
0
double
__logb (double x)
{
  int64_t ix, ex;

  EXTRACT_WORDS64 (ix, x);
  ix &= UINT64_C(0x7fffffffffffffff);
  if (ix == 0)
    return -1.0 / fabs (x);
  ex = ix >> 52;
  if (ex == 0x7ff)
    return x * x;
  if (__builtin_expect (ex == 0, 0))
    {
      int m = __builtin_clzll (ix);
      ex -= m - 12;
    }
  return (double) (ex - 1023);
}
예제 #24
0
long double
__ieee754_sinhl(long double x)
{
	long double t,w,h;
	int64_t ix,jx;
	double xhi;

    /* High word of |x|. */
	xhi = ldbl_high (x);
	EXTRACT_WORDS64 (jx, xhi);
	ix = jx&0x7fffffffffffffffLL;

    /* x is INF or NaN */
	if(ix>=0x7ff0000000000000LL) return x+x;

	h = 0.5;
	if (jx<0) h = -h;
    /* |x| in [0,40], return sign(x)*0.5*(E+E/(E+1))) */
	if (ix < 0x4044000000000000LL) {	/* |x|<40 */
	    if (ix<0x3c90000000000000LL) {	/* |x|<2**-54 */
		math_check_force_underflow (x);
		if(shuge+x>one) return x;/* sinhl(tiny) = tiny with inexact */
	    }
	    t = __expm1l(fabsl(x));
	    if(ix<0x3ff0000000000000LL) return h*(2.0*t-t*t/(t+one));
	    w = t/(t+one);
	    return h*(t+w);
	}

    /* |x| in [40, log(maxdouble)] return 0.5*exp(|x|) */
	if (ix < 0x40862e42fefa39efLL)  return h*__ieee754_expl(fabsl(x));

    /* |x| in [log(maxdouble), overflowthresold] */
	if (ix <= 0x408633ce8fb9f87eLL) {
	    w = __ieee754_expl(0.5*fabsl(x));
	    t = h*w;
	    return t*w;
	}

    /* |x| > overflowthresold, sinh(x) overflow */
	return x*shuge;
}
예제 #25
0
int
__issignaling (double x)
{
  u_int64_t xi;
  EXTRACT_WORDS64 (xi, x);
#if HIGH_ORDER_BIT_IS_SET_FOR_SNAN
  /* We only have to care about the high-order bit of x's significand, because
     having it set (sNaN) already makes the significand different from that
     used to designate infinity.  */
  return (xi & UINT64_C (0x7ff8000000000000)) == UINT64_C (0x7ff8000000000000);
#else
  /* To keep the following comparison simple, toggle the quiet/signaling bit,
     so that it is set for sNaNs.  This is inverse to IEEE 754-2008 (as well as
     common practice for IEEE 754-1985).  */
  xi ^= UINT64_C (0x0008000000000000);
  /* We have to compare for greater (instead of greater or equal), because x's
     significand being all-zero designates infinity not NaN.  */
  return (xi & UINT64_C (0x7fffffffffffffff)) > UINT64_C (0x7ff8000000000000);
#endif
}
예제 #26
0
double
__roundeven (double x)
{
  uint64_t ix, ux;
  EXTRACT_WORDS64 (ix, x);
  ux = ix & 0x7fffffffffffffffULL;
  int exponent = ux >> (MANT_DIG - 1);
  if (exponent >= BIAS + MANT_DIG - 1)
    {
      /* Integer, infinity or NaN.  */
      if (exponent == MAX_EXP)
	/* Infinity or NaN; quiet signaling NaNs.  */
	return x + x;
      else
	return x;
    }
  else if (exponent >= BIAS)
    {
      /* At least 1; not necessarily an integer.  Locate the bits with
	 exponents 0 and -1 (when the unbiased exponent is 0, the bit
	 with exponent 0 is implicit, but as the bias is odd it is OK
	 to take it from the low bit of the exponent).  */
      int int_pos = (BIAS + MANT_DIG - 1) - exponent;
      int half_pos = int_pos - 1;
      uint64_t half_bit = 1ULL << half_pos;
      uint64_t int_bit = 1ULL << int_pos;
      if ((ix & (int_bit | (half_bit - 1))) != 0)
	/* Carry into the exponent works correctly.  No need to test
	   whether HALF_BIT is set.  */
	ix += half_bit;
      ix &= ~(int_bit - 1);
    }
  else if (exponent == BIAS - 1 && ux > 0x3fe0000000000000ULL)
    /* Interval (0.5, 1).  */
    ix = (ix & 0x8000000000000000ULL) | 0x3ff0000000000000ULL;
  else
    /* Rounds to 0.  */
    ix &= 0x8000000000000000ULL;
  INSERT_WORDS64 (x, ix);
  return x;
}
예제 #27
0
long double __tanhl(long double x)
{
	long double t,z;
	int64_t jx,ix;
	double xhi;

    /* High word of |x|. */
	xhi = ldbl_high (x);
	EXTRACT_WORDS64 (jx, xhi);
	ix = jx&0x7fffffffffffffffLL;

    /* x is INF or NaN */
	if(ix>=0x7ff0000000000000LL) {
	    if (jx>=0) return one/x+one;    /* tanh(+-inf)=+-1 */
	    else       return one/x-one;    /* tanh(NaN) = NaN */
	}

    /* |x| < 40 */
	if (ix < 0x4044000000000000LL) {		/* |x|<40 */
	    if (ix == 0)
		return x;		/* x == +-0 */
	    if (ix<0x3c60000000000000LL) 	/* |x|<2**-57 */
	      {
		math_check_force_underflow (x);
		return x;		/* tanh(small) = small */
	      }
	    if (ix>=0x3ff0000000000000LL) {	/* |x|>=1  */
		t = __expm1l(two*fabsl(x));
		z = one - two/(t+two);
	    } else {
	        t = __expm1l(-two*fabsl(x));
	        z= -t/(t+two);
	    }
    /* |x| > 40, return +-1 */
	} else {
	    z = one - tiny;		/* raised inexact flag */
	}
	return (jx>=0)? z: -z;
}
예제 #28
0
파일: e_log10l.c 프로젝트: AubrCool/glibc
long double
__ieee754_log10l (long double x)
{
  long double z;
  long double y;
  int e;
  int64_t hx;
  double xhi;

/* Test for domain */
  xhi = ldbl_high (x);
  EXTRACT_WORDS64 (hx, xhi);
  if ((hx & 0x7fffffffffffffffLL) == 0)
    return (-1.0L / (x - x));
  if (hx < 0)
    return (x - x) / (x - x);
  if (hx >= 0x7ff0000000000000LL)
    return (x + x);

  if (x == 1.0L)
    return 0.0L;

/* separate mantissa from exponent */

/* Note, frexp is used so that denormal numbers
 * will be handled properly.
 */
  x = __frexpl (x, &e);


/* logarithm using log(x) = z + z**3 P(z)/Q(z),
 * where z = 2(x-1)/x+1)
 */
  if ((e > 2) || (e < -2))
    {
      if (x < SQRTH)
	{			/* 2( 2x-1 )/( 2x+1 ) */
	  e -= 1;
	  z = x - 0.5L;
	  y = 0.5L * z + 0.5L;
	}
      else
	{			/*  2 (x-1)/(x+1)   */
	  z = x - 0.5L;
	  z -= 0.5L;
	  y = 0.5L * x + 0.5L;
	}
      x = z / y;
      z = x * x;
      y = x * (z * neval (z, R, 5) / deval (z, S, 5));
      goto done;
    }


/* logarithm using log(1+x) = x - .5x**2 + x**3 P(x)/Q(x) */

  if (x < SQRTH)
    {
      e -= 1;
      x = 2.0 * x - 1.0L;	/*  2x - 1  */
    }
  else
    {
      x = x - 1.0L;
    }
  z = x * x;
  y = x * (z * neval (x, P, 12) / deval (x, Q, 11));
  y = y - 0.5 * z;

done:

  /* Multiply log of fraction by log10(e)
   * and base 2 exponent by log10(2).
   */
  z = y * L10EB;
  z += x * L10EB;
  z += e * L102B;
  z += y * L10EA;
  z += x * L10EA;
  z += e * L102A;
  return (z);
}
예제 #29
0
long double
__remquol (long double x, long double y, int *quo)
{
  int64_t hx,hy;
  u_int64_t sx,lx,ly,qs;
  int cquo;
  double xhi, xlo, yhi, ylo;

  ldbl_unpack (x, &xhi, &xlo);
  EXTRACT_WORDS64 (hx, xhi);
  EXTRACT_WORDS64 (lx, xlo);
  ldbl_unpack (y, &yhi, &ylo);
  EXTRACT_WORDS64 (hy, yhi);
  EXTRACT_WORDS64 (ly, ylo);
  sx = hx & 0x8000000000000000ULL;
  qs = sx ^ (hy & 0x8000000000000000ULL);
  hy &= 0x7fffffffffffffffLL;
  hx &= 0x7fffffffffffffffLL;

  /* Purge off exception values.  */
  if (hy == 0)
    return (x * y) / (x * y); 			/* y = 0 */
  if ((hx >= 0x7ff0000000000000LL)		/* x not finite */
      || (hy > 0x7ff0000000000000LL))		/* y is NaN */
    return (x * y) / (x * y);

  if (hy <= 0x7fbfffffffffffffLL)
    x = __ieee754_fmodl (x, 8 * y);              /* now x < 8y */

  if (((hx - hy) | (lx - ly)) == 0)
    {
      *quo = qs ? -1 : 1;
      return zero * x;
    }

  x  = fabsl (x);
  y  = fabsl (y);
  cquo = 0;

  if (hy <= 0x7fcfffffffffffffLL && x >= 4 * y)
    {
      x -= 4 * y;
      cquo += 4;
    }
  if (hy <= 0x7fdfffffffffffffLL && x >= 2 * y)
    {
      x -= 2 * y;
      cquo += 2;
    }

  if (hy < 0x0020000000000000LL)
    {
      if (x + x > y)
	{
	  x -= y;
	  ++cquo;
	  if (x + x >= y)
	    {
	      x -= y;
	      ++cquo;
	    }
	}
    }
  else
    {
      long double y_half = 0.5L * y;
      if (x > y_half)
	{
	  x -= y;
	  ++cquo;
	  if (x >= y_half)
	    {
	      x -= y;
	      ++cquo;
	    }
	}
    }

  *quo = qs ? -cquo : cquo;

  /* Ensure correct sign of zero result in round-downward mode.  */
  if (x == 0.0L)
    x = 0.0L;
  if (sx)
    x = -x;
  return x;
}
예제 #30
0
double
__remquo (double x, double y, int *quo)
{
  int64_t hx, hy;
  uint64_t sx, qs;
  int cquo;

  EXTRACT_WORDS64 (hx, x);
  EXTRACT_WORDS64 (hy, y);
  sx = hx & UINT64_C(0x8000000000000000);
  qs = sx ^ (hy & UINT64_C(0x8000000000000000));
  hy &= UINT64_C(0x7fffffffffffffff);
  hx &= UINT64_C(0x7fffffffffffffff);

  /* Purge off exception values.  */
  if (__glibc_unlikely (hy == 0))
    return (x * y) / (x * y);			/* y = 0 */
  if (__builtin_expect (hx >= UINT64_C(0x7ff0000000000000) /* x not finite */
			|| hy > UINT64_C(0x7ff0000000000000), 0))/* y is NaN */
    return (x * y) / (x * y);

  if (hy <= UINT64_C(0x7fbfffffffffffff))
    x = __ieee754_fmod (x, 8 * y);		/* now x < 8y */

  if (__glibc_unlikely (hx == hy))
    {
      *quo = qs ? -1 : 1;
      return zero * x;
    }

  x = fabs (x);
  INSERT_WORDS64 (y, hy);
  cquo = 0;

  if (hy <= UINT64_C(0x7fcfffffffffffff) && x >= 4 * y)
    {
      x -= 4 * y;
      cquo += 4;
    }
  if (hy <= UINT64_C(0x7fdfffffffffffff) && x >= 2 * y)
    {
      x -= 2 * y;
      cquo += 2;
    }

  if (hy < UINT64_C(0x0020000000000000))
    {
      if (x + x > y)
	{
	  x -= y;
	  ++cquo;
	  if (x + x >= y)
	    {
	      x -= y;
	      ++cquo;
	    }
	}
    }
  else
    {
      double y_half = 0.5 * y;
      if (x > y_half)
	{
	  x -= y;
	  ++cquo;
	  if (x >= y_half)
	    {
	      x -= y;
	      ++cquo;
	    }
	}
    }

  *quo = qs ? -cquo : cquo;

  /* Ensure correct sign of zero result in round-downward mode.  */
  if (x == 0.0)
    x = 0.0;
  if (sx)
    x = -x;
  return x;
}