예제 #1
0
float
__ieee754_atanhf (float x)
{
  float xa = fabsf (x);
  float t;
  if (isless (xa, 0.5f))
    {
      if (__glibc_unlikely (xa < 0x1.0p-28f))
	{
	  math_force_eval (huge + x);
	  if (fabsf (x) < FLT_MIN)
	    {
	      float force_underflow = x * x;
	      math_force_eval (force_underflow);
	    }
	  return x;
	}

      t = xa + xa;
      t = 0.5f * __log1pf (t + t * xa / (1.0f - xa));
    }
  else if (__glibc_likely (isless (xa, 1.0f)))
    t = 0.5f * __log1pf ((xa + xa) / (1.0f - xa));
  else
    {
      if (isgreater (xa, 1.0f))
	return (x - x) / (x - x);

      return x / 0.0f;
    }

  return __copysignf (t, x);
}
예제 #2
0
double __nexttoward(double x, long double y)
{
	int32_t hx,ix,iy;
	u_int32_t lx,hy,ly,esy;

	EXTRACT_WORDS(hx,lx,x);
	GET_LDOUBLE_WORDS(esy,hy,ly,y);
	ix = hx&0x7fffffff;		/* |x| */
	iy = esy&0x7fff;		/* |y| */

	/* Intel's extended format has the normally implicit 1 explicit
	   present.  Sigh!  */
	if(((ix>=0x7ff00000)&&((ix-0x7ff00000)|lx)!=0) ||   /* x is nan */
	   ((iy>=0x7fff)&&((hy&0x7fffffff)|ly)!=0))        /* 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,(esy&0x8000)<<16,1); /* return +-minsub */
	    u = math_opt_barrier (x);
	    u = u * u;
	    math_force_eval (u);		/* raise underflow flag */
	    return x;
	}
	if(hx>=0) {				/* x > 0 */
	    if (x > y) {			/* x -= ulp */
		if(lx==0) hx -= 1;
		lx -= 1;
	    } else {				/* x < y, x += ulp */
		lx += 1;
		if(lx==0) hx += 1;
	    }
	} else {				/* x < 0 */
	    if (x < y) {			/* x -= ulp */
		if(lx==0) hx -= 1;
		lx -= 1;
	    } else {				/* x > y, x += ulp */
		lx += 1;
		if(lx==0) hx += 1;
	    }
	}
	hy = hx&0x7ff00000;
	if(hy>=0x7ff00000) {
	  double u = x+x;			/* overflow  */
	  math_force_eval (u);
	}
	if(hy<0x00100000) {
	    double u = x*x;			/* underflow */
	    math_force_eval (u);		/* raise underflow flag */
	}
	INSERT_WORDS(x,hx,lx);
	return x;
}
예제 #3
0
__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;
}
예제 #4
0
long double __nextafterl(long double x, long double y)
{
	int64_t hx,hy,ix,iy;
	u_int64_t lx,ly;

	GET_LDOUBLE_WORDS64(hx,lx,x);
	GET_LDOUBLE_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 */
	    long double u;
	    SET_LDOUBLE_WORDS64(x,hy&0x8000000000000000ULL,1);/* return +-minsubnormal */
	    u = math_opt_barrier (x);
	    u = u * u;
	    math_force_eval (u);		/* raise 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) {
	    long double u = x + x;		/* overflow  */
	    math_force_eval (u);
	}
	if(hy==0) {
	    long double u = x*x;		/* underflow */
	    math_force_eval (u);		/* raise underflow flag */
	}
	SET_LDOUBLE_WORDS64(x,hx,lx);
	return x;
}
예제 #5
0
float __nexttowardf(float x, long double y)
{
	int32_t hx,ix,iy;
	uint32_t hy,ly,esy;

	GET_FLOAT_WORD(hx,x);
	GET_LDOUBLE_WORDS(esy,hy,ly,y);
	ix = hx&0x7fffffff;		/* |x| */
	iy = esy&0x7fff;		/* |y| */

	if((ix>0x7f800000) ||			/* x is nan */
	   (iy>=0x7fff&&((hy|ly)!=0)))		/* 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,((esy&0x8000)<<16)|1);/* return +-minsub*/
	    u = math_opt_barrier (x);
	    u = u * u;
	    math_force_eval (u);		/* raise underflow flag */
	    return x;
	}
	if(hx>=0) {				/* x > 0 */
	    if(x > y) {				/* x -= ulp */
		hx -= 1;
	    } else {				/* x < y, x += ulp */
		hx += 1;
	    }
	} else {				/* x < 0 */
	    if(x < y) {				/* x -= ulp */
		hx -= 1;
	    } else {				/* x > y, x += ulp */
		hx += 1;
	    }
	}
	hy = hx&0x7f800000;
	if(hy>=0x7f800000) {
	  float u = x+x;			/* overflow  */
	  math_force_eval (u);
	  __set_errno (ERANGE);
	}
	if(hy<0x00800000) {
	    float u = x*x;			/* underflow */
	    math_force_eval (u);		/* raise underflow flag */
	    __set_errno (ERANGE);
	}
	SET_FLOAT_WORD(x,hx);
	return x;
}
예제 #6
0
long double
__ieee754_atanhl(long double x)
{
	long double t;
	u_int32_t jx, ix;
	ieee854_long_double_shape_type u;

	u.value = x;
	jx = u.parts32.w0;
	ix = jx & 0x7fffffff;
	u.parts32.w0 = ix;
	if (ix >= 0x3fff0000) /* |x| >= 1.0 or infinity or NaN */
	  {
	    if (u.value == one)
	      return x/zero;
	    else
	      return (x-x)/(x-x);
	  }
	if(ix<0x3fc60000 && (huge+x)>zero)	/* x < 2^-57 */
	  {
	    if (fabsl (x) < LDBL_MIN)
	      {
		long double force_underflow = x * x;
		math_force_eval (force_underflow);
	      }
	    return x;
	  }

	if(ix<0x3ffe0000) {		/* x < 0.5 */
	    t = u.value+u.value;
	    t = 0.5*__log1pl(t+t*u.value/(one-u.value));
	} else
	    t = 0.5*__log1pl((u.value+u.value)/(one-u.value));
	if(jx & 0x80000000) return -t; else return t;
}
예제 #7
0
float
__ieee754_atanhf (float x)
{
  float xa = fabsf (x);
  float t;
  if (isless (xa, 0.5f))
    {
      if (__builtin_expect (xa < 0x1.0p-28f, 0))
	{
	  math_force_eval (huge + x);
	  return x;
	}

      t = xa + xa;
      t = 0.5f * __log1pf (t + t * xa / (1.0f - xa));
    }
  else if (__builtin_expect (isless (xa, 1.0f), 1))
    t = 0.5f * __log1pf ((xa + xa) / (1.0f - xa));
  else
    {
      if (isgreater (xa, 1.0f))
	return (x - x) / (x - x);

      return x / 0.0f;
    }

  return __copysignf (t, 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
double
__ieee754_atanh (double x)
{
  double xa = fabs (x);
  double t;
  if (isless (xa, 0.5))
    {
      if (__glibc_unlikely (xa < 0x1.0p-28))
	{
	  math_force_eval (huge + x);
	  math_check_force_underflow (x);
	  return x;
	}

      t = xa + xa;
      t = 0.5 * __log1p (t + t * xa / (1.0 - xa));
    }
  else if (__glibc_likely (isless (xa, 1.0)))
    t = 0.5 * __log1p ((xa + xa) / (1.0 - xa));
  else
    {
      if (isgreater (xa, 1.0))
	return (x - x) / (x - x);

      return x / 0.0;
    }

  return __copysign (t, x);
}
예제 #10
0
double
__ieee754_atanh (double x)
{
  double xa = fabs (x);
  double t;
  if (isless (xa, 0.5))
    {
      if (__builtin_expect (xa < 0x1.0p-28, 0))
	{
	  math_force_eval (huge + x);
	  return x;
	}

      t = xa + xa;
      t = 0.5 * __log1p (t + t * xa / (1.0 - xa));
    }
  else if (__builtin_expect (isless (xa, 1.0), 1))
    t = 0.5 * __log1p ((xa + xa) / (1.0 - xa));
  else
    {
      if (isgreater (xa, 1.0))
	return (x - x) / (x - x);

      return x / 0.0;
    }

  return __copysign (t, x);
}
예제 #11
0
float
__fmaf (float x, float y, float z)
{
  fenv_t env;

  /* Multiplication is always exact.  */
  double temp = (double) x * (double) y;

  /* Ensure correct sign of an exact zero result by performing the
     addition in the original rounding mode in that case.  */
  if (temp == -z)
    return (float) temp + z;

  union ieee754_double u;

  libc_feholdexcept_setround (&env, FE_TOWARDZERO);

  /* Perform addition with round to odd.  */
  u.d = temp + (double) z;
  /* Ensure the addition is not scheduled after fetestexcept call.  */
  math_force_eval (u.d);

  /* Reset rounding mode and test for inexact simultaneously.  */
  int j = libc_feupdateenv_test (&env, FE_INEXACT) != 0;

  if ((u.ieee.mantissa1 & 1) == 0 && u.ieee.exponent != 0x7ff)
    u.ieee.mantissa1 |= j;

  /* And finally truncation with round to nearest.  */
  return (float) u.d;
}
예제 #12
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;
	}
예제 #13
0
float __nldbl_nexttowardf(float x, double y)
{
	int32_t hx,hy,ix,iy;
	u_int32_t ly;

	GET_FLOAT_WORD(hx,x);
	EXTRACT_WORDS(hy,ly,y);
	ix = hx&0x7fffffff;		/* |x| */
	iy = hy&0x7fffffff;		/* |y| */

	if((ix>0x7f800000) ||				   /* x is nan */
	   ((iy>=0x7ff00000)&&((iy-0x7ff00000)|ly)!=0))    /* y is nan */
	   return x+y;
	if((double) x==y) return y;		/* x=y, return y */
	if(ix==0) {				/* x == 0 */
	    float u;
	    SET_FLOAT_WORD(x,(u_int32_t)(hy&0x80000000)|1);/* return +-minsub*/
	    u = math_opt_barrier (x);
	    u = u * u;
	    math_force_eval (u);		/* raise underflow flag */
	    return x;
	}
	if(hx>=0) {				/* x > 0 */
	    if(x > y)				/* x -= ulp */
		hx -= 1;
	    else				/* x < y, x += ulp */
		hx += 1;
	} else {				/* x < 0 */
	    if(x < y)				/* x -= ulp */
		hx -= 1;
	    else				/* x > y, x += ulp */
		hx += 1;
	}
	hy = hx&0x7f800000;
	if(hy>=0x7f800000) {
	  float u = x+x;			/* overflow  */
	  math_force_eval (u);
	  __set_errno (ERANGE);
	}
	if(hy<0x00800000) {
	    float u = x*x;			/* underflow */
	    math_force_eval (u);		/* raise underflow flag */
	    __set_errno (ERANGE);
	}
	SET_FLOAT_WORD(x,hx);
	return x;
}
예제 #14
0
float __nextafterf(float x, float y)
{
	int32_t hx,hy,ix,iy;

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

	if((ix>0x7f800000) ||   /* x is nan */
	   (iy>0x7f800000))     /* y is nan */
	   return x+y;
	if(x==y) return y;		/* x=y, return y */
	if(ix==0) {				/* x == 0 */
	    float u;
	    SET_FLOAT_WORD(x,(hy&0x80000000)|1);/* return +-minsubnormal */
	    u = math_opt_barrier (x);
	    u = u*u;
	    math_force_eval (u);		/* raise underflow flag */
	    return x;
	}
	if(hx>=0) {				/* x > 0 */
	    if(hx>hy) {				/* x > y, x -= ulp */
		hx -= 1;
	    } else {				/* x < y, x += ulp */
		hx += 1;
	    }
	} else {				/* x < 0 */
	    if(hy>=0||hx>hy){			/* x < y, x -= ulp */
		hx -= 1;
	    } else {				/* x > y, x += ulp */
		hx += 1;
	    }
	}
	hy = hx&0x7f800000;
	if(hy>=0x7f800000) {
	  float u = x+x;	/* overflow  */
	  math_force_eval (u);
	}
	if(hy<0x00800000) {
	    float u = x*x;			/* underflow */
	    math_force_eval (u);		/* raise underflow flag */
	}
	SET_FLOAT_WORD(x,hx);
	return x;
}
예제 #15
0
파일: e_j0.c 프로젝트: gf-chen/glibc
double
__ieee754_j0(double x)
{
	double z, s,c,ss,cc,r,u,v,r1,r2,s1,s2,z2,z4;
	int32_t hx,ix;

	GET_HIGH_WORD(hx,x);
	ix = hx&0x7fffffff;
	if(ix>=0x7ff00000) return one/(x*x);
	x = fabs(x);
	if(ix >= 0x40000000) {	/* |x| >= 2.0 */
		__sincos (x, &s, &c);
		ss = s-c;
		cc = s+c;
		if(ix<0x7fe00000) {  /* make sure x+x not overflow */
		    z = -__cos(x+x);
		    if ((s*c)<zero) cc = z/ss;
		    else	    ss = z/cc;
		}
	/*
	 * j0(x) = 1/sqrt(pi) * (P(0,x)*cc - Q(0,x)*ss) / sqrt(x)
	 * y0(x) = 1/sqrt(pi) * (P(0,x)*ss + Q(0,x)*cc) / sqrt(x)
	 */
		if(ix>0x48000000) z = (invsqrtpi*cc)/__ieee754_sqrt(x);
		else {
		    u = pzero(x); v = qzero(x);
		    z = invsqrtpi*(u*cc-v*ss)/__ieee754_sqrt(x);
		}
		return z;
	}
	if(ix<0x3f200000) {	/* |x| < 2**-13 */
	  math_force_eval(huge+x);	/* raise inexact if x != 0 */
	  if(ix<0x3e400000) return one;	/* |x|<2**-27 */
	  else	      return one - 0.25*x*x;
	}
	z = x*x;
#ifdef DO_NOT_USE_THIS
	r =  z*(R02+z*(R03+z*(R04+z*R05)));
	s =  one+z*(S01+z*(S02+z*(S03+z*S04)));
#else
	r1 = z*R[2]; z2=z*z;
	r2 = R[3]+z*R[4]; z4=z2*z2;
	r  = r1 + z2*r2 + z4*R[5];
	s1 = one+z*S[1];
	s2 = S[2]+z*S[3];
	s = s1 + z2*s2 + z4*S[4];
#endif
	if(ix < 0x3FF00000) {	/* |x| < 1.00 */
	    return one + z*(-0.25+(r/s));
	} else {
	    u = 0.5*x;
	    return((one+u)*(one-u)+z*(r/s));
	}
}
예제 #16
0
float nextafterf(float x, float y)
{
	int32_t hx, hy, ix, iy;

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

	/* x is nan or y is nan? */
	if ((ix > 0x7f800000) || (iy > 0x7f800000))
		return x + y;

	if (x == y)
		return y;

	if (ix == 0) { /* x == 0? */
/* glibc 2.4 does not seem to set underflow? */
/*		float u; */
		/* return +-minsubnormal */
		SET_FLOAT_WORD(x, (hy & 0x80000000) | 1);
/*		u = x * x;     raise underflow flag */
/*		math_force_eval(u); */
		return x;
	}

	if (hx >= 0) { /* x > 0 */
		if (hx > hy) { /* x > y: x -= ulp */
			hx -= 1;
		} else { /* x < y: x += ulp */
			hx += 1;
		}
	} else { /* x < 0 */
		if (hy >= 0 || hx > hy) { /* x < y: x -= ulp */
			hx -= 1;
		} else { /* x > y: x += ulp */
			hx += 1;
		}
	}
	hy = hx & 0x7f800000;
	if (hy >= 0x7f800000) {
		x = x + x; /* overflow */
		return x; /* overflow */
	}
	if (hy < 0x00800000) {
		float u = x * x; /* underflow */
		math_force_eval(u); /* raise underflow flag */
	}
	SET_FLOAT_WORD(x, hx);
	return x;
}
예제 #17
0
파일: s_tanh.c 프로젝트: hwoarang/glibc
double
__tanh (double x)
{
  double t, z;
  int32_t jx, ix, lx;

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

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

  /* |x| < 22 */
  if (ix < 0x40360000)                  /* |x|<22 */
    {
      if ((ix | lx) == 0)
	return x;                       /* x == +-0 */
      if (ix < 0x3c800000)              /* |x|<2**-55 */
	{
	  if (fabs (x) < DBL_MIN)
	    {
	      double force_underflow = x * x;
	      math_force_eval (force_underflow);
	    }
	  return x * (one + x);           /* tanh(small) = small */
	}
      if (ix >= 0x3ff00000)             /* |x|>=1  */
	{
	  t = __expm1 (two * fabs (x));
	  z = one - two / (t + two);
	}
      else
	{
	  t = __expm1 (-two * fabs (x));
	  z = -t / (t + two);
	}
      /* |x| > 22, return +-1 */
    }
  else
    {
      z = one - tiny;                   /* raised inexact flag */
    }
  return (jx >= 0) ? z : -z;
}
예제 #18
0
long double
__kernel_sinl(long double x, long double y, int iy)
{
  long double absx, h, l, z, sin_l, cos_l_m1;
  int index;

  absx = fabsl (x);
  if (absx < 0.1484375L)
    {
      /* Argument is small enough to approximate it by a Chebyshev
	 polynomial of degree 17.  */
      if (absx < 0x1p-33L)
	{
	  if (fabsl (x) < LDBL_MIN)
	    {
	      long double force_underflow = x * x;
	      math_force_eval (force_underflow);
	    }
	  if (!((int)x)) return x;	/* generate inexact */
	}
      z = x * x;
      return x + (x * (z*(SIN1+z*(SIN2+z*(SIN3+z*(SIN4+
		       z*(SIN5+z*(SIN6+z*(SIN7+z*SIN8)))))))));
    }
  else
    {
      /* So that we don't have to use too large polynomial,  we find
	 l and h such that x = l + h,  where fabsl(l) <= 1.0/256 with 83
	 possible values for h.  We look up cosl(h) and sinl(h) in
	 pre-computed tables,  compute cosl(l) and sinl(l) using a
	 Chebyshev polynomial of degree 10(11) and compute
	 sinl(h+l) = sinl(h)cosl(l) + cosl(h)sinl(l).  */
      index = (int) (128 * (absx - (0.1484375L - 1.0L / 256.0L)));
      h = 0.1484375L + index / 128.0;
      index *= 4;
      if (iy)
	l = (x < 0 ? -y : y) - (h - absx);
      else
	l = absx - h;
      z = l * l;
      sin_l = l*(ONE+z*(SSIN1+z*(SSIN2+z*(SSIN3+z*(SSIN4+z*SSIN5)))));
      cos_l_m1 = z*(SCOS1+z*(SCOS2+z*(SCOS3+z*(SCOS4+z*SCOS5))));
      z = __sincosl_table [index + SINCOSL_SIN_HI]
	  + (__sincosl_table [index + SINCOSL_SIN_LO]
	     + (__sincosl_table [index + SINCOSL_SIN_HI] * cos_l_m1)
	     + (__sincosl_table [index + SINCOSL_COS_HI] * sin_l));
      return (x < 0) ? -z : z;
    }
}
예제 #19
0
파일: s_atanf.c 프로젝트: AubrCool/glibc
float __atanf(float x)
{
	float w,s1,s2,z;
	int32_t ix,hx,id;

	GET_FLOAT_WORD(hx,x);
	ix = hx&0x7fffffff;
	if(ix>=0x50800000) {	/* if |x| >= 2^34 */
	    if(ix>0x7f800000)
		return x+x;		/* NaN */
	    if(hx>0) return  atanhi[3]+atanlo[3];
	    else     return -atanhi[3]-atanlo[3];
	} if (ix < 0x3ee00000) {	/* |x| < 0.4375 */
	    if (ix < 0x31000000) {	/* |x| < 2^-29 */
		if (fabsf (x) < FLT_MIN)
		  {
		    float force_underflow = x * x;
		    math_force_eval (force_underflow);
		  }
		if(huge+x>one) return x;	/* raise inexact */
	    }
	    id = -1;
	} else {
	x = fabsf(x);
	if (ix < 0x3f980000) {		/* |x| < 1.1875 */
	    if (ix < 0x3f300000) {	/* 7/16 <=|x|<11/16 */
		id = 0; x = ((float)2.0*x-one)/((float)2.0+x);
	    } else {			/* 11/16<=|x|< 19/16 */
		id = 1; x  = (x-one)/(x+one);
	    }
	} else {
	    if (ix < 0x401c0000) {	/* |x| < 2.4375 */
		id = 2; x  = (x-(float)1.5)/(one+(float)1.5*x);
	    } else {			/* 2.4375 <= |x| < 2^66 */
		id = 3; x  = -(float)1.0/x;
	    }
	}}
    /* end of argument reduction */
	z = x*x;
	w = z*z;
    /* break sum from i=0 to 10 aT[i]z**(i+1) into odd and even poly */
	s1 = z*(aT[0]+w*(aT[2]+w*(aT[4]+w*(aT[6]+w*(aT[8]+w*aT[10])))));
	s2 = w*(aT[1]+w*(aT[3]+w*(aT[5]+w*(aT[7]+w*aT[9]))));
	if (id<0) return x - x*(s1+s2);
	else {
	    z = atanhi[id] - ((x*(s1+s2) - atanlo[id]) - x);
	    return (hx<0)? -z:z;
	}
}
예제 #20
0
파일: e_sinhl.c 프로젝트: hwoarang/glibc
long double
__ieee754_sinhl(long double x)
{
	long double t,w,h;
	u_int32_t jx,ix,i0,i1;

    /* Words of |x|. */
	GET_LDOUBLE_WORDS(jx,i0,i1,x);
	ix = jx&0x7fff;

    /* x is INF or NaN */
	if(__builtin_expect(ix==0x7fff, 0)) return x+x;

	h = 0.5;
	if (jx & 0x8000) h = -h;
    /* |x| in [0,25], return sign(x)*0.5*(E+E/(E+1))) */
	if (ix < 0x4003 || (ix == 0x4003 && i0 <= 0xc8000000)) { /* |x|<25 */
	    if (ix<0x3fdf) {		/* |x|<2**-32 */
		if (fabsl (x) < LDBL_MIN)
		  {
		    long double force_underflow = x * x;
		    math_force_eval (force_underflow);
		  }
		if(shuge+x>one) return x;/* sinh(tiny) = tiny with inexact */
	    }
	    t = __expm1l(fabsl(x));
	    if(ix<0x3fff) return h*(2.0*t-t*t/(t+one));
	    return h*(t+t/(t+one));
	}

    /* |x| in [25, log(maxdouble)] return 0.5*exp(|x|) */
	if (ix < 0x400c || (ix == 0x400c && i0 < 0xb17217f7))
		return h*__ieee754_expl(fabsl(x));

    /* |x| in [log(maxdouble), overflowthreshold] */
	if (ix<0x400c || (ix == 0x400c && (i0 < 0xb174ddc0
					   || (i0 == 0xb174ddc0
					       && i1 <= 0x31aec0ea)))) {
	    w = __ieee754_expl(0.5*fabsl(x));
	    t = h*w;
	    return t*w;
	}

    /* |x| > overflowthreshold, sinhl(x) overflow */
	return x*shuge;
}
예제 #21
0
float
__ieee754_j0f(float x)
{
	float z, s,c,ss,cc,r,u,v;
	int32_t hx,ix;

	GET_FLOAT_WORD(hx,x);
	ix = hx&0x7fffffff;
	if(ix>=0x7f800000) return one/(x*x);
	x = fabsf(x);
	if(ix >= 0x40000000) {	/* |x| >= 2.0 */
		__sincosf (x, &s, &c);
		ss = s-c;
		cc = s+c;
		if(ix<0x7f000000) {  /* make sure x+x not overflow */
		    z = -__cosf(x+x);
		    if ((s*c)<zero) cc = z/ss;
		    else	    ss = z/cc;
		}
	/*
	 * j0(x) = 1/sqrt(pi) * (P(0,x)*cc - Q(0,x)*ss) / sqrt(x)
	 * y0(x) = 1/sqrt(pi) * (P(0,x)*ss + Q(0,x)*cc) / sqrt(x)
	 */
		if(ix>0x48000000) z = (invsqrtpi*cc)/__ieee754_sqrtf(x);
		else {
		    u = pzerof(x); v = qzerof(x);
		    z = invsqrtpi*(u*cc-v*ss)/__ieee754_sqrtf(x);
		}
		return z;
	}
	if(ix<0x39000000) {	/* |x| < 2**-13 */
	    math_force_eval(huge+x);		/* raise inexact if x != 0 */
	    if(ix<0x32000000) return one;	/* |x|<2**-27 */
	    else	      return one - (float)0.25*x*x;
	}
	z = x*x;
	r =  z*(R02+z*(R03+z*(R04+z*R05)));
	s =  one+z*(S01+z*(S02+z*(S03+z*S04)));
	if(ix < 0x3F800000) {	/* |x| < 1.00 */
	    return one + z*((float)-0.25+(r/s));
	} else {
	    u = (float)0.5*x;
	    return((one+u)*(one-u)+z*(r/s));
	}
}
예제 #22
0
double
__asinh (double x)
{
  double w;
  int32_t hx, ix;
  GET_HIGH_WORD (hx, x);
  ix = hx & 0x7fffffff;
  if (__glibc_unlikely (ix < 0x3e300000))                  /* |x|<2**-28 */
    {
      if (fabs (x) < DBL_MIN)
	{
	  double force_underflow = x * x;
	  math_force_eval (force_underflow);
	}
      if (huge + x > one)
	return x;                       /* return x inexact except 0 */
    }
  if (__glibc_unlikely (ix > 0x41b00000))                  /* |x| > 2**28 */
    {
      if (ix >= 0x7ff00000)
	return x + x;                           /* x is inf or NaN */
      w = __ieee754_log (fabs (x)) + ln2;
    }
  else
    {
      double xa = fabs (x);
      if (ix > 0x40000000)              /* 2**28 > |x| > 2.0 */
	{
	  w = __ieee754_log (2.0 * xa + one / (__ieee754_sqrt (xa * xa + one) +
              xa));
	}
      else                      /* 2.0 > |x| > 2**-28 */
	{
	  double t = xa * xa;
	  w = __log1p (xa + t / (one + __ieee754_sqrt (one + t)));
	}
    }
  return __copysign (w, x);
}
예제 #23
0
파일: s_fma.c 프로젝트: jnaulet/glibc
double
__fma (double x, double y, double z)
{
  union ieee754_double u, v, w;
  int adjust = 0;
  u.d = x;
  v.d = y;
  w.d = z;
  if (__builtin_expect (u.ieee.exponent + v.ieee.exponent
			>= 0x7ff + IEEE754_DOUBLE_BIAS - DBL_MANT_DIG, 0)
      || __builtin_expect (u.ieee.exponent >= 0x7ff - DBL_MANT_DIG, 0)
      || __builtin_expect (v.ieee.exponent >= 0x7ff - DBL_MANT_DIG, 0)
      || __builtin_expect (w.ieee.exponent >= 0x7ff - DBL_MANT_DIG, 0)
      || __builtin_expect (u.ieee.exponent + v.ieee.exponent
			   <= IEEE754_DOUBLE_BIAS + DBL_MANT_DIG, 0))
    {
      /* If z is Inf, but x and y are finite, the result should be
	 z rather than NaN.  */
      if (w.ieee.exponent == 0x7ff
	  && u.ieee.exponent != 0x7ff
	  && v.ieee.exponent != 0x7ff)
	return (z + x) + y;
      /* If z is zero and x are y are nonzero, compute the result
	 as x * y to avoid the wrong sign of a zero result if x * y
	 underflows to 0.  */
      if (z == 0 && x != 0 && y != 0)
	return x * y;
      /* If x or y or z is Inf/NaN, or if x * y is zero, compute as
	 x * y + z.  */
      if (u.ieee.exponent == 0x7ff
	  || v.ieee.exponent == 0x7ff
	  || w.ieee.exponent == 0x7ff
	  || x == 0
	  || y == 0)
	return x * y + z;
      /* If fma will certainly overflow, compute as x * y.  */
      if (u.ieee.exponent + v.ieee.exponent > 0x7ff + IEEE754_DOUBLE_BIAS)
	return x * y;
      /* If x * y is less than 1/4 of DBL_DENORM_MIN, neither the
	 result nor whether there is underflow depends on its exact
	 value, only on its sign.  */
      if (u.ieee.exponent + v.ieee.exponent
	  < IEEE754_DOUBLE_BIAS - DBL_MANT_DIG - 2)
	{
	  int neg = u.ieee.negative ^ v.ieee.negative;
	  double tiny = neg ? -0x1p-1074 : 0x1p-1074;
	  if (w.ieee.exponent >= 3)
	    return tiny + z;
	  /* Scaling up, adding TINY and scaling down produces the
	     correct result, because in round-to-nearest mode adding
	     TINY has no effect and in other modes double rounding is
	     harmless.  But it may not produce required underflow
	     exceptions.  */
	  v.d = z * 0x1p54 + tiny;
	  if (TININESS_AFTER_ROUNDING
	      ? v.ieee.exponent < 55
	      : (w.ieee.exponent == 0
		 || (w.ieee.exponent == 1
		     && w.ieee.negative != neg
		     && w.ieee.mantissa1 == 0
		     && w.ieee.mantissa0 == 0)))
	    {
	      volatile double force_underflow = x * y;
	      (void) force_underflow;
	    }
	  return v.d * 0x1p-54;
	}
      if (u.ieee.exponent + v.ieee.exponent
	  >= 0x7ff + IEEE754_DOUBLE_BIAS - DBL_MANT_DIG)
	{
	  /* Compute 1p-53 times smaller result and multiply
	     at the end.  */
	  if (u.ieee.exponent > v.ieee.exponent)
	    u.ieee.exponent -= DBL_MANT_DIG;
	  else
	    v.ieee.exponent -= DBL_MANT_DIG;
	  /* If x + y exponent is very large and z exponent is very small,
	     it doesn't matter if we don't adjust it.  */
	  if (w.ieee.exponent > DBL_MANT_DIG)
	    w.ieee.exponent -= DBL_MANT_DIG;
	  adjust = 1;
	}
      else if (w.ieee.exponent >= 0x7ff - DBL_MANT_DIG)
	{
	  /* Similarly.
	     If z exponent is very large and x and y exponents are
	     very small, adjust them up to avoid spurious underflows,
	     rather than down.  */
	  if (u.ieee.exponent + v.ieee.exponent
	      <= IEEE754_DOUBLE_BIAS + DBL_MANT_DIG)
	    {
	      if (u.ieee.exponent > v.ieee.exponent)
		u.ieee.exponent += 2 * DBL_MANT_DIG + 2;
	      else
		v.ieee.exponent += 2 * DBL_MANT_DIG + 2;
	    }
	  else if (u.ieee.exponent > v.ieee.exponent)
	    {
	      if (u.ieee.exponent > DBL_MANT_DIG)
		u.ieee.exponent -= DBL_MANT_DIG;
	    }
	  else if (v.ieee.exponent > DBL_MANT_DIG)
	    v.ieee.exponent -= DBL_MANT_DIG;
	  w.ieee.exponent -= DBL_MANT_DIG;
	  adjust = 1;
	}
      else if (u.ieee.exponent >= 0x7ff - DBL_MANT_DIG)
	{
	  u.ieee.exponent -= DBL_MANT_DIG;
	  if (v.ieee.exponent)
	    v.ieee.exponent += DBL_MANT_DIG;
	  else
	    v.d *= 0x1p53;
	}
      else if (v.ieee.exponent >= 0x7ff - DBL_MANT_DIG)
	{
	  v.ieee.exponent -= DBL_MANT_DIG;
	  if (u.ieee.exponent)
	    u.ieee.exponent += DBL_MANT_DIG;
	  else
	    u.d *= 0x1p53;
	}
      else /* if (u.ieee.exponent + v.ieee.exponent
		  <= IEEE754_DOUBLE_BIAS + DBL_MANT_DIG) */
	{
	  if (u.ieee.exponent > v.ieee.exponent)
	    u.ieee.exponent += 2 * DBL_MANT_DIG + 2;
	  else
	    v.ieee.exponent += 2 * DBL_MANT_DIG + 2;
	  if (w.ieee.exponent <= 4 * DBL_MANT_DIG + 6)
	    {
	      if (w.ieee.exponent)
		w.ieee.exponent += 2 * DBL_MANT_DIG + 2;
	      else
		w.d *= 0x1p108;
	      adjust = -1;
	    }
	  /* Otherwise x * y should just affect inexact
	     and nothing else.  */
	}
      x = u.d;
      y = v.d;
      z = w.d;
    }

  /* Ensure correct sign of exact 0 + 0.  */
  if (__glibc_unlikely ((x == 0 || y == 0) && z == 0))
    return x * y + z;

  fenv_t env;
  libc_feholdexcept_setround (&env, FE_TONEAREST);

  /* Multiplication m1 + m2 = x * y using Dekker's algorithm.  */
#define C ((1 << (DBL_MANT_DIG + 1) / 2) + 1)
  double x1 = x * C;
  double y1 = y * C;
  double m1 = x * y;
  x1 = (x - x1) + x1;
  y1 = (y - y1) + y1;
  double x2 = x - x1;
  double y2 = y - y1;
  double m2 = (((x1 * y1 - m1) + x1 * y2) + x2 * y1) + x2 * y2;

  /* Addition a1 + a2 = z + m1 using Knuth's algorithm.  */
  double a1 = z + m1;
  double t1 = a1 - z;
  double t2 = a1 - t1;
  t1 = m1 - t1;
  t2 = z - t2;
  double a2 = t1 + t2;
  /* Ensure the arithmetic is not scheduled after feclearexcept call.  */
  math_force_eval (m2);
  math_force_eval (a2);
  feclearexcept (FE_INEXACT);

  /* If the result is an exact zero, ensure it has the correct sign.  */
  if (a1 == 0 && m2 == 0)
    {
      libc_feupdateenv (&env);
      /* Ensure that round-to-nearest value of z + m1 is not reused.  */
      z = math_opt_barrier (z);
      return z + m1;
    }

  libc_fesetround (FE_TOWARDZERO);

  /* Perform m2 + a2 addition with round to odd.  */
  u.d = a2 + m2;

  if (__glibc_unlikely (adjust < 0))
    {
      if ((u.ieee.mantissa1 & 1) == 0)
	u.ieee.mantissa1 |= libc_fetestexcept (FE_INEXACT) != 0;
      v.d = a1 + u.d;
      /* Ensure the addition is not scheduled after fetestexcept call.  */
      math_force_eval (v.d);
    }

  /* Reset rounding mode and test for inexact simultaneously.  */
  int j = libc_feupdateenv_test (&env, FE_INEXACT) != 0;

  if (__glibc_likely (adjust == 0))
    {
      if ((u.ieee.mantissa1 & 1) == 0 && u.ieee.exponent != 0x7ff)
	u.ieee.mantissa1 |= j;
      /* Result is a1 + u.d.  */
      return a1 + u.d;
    }
  else if (__glibc_likely (adjust > 0))
    {
      if ((u.ieee.mantissa1 & 1) == 0 && u.ieee.exponent != 0x7ff)
	u.ieee.mantissa1 |= j;
      /* Result is a1 + u.d, scaled up.  */
      return (a1 + u.d) * 0x1p53;
    }
  else
    {
      /* If a1 + u.d is exact, the only rounding happens during
	 scaling down.  */
      if (j == 0)
	return v.d * 0x1p-108;
      /* If result rounded to zero is not subnormal, no double
	 rounding will occur.  */
      if (v.ieee.exponent > 108)
	return (a1 + u.d) * 0x1p-108;
      /* If v.d * 0x1p-108 with round to zero is a subnormal above
	 or equal to DBL_MIN / 2, then v.d * 0x1p-108 shifts mantissa
	 down just by 1 bit, which means v.ieee.mantissa1 |= j would
	 change the round bit, not sticky or guard bit.
	 v.d * 0x1p-108 never normalizes by shifting up,
	 so round bit plus sticky bit should be already enough
	 for proper rounding.  */
      if (v.ieee.exponent == 108)
	{
	  /* If the exponent would be in the normal range when
	     rounding to normal precision with unbounded exponent
	     range, the exact result is known and spurious underflows
	     must be avoided on systems detecting tininess after
	     rounding.  */
	  if (TININESS_AFTER_ROUNDING)
	    {
	      w.d = a1 + u.d;
	      if (w.ieee.exponent == 109)
		return w.d * 0x1p-108;
	    }
	  /* v.ieee.mantissa1 & 2 is LSB bit of the result before rounding,
	     v.ieee.mantissa1 & 1 is the round bit and j is our sticky
	     bit.  */
	  w.d = 0.0;
	  w.ieee.mantissa1 = ((v.ieee.mantissa1 & 3) << 1) | j;
	  w.ieee.negative = v.ieee.negative;
	  v.ieee.mantissa1 &= ~3U;
	  v.d *= 0x1p-108;
	  w.d *= 0x1p-2;
	  return v.d + w.d;
	}
      v.ieee.mantissa1 |= j;
      return v.d * 0x1p-108;
    }
}
예제 #24
0
long double __nextafterl(long double x, long double y)
{
	int32_t ix,iy,esx,esy;
	uint32_t hx,hy,lx,ly;

	GET_LDOUBLE_WORDS(esx,hx,lx,x);
	GET_LDOUBLE_WORDS(esy,hy,ly,y);
	ix = esx&0x7fff;		/* |x| */
	iy = esy&0x7fff;		/* |y| */

	if(((ix==0x7fff)&&((hx&0x7fffffff)|lx)!=0) ||   /* x is nan */
	   ((iy==0x7fff)&&((hy&0x7fffffff)|ly)!=0))     /* y is nan */
	   return x+y;
	if(x==y) return y;		/* x=y, return y */
	if((ix|hx|lx)==0) {			/* x == 0 */
	    SET_LDOUBLE_WORDS(x,esy&0x8000,0,1);/* return +-minsubnormal */
	    y = x*x;
	    math_force_eval (y);		/* raise underflow flag */
	    return x;
	}
	if(esx>=0) {			/* x > 0 */
	    if(esx>esy||((esx==esy) && (hx>hy||((hx==hy)&&(lx>ly))))) {
	      /* x > y, x -= ulp */
		if(lx==0) {
		    if (ix != 0 && hx == 0x80000000) hx = 0;
		    if (hx==0) esx -= 1;
		    hx -= 1;
		}
		lx -= 1;
	    } else {				/* x < y, x += ulp */
		lx += 1;
		if(lx==0) {
		    hx += 1;
		    if (hx==0) {
			hx = 0x80000000;
			esx += 1;
		    }
		}
	    }
	} else {				/* x < 0 */
	    if(esy>=0||esx>esy||((esx==esy) && (hx>hy||((hx==hy)&&(lx>ly))))){
	      /* x < y, x -= ulp */
		if(lx==0) {
		    if (ix != 0 && hx == 0x80000000) hx = 0;
		    if (hx==0) esx -= 1;
		    hx -= 1;
		}
		lx -= 1;
	    } else {				/* x > y, x += ulp */
		lx += 1;
		if(lx==0) {
		    hx += 1;
		    if (hx==0) {
			hx = 0x80000000;
			esx += 1;
		    }
		}
	    }
	}
	esy = esx&0x7fff;
	if(esy==0x7fff) {
	    long double u = x + x;	/* overflow  */
	    math_force_eval (u);
	    __set_errno (ERANGE);
	}
	if(esy==0 && (hx & 0x80000000) == 0) { /* underflow */
	    y = x*x;
	    math_force_eval (y);		/* raise underflow flag */
	    __set_errno (ERANGE);
	}
	SET_LDOUBLE_WORDS(x,esx,hx,lx);
	return x;
}
예제 #25
0
파일: e_asinl.c 프로젝트: AubrCool/glibc
long double
__ieee754_asinl (long double x)
{
  long double t, w, p, q, c, r, s;
  int32_t ix, sign, flag;
  ieee854_long_double_shape_type u;

  flag = 0;
  u.value = x;
  sign = u.parts32.w0;
  ix = sign & 0x7fffffff;
  u.parts32.w0 = ix;    /* |x| */
  if (ix >= 0x3fff0000)	/* |x|>= 1 */
    {
      if (ix == 0x3fff0000
	  && (u.parts32.w1 | u.parts32.w2 | u.parts32.w3) == 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 (ix < 0x3ffe0000) /* |x| < 0.5 */
    {
      if (ix < 0x3fc60000) /* |x| < 2**-57 */
	{
	  if (fabsl (x) < LDBL_MIN)
	    {
	      long double force_underflow = x * x;
	      math_force_eval (force_underflow);
	    }
	  if (huge + x > one)
	    return x;		/* return x with inexact if x!=0 */
	}
      else
	{
	  t = x * x;
	  /* Mark to use pS, qS later on.  */
	  flag = 1;
	}
    }
  else if (ix < 0x3ffe4000) /* 0.625 */
    {
      t = u.value - 0.5625;
      p = ((((((((((rS10 * t
		    + rS9) * t
		   + rS8) * t
		  + rS7) * t
		 + rS6) * t
		+ rS5) * t
	       + rS4) * t
	      + rS3) * t
	     + rS2) * t
	    + rS1) * t
	   + rS0) * t;

      q = ((((((((( t
		    + sS9) * t
		  + sS8) * t
		 + sS7) * t
		+ sS6) * t
	       + sS5) * t
	      + sS4) * t
	     + sS3) * t
	    + sS2) * t
	   + sS1) * t
	+ sS0;
      t = asinr5625 + p / q;
      if ((sign & 0x80000000) == 0)
	return t;
      else
	return -t;
    }
  else
    {
      /* 1 > |x| >= 0.625 */
      w = one - u.value;
      t = w * 0.5;
    }

  p = (((((((((pS9 * t
	       + pS8) * t
	      + pS7) * t
	     + pS6) * t
	    + pS5) * t
	   + pS4) * t
	  + pS3) * t
	 + pS2) * t
	+ pS1) * t
       + pS0) * t;

  q = (((((((( t
	      + qS8) * t
	     + qS7) * t
	    + qS6) * t
	   + qS5) * t
	  + qS4) * t
	 + qS3) * t
	+ qS2) * t
       + qS1) * t
    + qS0;

  if (flag) /* 2^-57 < |x| < 0.5 */
    {
      w = p / q;
      return x + x * w;
    }

  s = __ieee754_sqrtl (t);
  if (ix >= 0x3ffef333) /* |x| > 0.975 */
    {
      w = p / q;
      t = pio2_hi - (2.0 * (s + s * w) - pio2_lo);
    }
  else
    {
      u.value = s;
      u.parts32.w3 = 0;
      u.parts32.w2 = 0;
      w = u.value;
      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);
    }

  if ((sign & 0x80000000) == 0)
    return t;
  else
    return -t;
}
예제 #26
0
파일: s_clog10f.c 프로젝트: AubrCool/glibc
__complex__ float
__clog10f (__complex__ float x)
{
  __complex__ float result;
  int rcls = fpclassify (__real__ x);
  int icls = fpclassify (__imag__ x);

  if (__glibc_unlikely (rcls == FP_ZERO && icls == FP_ZERO))
    {
      /* Real and imaginary part are 0.0.  */
      __imag__ result = signbit (__real__ x) ? M_PI_LOG10Ef : 0.0;
      __imag__ result = __copysignf (__imag__ result, __imag__ x);
      /* Yes, the following line raises an exception.  */
      __real__ result = -1.0 / fabsf (__real__ x);
    }
  else if (__glibc_likely (rcls != FP_NAN && icls != FP_NAN))
    {
      /* Neither real nor imaginary part is NaN.  */
      float absx = fabsf (__real__ x), absy = fabsf (__imag__ x);
      int scale = 0;

      if (absx < absy)
	{
	  float t = absx;
	  absx = absy;
	  absy = t;
	}

      if (absx > FLT_MAX / 2.0f)
	{
	  scale = -1;
	  absx = __scalbnf (absx, scale);
	  absy = (absy >= FLT_MIN * 2.0f ? __scalbnf (absy, scale) : 0.0f);
	}
      else if (absx < FLT_MIN && absy < FLT_MIN)
	{
	  scale = FLT_MANT_DIG;
	  absx = __scalbnf (absx, scale);
	  absy = __scalbnf (absy, scale);
	}

      if (absx == 1.0f && scale == 0)
	{
	  float absy2 = absy * absy;
	  if (absy2 <= FLT_MIN * 2.0f * (float) M_LN10)
	    {
	      float force_underflow = absy2 * absy2;
	      __real__ result = absy2 * ((float) M_LOG10E / 2.0f);
	      math_force_eval (force_underflow);
	    }
	  else
	    __real__ result = __log1pf (absy2) * ((float) M_LOG10E / 2.0f);
	}
      else if (absx > 1.0f && absx < 2.0f && absy < 1.0f && scale == 0)
	{
	  float d2m1 = (absx - 1.0f) * (absx + 1.0f);
	  if (absy >= FLT_EPSILON)
	    d2m1 += absy * absy;
	  __real__ result = __log1pf (d2m1) * ((float) M_LOG10E / 2.0f);
	}
      else if (absx < 1.0f
	       && absx >= 0.75f
	       && absy < FLT_EPSILON / 2.0f
	       && scale == 0)
	{
	  float d2m1 = (absx - 1.0f) * (absx + 1.0f);
	  __real__ result = __log1pf (d2m1) * ((float) M_LOG10E / 2.0f);
	}
      else if (absx < 1.0f && (absx >= 0.75f || absy >= 0.5f) && scale == 0)
	{
	  float d2m1 = __x2y2m1f (absx, absy);
	  __real__ result = __log1pf (d2m1) * ((float) M_LOG10E / 2.0f);
	}
      else
	{
	  float d = __ieee754_hypotf (absx, absy);
	  __real__ result = __ieee754_log10f (d) - scale * M_LOG10_2f;
	}

      __imag__ result = M_LOG10E * __ieee754_atan2f (__imag__ x, __real__ x);
    }
  else
    {
      __imag__ result = __nanf ("");
      if (rcls == FP_INFINITE || icls == FP_INFINITE)
	/* Real or imaginary part is infinite.  */
	__real__ result = HUGE_VALF;
      else
	__real__ result = __nanf ("");
    }

  return result;
}
예제 #27
0
파일: e_j1.c 프로젝트: KubaKaszycki/kklibc
double
__ieee754_j1 (double x)
{
  double z, s, c, ss, cc, r, u, v, y, r1, r2, s1, s2, s3, z2, z4;
  int32_t hx, ix;

  GET_HIGH_WORD (hx, x);
  ix = hx & 0x7fffffff;
  if (__glibc_unlikely (ix >= 0x7ff00000))
    return one / x;
  y = fabs (x);
  if (ix >= 0x40000000)         /* |x| >= 2.0 */
    {
      __sincos (y, &s, &c);
      ss = -s - c;
      cc = s - c;
      if (ix < 0x7fe00000)           /* make sure y+y not overflow */
	{
	  z = __cos (y + y);
	  if ((s * c) > zero)
	    cc = z / ss;
	  else
	    ss = z / cc;
	}
      /*
       * j1(x) = 1/sqrt(pi) * (P(1,x)*cc - Q(1,x)*ss) / sqrt(x)
       * y1(x) = 1/sqrt(pi) * (P(1,x)*ss + Q(1,x)*cc) / sqrt(x)
       */
      if (ix > 0x48000000)
	z = (invsqrtpi * cc) / __ieee754_sqrt (y);
      else
	{
	  u = pone (y); v = qone (y);
	  z = invsqrtpi * (u * cc - v * ss) / __ieee754_sqrt (y);
	}
      if (hx < 0)
	return -z;
      else
	return z;
    }
  if (__glibc_unlikely (ix < 0x3e400000))                  /* |x|<2**-27 */
    {
      if (huge + x > one)                 /* inexact if x!=0 necessary */
	{
	  double ret = 0.5 * x;
	  if (fabs (ret) < DBL_MIN)
	    {
	      double force_underflow = ret * ret;
	      math_force_eval (force_underflow);
	    }
	  return ret;
	}
    }
  z = x * x;
  r1 = z * R[0]; z2 = z * z;
  r2 = R[1] + z * R[2]; z4 = z2 * z2;
  r = r1 + z2 * r2 + z4 * R[3];
  r *= x;
  s1 = one + z * S[1];
  s2 = S[2] + z * S[3];
  s3 = S[4] + z * S[5];
  s = s1 + z2 * s2 + z4 * s3;
  return (x * 0.5 + r / s);
}
npy_longdouble _nextl(npy_longdouble x, int p)
{
    npy_int64 hx,ihx,ilx;
    npy_uint64 lx;

    GET_LDOUBLE_WORDS64(hx, lx, x);
    ihx = hx & 0x7fffffffffffffffLL;      /* |hx| */
    ilx = lx & 0x7fffffffffffffffLL;      /* |lx| */

    if(((ihx & 0x7ff0000000000000LL)==0x7ff0000000000000LL)&&
       ((ihx & 0x000fffffffffffffLL)!=0)) {
        return x; /* signal the nan */
    }
    if(ihx == 0 && ilx == 0) {          /* x == 0 */
        npy_longdouble u;
        SET_LDOUBLE_WORDS64(x, p, 0ULL);/* return +-minsubnormal */
        u = x * x;
        if (u == x) {
            return u;
        } else {
            return x;           /* raise underflow flag */
        }
    }

    npy_longdouble u;
    if(p < 0) { /* p < 0, x -= ulp */
        if((hx==0xffefffffffffffffLL)&&(lx==0xfc8ffffffffffffeLL))
            return x+x; /* overflow, return -inf */
        if (hx >= 0x7ff0000000000000LL) {
            SET_LDOUBLE_WORDS64(u,0x7fefffffffffffffLL,0x7c8ffffffffffffeLL);
            return u;
        }
        if(ihx <= 0x0360000000000000LL) {  /* x <= LDBL_MIN */
            u = math_opt_barrier (x);
            x -= LDBL_TRUE_MIN;
            if (ihx < 0x0360000000000000LL
                    || (hx > 0 && (npy_int64) lx <= 0)
                    || (hx < 0 && (npy_int64) lx > 1)) {
                u = u * u;
                math_force_eval (u);        /* raise underflow flag */
            }
            return x;
        }
        if (ihx < 0x06a0000000000000LL) { /* ulp will denormal */
            SET_LDOUBLE_WORDS64(u,(hx&0x7ff0000000000000LL),0ULL);
            u *= 0x1.0000000000000p-105L;
        } else
            SET_LDOUBLE_WORDS64(u,(hx&0x7ff0000000000000LL)-0x0690000000000000LL,0ULL);
        return x - u;
    } else {                /* p >= 0, x += ulp */
        if((hx==0x7fefffffffffffffLL)&&(lx==0x7c8ffffffffffffeLL))
            return x+x; /* overflow, return +inf */
        if ((npy_uint64) hx >= 0xfff0000000000000ULL) {
            SET_LDOUBLE_WORDS64(u,0xffefffffffffffffLL,0xfc8ffffffffffffeLL);
            return u;
        }
        if(ihx <= 0x0360000000000000LL) {  /* x <= LDBL_MIN */
            u = math_opt_barrier (x);
            x += LDBL_TRUE_MIN;
            if (ihx < 0x0360000000000000LL
                    || (hx > 0 && (npy_int64) lx < 0 && lx != 0x8000000000000001LL)
                    || (hx < 0 && (npy_int64) lx >= 0)) {
                u = u * u;
                math_force_eval (u);        /* raise underflow flag */
            }
            if (x == 0.0L)  /* handle negative LDBL_TRUE_MIN case */
                x = -0.0L;
            return x;
        }
        if (ihx < 0x06a0000000000000LL) { /* ulp will denormal */
            SET_LDOUBLE_WORDS64(u,(hx&0x7ff0000000000000LL),0ULL);
            u *= 0x1.0000000000000p-105L;
        } else
            SET_LDOUBLE_WORDS64(u,(hx&0x7ff0000000000000LL)-0x0690000000000000LL,0ULL);
        return x + u;
    }
}
예제 #29
0
long double
__kernel_standard_l (long double x, long double y, int type)
{
  double dx, dy;
  struct exception exc;
  fenv_t env;

  feholdexcept (&env);
  dx = x;
  dy = y;
  math_force_eval (dx);
  math_force_eval (dy);
  fesetenv (&env);

  switch (type)
    {
    case 221:
      /* powl (x, y) overflow.  */
      exc.arg1 = dx;
      exc.arg2 = dy;
      exc.type = OVERFLOW;
      exc.name = (char *) "powl";
      if (_LIB_VERSION == _SVID_)
	{
	  exc.retval = HUGE;
	  y *= 0.5;
	  if (x < zero && __rintl (y) != y)
	    exc.retval = -HUGE;
	}
      else
	{
	  exc.retval = HUGE_VAL;
	  y *= 0.5;
	  if (x < zero && __rintl (y) != y)
	    exc.retval = -HUGE_VAL;
	}
      if (_LIB_VERSION == _POSIX_)
	__set_errno (ERANGE);
      else if (!matherr (&exc))
	__set_errno (ERANGE);
      return exc.retval;

    case 222:
      /* powl (x, y) underflow.  */
      exc.arg1 = dx;
      exc.arg2 = dy;
      exc.type = UNDERFLOW;
      exc.name = (char *) "powl";
      exc.retval = zero;
      y *= 0.5;
      if (x < zero && __rintl (y) != y)
	exc.retval = -zero;
      if (_LIB_VERSION == _POSIX_)
	__set_errno (ERANGE);
      else if (!matherr (&exc))
	__set_errno (ERANGE);
      return exc.retval;

    default:
      return __kernel_standard (dx, dy, type);
    }
}
예제 #30
0
long double
__nearbyintl (long double x)
{
  fenv_t env;
  static const long double TWO52 = 4503599627370496.0L;
  union ibm_extended_long_double u;
  u.d = x;

  if (fabs (u.dd[0]) < TWO52)
    {
      double high = u.dd[0];
      feholdexcept (&env);
      if (high > 0.0)
	{
	  high += TWO52;
	  high -= TWO52;
          if (high == -0.0) high = 0.0;
	}
      else if (high < 0.0)
	{
	  high -= TWO52;
	  high += TWO52;
          if (high == 0.0) high = -0.0;
	}
      u.dd[0] = high;
      u.dd[1] = 0.0;
      math_force_eval (u.dd[0]);
      math_force_eval (u.dd[1]);
      fesetenv (&env);
    }
  else if (fabs (u.dd[1]) < TWO52 && u.dd[1] != 0.0)
    {
      double high, low, tau;
      /* In this case we have to round the low double and handle any
         adjustment to the high double that may be caused by rounding
         (up).  This is complicated by the fact that the high double
         may already be rounded and the low double may have the
         opposite sign to compensate.  */
      feholdexcept (&env);
      if (u.dd[0] > 0.0)
	{
	  if (u.dd[1] > 0.0)
	    {
	      /* If the high/low doubles are the same sign then simply
	         round the low double.  */
	      high = u.dd[0];
	      low = u.dd[1];
	    }
	  else if (u.dd[1] < 0.0)
	    {
	      /* Else the high double is pre rounded and we need to
	         adjust for that.  */

	      tau = __nextafter (u.dd[0], 0.0);
	      tau = (u.dd[0] - tau) * 2.0;
	      high = u.dd[0] - tau;
	      low = u.dd[1] + tau;
	    }
	  low += TWO52;
	  low -= TWO52;
	}
      else if (u.dd[0] < 0.0)
	{
	  if (u.dd[1] < 0.0)
	    {
	      /* If the high/low doubles are the same sign then simply
	         round the low double.  */
	      high = u.dd[0];
	      low = u.dd[1];
	    }
	  else if (u.dd[1] > 0.0)
	    {
	      /* Else the high double is pre rounded and we need to
	         adjust for that.  */
	      tau = __nextafter (u.dd[0], 0.0);
	      tau = (u.dd[0] - tau) * 2.0;
	      high = u.dd[0] - tau;
	      low = u.dd[1] + tau;
	    }
	  low = TWO52 - low;
	  low = -(low - TWO52);
	}
      u.dd[0] = high + low;
      u.dd[1] = high - u.dd[0] + low;
      math_force_eval (u.dd[0]);
      math_force_eval (u.dd[1]);
      fesetenv (&env);
    }

  return u.d;
}