__float128
nextafterq (__float128 x, __float128 y)
{
	int64_t hx,hy,ix,iy;
	uint64_t lx,ly;

	GET_FLT128_WORDS64(hx,lx,x);
	GET_FLT128_WORDS64(hy,ly,y);
	ix = hx&0x7fffffffffffffffLL;		/* |x| */
	iy = hy&0x7fffffffffffffffLL;		/* |y| */

	if(((ix>=0x7fff000000000000LL)&&((ix-0x7fff000000000000LL)|lx)!=0) ||   /* x is nan */
	   ((iy>=0x7fff000000000000LL)&&((iy-0x7fff000000000000LL)|ly)!=0))     /* y is nan */
	   return x+y;
	if(x==y) return y;		/* x=y, return y */
	if((ix|lx)==0) {			/* x == 0 */
	    SET_FLT128_WORDS64(x,hy&0x8000000000000000ULL,1);/* return +-minsubnormal */

	    /* here we should raise an underflow flag */
	    return x;
	}
	if(hx>=0) {			/* x > 0 */
	    if(hx>hy||((hx==hy)&&(lx>ly))) {	/* x > y, x -= ulp */
		if(lx==0) hx--;
		lx--;
	    } else {				/* x < y, x += ulp */
		lx++;
		if(lx==0) hx++;
	    }
	} else {				/* x < 0 */
	    if(hy>=0||hx>hy||((hx==hy)&&(lx>ly))){/* x < y, x -= ulp */
		if(lx==0) hx--;
		lx--;
	    } else {				/* x > y, x += ulp */
		lx++;
		if(lx==0) hx++;
	    }
	}
	hy = hx&0x7fff000000000000LL;
	if(hy==0x7fff000000000000LL) {
	    __float128 u = x + x;		/* overflow  */
	    math_force_eval (u);
	    errno = ERANGE;
	}
	if(hy==0) {
	    __float128 u = x*x;			/* underflow */
	    math_force_eval (u);		/* raise underflow flag */
	    errno = ERANGE;
	}
	SET_FLT128_WORDS64(x,hx,lx);
	return x;
}
Exemple #2
0
int
ilogbq (__float128 x)
{
	int64_t hx,lx;
	int ix;

	GET_FLT128_WORDS64(hx,lx,x);
	hx &= 0x7fffffffffffffffLL;
	if(hx <= 0x0001000000000000LL) {
	    if((hx|lx)==0)
	      {
		errno = EDOM;
#ifdef USE_FENV_H
		feraiseexcept (FE_INVALID);
#endif
		return FP_ILOGB0;	/* ilogbl(0) = FP_ILOGB0 */
	      }
	    else			/* subnormal x */
		if(hx==0) {
		    for (ix = -16431; lx>0; lx<<=1) ix -=1;
		} else {
		    for (ix = -16382, hx<<=15; hx>0; hx<<=1) ix -=1;
		}
	    return ix;
	}
	else if (hx<0x7fff000000000000LL) return (hx>>48)-0x3fff;
	else if (FP_ILOGBNAN != INT_MAX) {
Exemple #3
0
int
isnanq (const __float128 x)
{
  int64_t hx,lx;
  GET_FLT128_WORDS64(hx,lx,x);
  hx &= 0x7fffffffffffffffLL;
  hx |= (uint64_t)(lx|(-lx))>>63;
  hx = 0x7fff000000000000LL - hx;
  return (int)((uint64_t)hx>>63);
}
__float128
frexpq (__float128 x, int *eptr)
{
  uint64_t hx, lx, ix;
  GET_FLT128_WORDS64(hx,lx,x);
  ix = 0x7fffffffffffffffULL&hx;
  *eptr = 0;
  if(ix>=0x7fff000000000000ULL||((ix|lx)==0)) return x;	/* 0,inf,nan */
  if (ix<0x0001000000000000ULL) {		/* subnormal */
    x *= two114;
    GET_FLT128_MSW64(hx,x);
    ix = hx&0x7fffffffffffffffULL;
    *eptr = -114;
  }
  *eptr += (ix>>48)-16382;
  hx = (hx&0x8000ffffffffffffULL) | 0x3ffe000000000000ULL;
  SET_FLT128_MSW64(x,hx);
  return x;
}
__float128
log2q (__float128 x)
{
  __float128 z;
  __float128 y;
  int e;
  int64_t hx, lx;

/* Test for domain */
  GET_FLT128_WORDS64 (hx, lx, x);
  if (((hx & 0x7fffffffffffffffLL) | lx) == 0)
    return (-1.0Q / fabsq (x));		/* log2l(+-0)=-inf  */
  if (hx < 0)
    return (x - x) / (x - x);
  if (hx >= 0x7fff000000000000LL)
    return (x + x);

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

/* separate mantissa from exponent */

/* Note, frexp is used so that denormal numbers
 * will be handled properly.
 */
  x = frexpq (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.5Q;
	  y = 0.5Q * z + 0.5Q;
	}
      else
	{			/*  2 (x-1)/(x+1)   */
	  z = x - 0.5Q;
	  z -= 0.5Q;
	  y = 0.5Q * x + 0.5Q;
	}
      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.0Q;	/*  2x - 1  */
    }
  else
    {
      x = x - 1.0Q;
    }
  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 log2(e)
 * and base 2 exponent by 1
 */
  z = y * LOG2EA;
  z += x * LOG2EA;
  z += y;
  z += x;
  z += e;
  return (z);
}
__float128
remquoq (__float128 x, __float128 y, int *quo)
{
  int64_t hx,hy;
  uint64_t sx,lx,ly,qs;
  int cquo;

  GET_FLT128_WORDS64 (hx, lx, x);
  GET_FLT128_WORDS64 (hy, ly, y);
  sx = hx & 0x8000000000000000ULL;
  qs = sx ^ (hy & 0x8000000000000000ULL);
  hy &= 0x7fffffffffffffffLL;
  hx &= 0x7fffffffffffffffLL;

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

  if (hy <= 0x7ffbffffffffffffLL)
    x = fmodq (x, 8 * y);              /* now x < 8y */

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

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

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

  if (hy < 0x0002000000000000LL)
    {
      if (x + x > y)
	{
	  x -= y;
	  ++cquo;
	  if (x + x >= y)
	    {
	      x -= y;
	      ++cquo;
	    }
	}
    }
  else
    {
      __float128 y_half = 0.5Q * 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.0Q)
    x = 0.0Q;
  if (sx)
    x = -x;
  return x;
}