예제 #1
0
파일: e_sinhl.c 프로젝트: dreal/tai
long double
__ieee754_sinhl (long double x)
{
  long double t, w, h;
  u_int32_t jx, ix;
  ieee854_long_double_shape_type u;

  /* Words of |x|. */
  u.value = x;
  jx = u.parts32.w0;
  ix = jx & 0x7fffffff;

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

  h = 0.5;
  if (jx & 0x80000000)
    h = -h;

  /* Absolute value of x.  */
  u.parts32.w0 = ix;

  /* |x| in [0,40], return sign(x)*0.5*(E+E/(E+1))) */
  if (ix <= 0x40044000)
    {
      if (ix < 0x3fc60000) /* |x| < 2^-57 */
	if (shuge + x > one)
	  return x;		/* sinh(tiny) = tiny with inexact */
      t = __expm1l (u.value);
      if (ix < 0x3fff0000)
	return h * (2.0 * t - t * t / (t + one));
      return h * (t + t / (t + one));
    }

  /* |x| in [40, log(maxdouble)] return 0.5*exp(|x|) */
  if (ix <= 0x400c62e3) /* 11356.375 */
    return h * __ieee754_expl (u.value);

  /* |x| in [log(maxdouble), overflowthreshold]
     Overflow threshold is log(2 * maxdouble).  */
  if (u.value <= ovf_thresh)
    {
      w = __ieee754_expl (0.5 * u.value);
      t = h * w;
      return t * w;
    }

  /* |x| > overflowthreshold, sinhl(x) overflow */
  return x * shuge;
}
예제 #2
0
long double
__ieee754_gammal_r (long double x, int *signgamp)
{
  /* We don't have a real gamma implementation now.  We'll use lgamma
     and the exp function.  But due to the required boundary
     conditions we must check some values separately.  */
  u_int32_t es, hx, lx;

  GET_LDOUBLE_WORDS (es, hx, lx, x);

  if (((es & 0x7fff) | hx | lx) == 0)
    {
      /* Return value for x == 0 is NaN with invalid exception.  */
      *signgamp = 0;
      return x / x;
    }
  if (es == 0xffffffff && ((hx & 0x7fffffff) | lx) == 0)
    {
      /* x == -Inf.  According to ISO this is NaN.  */
      *signgamp = 0;
      return x - x;
    }
  if ((es & 0x7fff) == 0x7fff && ((hx & 0x7fffffff) | lx) != 0)
    /* NaN, return it.  */
    return x;
  if ((es & 0x8000) != 0 && x < 0xffffffff && __rintl (x) == x)
    {
      /* Return value for integer x < 0 is NaN with invalid exception.  */
      *signgamp = 0;
      return (x - x) / (x - x);
    }

  /* XXX FIXME.  */
  return __ieee754_expl (__ieee754_lgammal_r (x, signgamp));
}
예제 #3
0
/*Converting from double precision to Multi-precision and calculating  e^x */
double __slowexp(double x) {
#ifdef NO_LONG_DOUBLE
  double w,z,res,eps=3.0e-26;
  int p;
  mp_no mpx, mpy, mpz,mpw,mpeps,mpcor;

  p=6;
  __dbl_mp(x,&mpx,p); /* Convert a double precision number  x               */
                    /* into a multiple precision number mpx with prec. p. */
  __mpexp(&mpx, &mpy, p); /* Multi-Precision exponential function */
  __dbl_mp(eps,&mpeps,p);
  __mul(&mpeps,&mpy,&mpcor,p);
  __add(&mpy,&mpcor,&mpw,p);
  __sub(&mpy,&mpcor,&mpz,p);
  __mp_dbl(&mpw, &w, p);
  __mp_dbl(&mpz, &z, p);
  if (w == z) return w;
  else  {                   /* if calculating is not exactly   */
    p = 32;
    __dbl_mp(x,&mpx,p);
    __mpexp(&mpx, &mpy, p);
    __mp_dbl(&mpy, &res, p);
    return res;
  }
#else
  return (double) __ieee754_expl((long double)x);
#endif
}
예제 #4
0
long double
__ieee754_gammal_r (long double x, int *signgamp)
{
  /* We don't have a real gamma implementation now.  We'll use lgamma
     and the exp function.  But due to the required boundary
     conditions we must check some values separately.  */
  int64_t hx;
  u_int64_t lx;

  GET_LDOUBLE_WORDS64 (hx, lx, x);

  if (((hx | lx) & 0x7fffffffffffffffLL) == 0)
    {
      /* Return value for x == 0 is Inf with divide by zero exception.  */
      *signgamp = 0;
      return 1.0 / x;
    }
  if (hx < 0 && (u_int64_t) hx < 0xfff0000000000000ULL && __rintl (x) == x)
    {
      /* Return value for integer x < 0 is NaN with invalid exception.  */
      *signgamp = 0;
      return (x - x) / (x - x);
    }
  if (hx == 0xfff0000000000000ULL)
    {
      /* x == -Inf.  According to ISO this is NaN.  */
      *signgamp = 0;
      return x - x;
    }

  /* XXX FIXME.  */
  return __ieee754_expl (__ieee754_lgammal_r (x, signgamp));
}
예제 #5
0
long double
__ieee754_exp2l (long double x)
{
  if (__glibc_likely (isless (x, (long double) LDBL_MAX_EXP)))
    {
      if (__builtin_expect (isgreaterequal (x, (long double) (LDBL_MIN_EXP
							      - LDBL_MANT_DIG
							      - 1)), 1))
	{
	  int intx = (int) x;
	  long double fractx = x - intx;
	  if (fabsl (fractx) < LDBL_EPSILON / 4.0L)
	    return __scalbnl (1.0L + fractx, intx);
	  return __scalbnl (__ieee754_expl (M_LN2l * fractx), intx);
	}
      else
	{
	  /* Underflow or exact zero.  */
	  if (isinf (x))
	    return 0;
	  else
	    return LDBL_MIN * LDBL_MIN;
	}
    }
  else
    /* Infinity, NaN or overflow.  */
    return LDBL_MAX * x;
}
예제 #6
0
파일: slowexp.c 프로젝트: gf-chen/glibc
/*Converting from double precision to Multi-precision and calculating  e^x */
double
SECTION
__slowexp (double x)
{
#ifndef USE_LONG_DOUBLE_FOR_MP
  double w, z, res, eps = 3.0e-26;
  int p;
  mp_no mpx, mpy, mpz, mpw, mpeps, mpcor;

  /* Use the multiple precision __MPEXP function to compute the exponential
     First at 144 bits and if it is not accurate enough, at 768 bits.  */
  p = 6;
  __dbl_mp (x, &mpx, p);
  __mpexp (&mpx, &mpy, p);
  __dbl_mp (eps, &mpeps, p);
  __mul (&mpeps, &mpy, &mpcor, p);
  __add (&mpy, &mpcor, &mpw, p);
  __sub (&mpy, &mpcor, &mpz, p);
  __mp_dbl (&mpw, &w, p);
  __mp_dbl (&mpz, &z, p);
  if (w == z)
    return w;
  else
    {
      p = 32;
      __dbl_mp (x, &mpx, p);
      __mpexp (&mpx, &mpy, p);
      __mp_dbl (&mpy, &res, p);
      return res;
    }
#else
  return (double) __ieee754_expl((long double)x);
#endif
}
예제 #7
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;
}
예제 #8
0
파일: w_expl.c 프로젝트: AubrCool/glibc
/* wrapper expl */
long double
__expl (long double x)
{
  long double z = __ieee754_expl (x);
  if (__builtin_expect (!__finitel (z) || z == 0, 0)
      && __finitel (x) && _LIB_VERSION != _IEEE_)
    return __kernel_standard_l (x, x, 206 + !!__signbitl (x));

  return z;
}
예제 #9
0
long double
__ieee754_exp10l (long double arg)
{
  if (__finitel (arg) && arg < LDBL_MIN_10_EXP - LDBL_DIG - 10)
    return LDBL_MIN * LDBL_MIN;
  else
    /* This is a very stupid and inprecise implementation.  It'll get
       replaced sometime (soon?).  */
    return __ieee754_expl (M_LN10l * arg);
}
예제 #10
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;
}
예제 #11
0
파일: e_coshl.c 프로젝트: dreal/tai
long double
__ieee754_coshl (long double x)
{
	long double t,w;
	int64_t ix;

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

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

    /* |x| in [0,0.5*ln2], return 1+expm1(|x|)^2/(2*exp(|x|)) */
	if(ix<0x3fd62e42fefa39efLL) {
	    t = __expm1l(fabsl(x));
	    w = one+t;
	    if (ix<0x3c80000000000000LL) return w;	/* cosh(tiny) = 1 */
	    return one+(t*t)/(w+w);
	}

    /* |x| in [0.5*ln2,22], return (exp(|x|)+1/exp(|x|)/2; */
	if (ix < 0x4036000000000000LL) {
		t = __ieee754_expl(fabsl(x));
		return half*t+half/t;
	}

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

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

    /* |x| > overflowthresold, cosh(x) overflow */
	return huge*huge;
}
예제 #12
0
파일: e_exp10l.c 프로젝트: AubrCool/glibc
long double
__ieee754_exp10l (long double arg)
{
  union ibm_extended_long_double u;
  long double arg_high, arg_low;
  long double exp_high, exp_low;

  if (!__finitel (arg))
    return __ieee754_expl (arg);
  if (arg < LDBL_MIN_10_EXP - LDBL_DIG - 10)
    return LDBL_MIN * LDBL_MIN;
  else if (arg > LDBL_MAX_10_EXP + 1)
    return LDBL_MAX * LDBL_MAX;
  else if (fabsl (arg) < 0x1p-109L)
    return 1.0L;

  u.ld = arg;
  arg_high = u.d[0].d;
  arg_low = u.d[1].d;
  exp_high = arg_high * log10_high;
  exp_low = arg_high * log10_low + arg_low * M_LN10l;
  return __ieee754_expl (exp_high) * __ieee754_expl (exp_low);
}
예제 #13
0
long double
__ieee754_exp10l (long double arg)
{
  ieee854_long_double_shape_type u;
  long double arg_high, arg_low;
  long double exp_high, exp_low;

  if (!isfinite (arg))
    return __ieee754_expl (arg);
  if (arg < LDBL_MIN_10_EXP - LDBL_DIG - 10)
    return LDBL_MIN * LDBL_MIN;
  else if (arg > LDBL_MAX_10_EXP + 1)
    return LDBL_MAX * LDBL_MAX;
  else if (fabsl (arg) < 0x1p-116L)
    return 1.0L;

  u.value = arg;
  u.parts64.lsw &= 0xfe00000000000000LL;
  arg_high = u.value;
  arg_low = arg - arg_high;
  exp_high = arg_high * log10_high;
  exp_low = arg_high * log10_low + arg_low * M_LN10l;
  return __ieee754_expl (exp_high) * __ieee754_expl (exp_low);
}
예제 #14
0
파일: slowexp.c 프로젝트: riscv/riscv-glibc
/*Converting from double precision to Multi-precision and calculating  e^x */
double
SECTION
__slowexp (double x)
{
#ifndef USE_LONG_DOUBLE_FOR_MP
  double w, z, res, eps = 3.0e-26;
  int p;
  mp_no mpx, mpy, mpz, mpw, mpeps, mpcor;

  /* Use the multiple precision __MPEXP function to compute the exponential
     First at 144 bits and if it is not accurate enough, at 768 bits.  */
  p = 6;
  __dbl_mp (x, &mpx, p);
  __mpexp (&mpx, &mpy, p);
  __dbl_mp (eps, &mpeps, p);
  __mul (&mpeps, &mpy, &mpcor, p);
  __add (&mpy, &mpcor, &mpw, p);
  __sub (&mpy, &mpcor, &mpz, p);
  __mp_dbl (&mpw, &w, p);
  __mp_dbl (&mpz, &z, p);
  if (w == z)
    {
      /* Track how often we get to the slow exp code plus
	 its input/output values.  */
      LIBC_PROBE (slowexp_p6, 2, &x, &w);
      return w;
    }
  else
    {
      p = 32;
      __dbl_mp (x, &mpx, p);
      __mpexp (&mpx, &mpy, p);
      __mp_dbl (&mpy, &res, p);

      /* Track how often we get to the uber-slow exp code plus
	 its input/output values.  */
      LIBC_PROBE (slowexp_p32, 2, &x, &res);
      return res;
    }
#else
  return (double) __ieee754_expl((long double)x);
#endif
}
예제 #15
0
__complex__ long double
__ccoshl (__complex__ long double x)
{
  __complex__ long double retval;
  int rcls = fpclassify (__real__ x);
  int icls = fpclassify (__imag__ x);

  if (__glibc_likely (rcls >= FP_ZERO))
    {
      /* Real part is finite.  */
      if (__glibc_likely (icls >= FP_ZERO))
	{
	  /* Imaginary part is finite.  */
	  const int t = (int) ((LDBL_MAX_EXP - 1) * M_LN2l);
	  long double sinix, cosix;

	  if (__glibc_likely (fabsl (__imag__ x) > LDBL_MIN))
	    {
	      __sincosl (__imag__ x, &sinix, &cosix);
	    }
	  else
	    {
	      sinix = __imag__ x;
	      cosix = 1.0;
	    }

	  if (fabsl (__real__ x) > t)
	    {
	      long double exp_t = __ieee754_expl (t);
	      long double rx = fabsl (__real__ x);
	      if (signbit (__real__ x))
		sinix = -sinix;
	      rx -= t;
	      sinix *= exp_t / 2.0L;
	      cosix *= exp_t / 2.0L;
	      if (rx > t)
		{
		  rx -= t;
		  sinix *= exp_t;
		  cosix *= exp_t;
		}
	      if (rx > t)
		{
		  /* Overflow (original real part of x > 3t).  */
		  __real__ retval = LDBL_MAX * cosix;
		  __imag__ retval = LDBL_MAX * sinix;
		}
	      else
		{
		  long double exp_val = __ieee754_expl (rx);
		  __real__ retval = exp_val * cosix;
		  __imag__ retval = exp_val * sinix;
		}
	    }
	  else
	    {
	      __real__ retval = __ieee754_coshl (__real__ x) * cosix;
	      __imag__ retval = __ieee754_sinhl (__real__ x) * sinix;
	    }

	  math_check_force_underflow_complex (retval);
	}
      else
	{
	  __imag__ retval = __real__ x == 0.0 ? 0.0 : __nanl ("");
	  __real__ retval = __nanl ("") + __nanl ("");

	  if (icls == FP_INFINITE)
	    feraiseexcept (FE_INVALID);
	}
    }
  else if (rcls == FP_INFINITE)
    {
      /* Real part is infinite.  */
      if (__glibc_likely (icls > FP_ZERO))
	{
	  /* Imaginary part is finite.  */
	  long double sinix, cosix;

	  if (__glibc_likely (fabsl (__imag__ x) > LDBL_MIN))
	    {
	      __sincosl (__imag__ x, &sinix, &cosix);
	    }
	  else
	    {
	      sinix = __imag__ x;
	      cosix = 1.0;
	    }

	  __real__ retval = __copysignl (HUGE_VALL, cosix);
	  __imag__ retval = (__copysignl (HUGE_VALL, sinix)
			     * __copysignl (1.0, __real__ x));
	}
      else if (icls == FP_ZERO)
	{
	  /* Imaginary part is 0.0.  */
	  __real__ retval = HUGE_VALL;
	  __imag__ retval = __imag__ x * __copysignl (1.0, __real__ x);
	}
      else
	{
	  /* The addition raises the invalid exception.  */
	  __real__ retval = HUGE_VALL;
	  __imag__ retval = __nanl ("") + __nanl ("");

	  if (icls == FP_INFINITE)
	    feraiseexcept (FE_INVALID);
	}
    }
  else
    {
      __real__ retval = __nanl ("");
      __imag__ retval = __imag__ x == 0.0 ? __imag__ x : __nanl ("");
    }

  return retval;
}
예제 #16
0
파일: s_cexpl.c 프로젝트: AdvancedC/glibc
__complex__ long double
__cexpl (__complex__ long double x)
{
  __complex__ long double retval;
  int rcls = fpclassify (__real__ x);
  int icls = fpclassify (__imag__ x);

  if (__builtin_expect (rcls >= FP_ZERO, 1))
    {
      /* Real part is finite.  */
      if (__builtin_expect (icls >= FP_ZERO, 1))
	{
	  /* Imaginary part is finite.  */
	  const int t = (int) ((LDBL_MAX_EXP - 1) * M_LN2l);
	  long double sinix, cosix;

	  __sincosl (__imag__ x, &sinix, &cosix);

	  if (__real__ x > t)
	    {
	      long double exp_t = __ieee754_expl (t);
	      __real__ x -= t;
	      sinix *= exp_t;
	      cosix *= exp_t;
	      if (__real__ x > t)
		{
		  __real__ x -= t;
		  sinix *= exp_t;
		  cosix *= exp_t;
		}
	    }
	  if (__real__ x > t)
	    {
	      /* Overflow (original real part of x > 3t).  */
	      __real__ retval = LDBL_MAX * cosix;
	      __imag__ retval = LDBL_MAX * sinix;
	    }
	  else
	    {
	      long double exp_val = __ieee754_expl (__real__ x);
	      __real__ retval = exp_val * cosix;
	      __imag__ retval = exp_val * sinix;
	    }
	}
      else
	{
	  /* If the imaginary part is +-inf or NaN and the real part
	     is not +-inf the result is NaN + iNaN.  */
	  __real__ retval = __nanl ("");
	  __imag__ retval = __nanl ("");

	  feraiseexcept (FE_INVALID);
	}
    }
  else if (__builtin_expect (rcls == FP_INFINITE, 1))
    {
      /* Real part is infinite.  */
      if (__builtin_expect (icls >= FP_ZERO, 1))
	{
	  /* Imaginary part is finite.  */
	  long double value = signbit (__real__ x) ? 0.0 : HUGE_VALL;

	  if (icls == FP_ZERO)
	    {
	      /* Imaginary part is 0.0.  */
	      __real__ retval = value;
	      __imag__ retval = __imag__ x;
	    }
	  else
	    {
	      long double sinix, cosix;

	      __sincosl (__imag__ x, &sinix, &cosix);

	      __real__ retval = __copysignl (value, cosix);
	      __imag__ retval = __copysignl (value, sinix);
	    }
	}
      else if (signbit (__real__ x) == 0)
	{
	  __real__ retval = HUGE_VALL;
	  __imag__ retval = __nanl ("");

	  if (icls == FP_INFINITE)
	    feraiseexcept (FE_INVALID);
	}
      else
	{
	  __real__ retval = 0.0;
	  __imag__ retval = __copysignl (0.0, __imag__ x);
	}
    }
  else
    {
      /* If the real part is NaN the result is NaN + iNaN.  */
      __real__ retval = __nanl ("");
      __imag__ retval = __nanl ("");

      if (rcls != FP_NAN || icls != FP_NAN)
	feraiseexcept (FE_INVALID);
    }

  return retval;
}
예제 #17
0
파일: s_ctanl.c 프로젝트: wilseypa/llamaOS
__complex__ long double
__ctanl (__complex__ long double x)
{
  __complex__ long double res;

  if (__builtin_expect (!isfinite (__real__ x) || !isfinite (__imag__ x), 0))
    {
      if (__isinf_nsl (__imag__ x))
	{
	  __real__ res = __copysignl (0.0, __real__ x);
	  __imag__ res = __copysignl (1.0, __imag__ x);
	}
      else if (__real__ x == 0.0)
	{
	  res = x;
	}
      else
	{
	  __real__ res = __nanl ("");
	  __imag__ res = __nanl ("");

	  if (__isinf_nsl (__real__ x))
	    feraiseexcept (FE_INVALID);
	}
    }
  else
    {
      long double sinrx, cosrx;
      long double den;
      const int t = (int) ((LDBL_MAX_EXP - 1) * M_LN2l / 2);
      int rcls = fpclassify (__real__ x);

      /* tan(x+iy) = (sin(2x) + i*sinh(2y))/(cos(2x) + cosh(2y))
	 = (sin(x)*cos(x) + i*sinh(y)*cosh(y)/(cos(x)^2 + sinh(y)^2). */

      if (__builtin_expect (rcls != FP_SUBNORMAL, 1))
	{
	  __sincosl (__real__ x, &sinrx, &cosrx);
	}
      else
	{
	  sinrx = __real__ x;
	  cosrx = 1.0;
	}

      if (fabsl (__imag__ x) > t)
	{
	  /* Avoid intermediate overflow when the real part of the
	     result may be subnormal.  Ignoring negligible terms, the
	     imaginary part is +/- 1, the real part is
	     sin(x)*cos(x)/sinh(y)^2 = 4*sin(x)*cos(x)/exp(2y).  */
	  long double exp_2t = __ieee754_expl (2 * t);

	  __imag__ res = __copysignl (1.0, __imag__ x);
	  __real__ res = 4 * sinrx * cosrx;
	  __imag__ x = fabsl (__imag__ x);
	  __imag__ x -= t;
	  __real__ res /= exp_2t;
	  if (__imag__ x > t)
	    {
	      /* Underflow (original imaginary part of x has absolute
		 value > 2t).  */
	      __real__ res /= exp_2t;
	    }
	  else
	    __real__ res /= __ieee754_expl (2 * __imag__ x);
	}
      else
	{
	  long double sinhix, coshix;
	  if (fabsl (__imag__ x) > LDBL_MIN)
	    {
	      sinhix = __ieee754_sinhl (__imag__ x);
	      coshix = __ieee754_coshl (__imag__ x);
	    }
	  else
	    {
	      sinhix = __imag__ x;
	      coshix = 1.0L;
	    }

	  if (fabsl (sinhix) > fabsl (cosrx) * LDBL_EPSILON)
	    den = cosrx * cosrx + sinhix * sinhix;
	  else
	    den = cosrx * cosrx;
	  __real__ res = sinrx * cosrx / den;
	  __imag__ res = sinhix * coshix / den;
	}
    }

  return res;
}
예제 #18
0
파일: s_csinl.c 프로젝트: Xilinx/eglibc
__complex__ long double
__csinl (__complex__ long double x)
{
  __complex__ long double retval;
  int negate = signbit (__real__ x);
  int rcls = fpclassify (__real__ x);
  int icls = fpclassify (__imag__ x);

  __real__ x = fabsl (__real__ x);

  if (__builtin_expect (icls >= FP_ZERO, 1))
    {
      /* Imaginary part is finite.  */
      if (__builtin_expect (rcls >= FP_ZERO, 1))
	{
	  /* Real part is finite.  */
	  const int t = (int) ((LDBL_MAX_EXP - 1) * M_LN2l);
	  long double sinix, cosix;

	  if (__builtin_expect (rcls != FP_SUBNORMAL, 1))
	    {
	      __sincosl (__real__ x, &sinix, &cosix);
	    }
	  else
	    {
	      sinix = __real__ x;
	      cosix = 1.0;
	    }

	  if (fabsl (__imag__ x) > t)
	    {
	      long double exp_t = __ieee754_expl (t);
	      long double ix = fabsl (__imag__ x);
	      if (signbit (__imag__ x))
		cosix = -cosix;
	      ix -= t;
	      sinix *= exp_t / 2.0L;
	      cosix *= exp_t / 2.0L;
	      if (ix > t)
		{
		  ix -= t;
		  sinix *= exp_t;
		  cosix *= exp_t;
		}
	      if (ix > t)
		{
		  /* Overflow (original imaginary part of x > 3t).  */
		  __real__ retval = LDBL_MAX * sinix;
		  __imag__ retval = LDBL_MAX * cosix;
		}
	      else
		{
		  long double exp_val = __ieee754_expl (ix);
		  __real__ retval = exp_val * sinix;
		  __imag__ retval = exp_val * cosix;
		}
	    }
	  else
	    {
	      __real__ retval = __ieee754_coshl (__imag__ x) * sinix;
	      __imag__ retval = __ieee754_sinhl (__imag__ x) * cosix;
	    }

	  if (negate)
	    __real__ retval = -__real__ retval;

	  if (fabsl (__real__ retval) < LDBL_MIN)
	    {
	      volatile long double force_underflow
		= __real__ retval * __real__ retval;
	      (void) force_underflow;
	    }
	  if (fabsl (__imag__ retval) < LDBL_MIN)
	    {
	      volatile long double force_underflow
		= __imag__ retval * __imag__ retval;
	      (void) force_underflow;
	    }
	}
      else
	{
	  if (icls == FP_ZERO)
	    {
	      /* Imaginary part is 0.0.  */
	      __real__ retval = __nanl ("");
	      __imag__ retval = __imag__ x;

	      if (rcls == FP_INFINITE)
		feraiseexcept (FE_INVALID);
	    }
	  else
	    {
	      __real__ retval = __nanl ("");
	      __imag__ retval = __nanl ("");

	      feraiseexcept (FE_INVALID);
	    }
	}
    }
  else if (icls == FP_INFINITE)
    {
      /* Imaginary part is infinite.  */
      if (rcls == FP_ZERO)
	{
	  /* Real part is 0.0.  */
	  __real__ retval = __copysignl (0.0, negate ? -1.0 : 1.0);
	  __imag__ retval = __imag__ x;
	}
      else if (rcls > FP_ZERO)
	{
	  /* Real part is finite.  */
	  long double sinix, cosix;

	  if (__builtin_expect (rcls != FP_SUBNORMAL, 1))
	    {
	      __sincosl (__real__ x, &sinix, &cosix);
	    }
	  else
	    {
	      sinix = __real__ x;
	      cosix = 1.0;
	    }

	  __real__ retval = __copysignl (HUGE_VALL, sinix);
	  __imag__ retval = __copysignl (HUGE_VALL, cosix);

	  if (negate)
	    __real__ retval = -__real__ retval;
	  if (signbit (__imag__ x))
	    __imag__ retval = -__imag__ retval;
	}
      else
	{
	  /* The addition raises the invalid exception.  */
	  __real__ retval = __nanl ("");
	  __imag__ retval = HUGE_VALL;

	  if (rcls == FP_INFINITE)
	    feraiseexcept (FE_INVALID);
	}
    }
  else
    {
      if (rcls == FP_ZERO)
	__real__ retval = __copysignl (0.0, negate ? -1.0 : 1.0);
      else
	__real__ retval = __nanl ("");
      __imag__ retval = __nanl ("");
    }

  return retval;
}
예제 #19
0
static long double
gammal_positive (long double x, int *exp2_adj)
{
  int local_signgam;
  if (x < 0.5L)
    {
      *exp2_adj = 0;
      return __ieee754_expl (__ieee754_lgammal_r (x + 1, &local_signgam)) / x;
    }
  else if (x <= 1.5L)
    {
      *exp2_adj = 0;
      return __ieee754_expl (__ieee754_lgammal_r (x, &local_signgam));
    }
  else if (x < 12.5L)
    {
      /* Adjust into the range for using exp (lgamma).  */
      *exp2_adj = 0;
      long double n = __ceill (x - 1.5L);
      long double x_adj = x - n;
      long double eps;
      long double prod = __gamma_productl (x_adj, 0, n, &eps);
      return (__ieee754_expl (__ieee754_lgammal_r (x_adj, &local_signgam))
	      * prod * (1.0L + eps));
    }
  else
    {
      long double eps = 0;
      long double x_eps = 0;
      long double x_adj = x;
      long double prod = 1;
      if (x < 24.0L)
	{
	  /* Adjust into the range for applying Stirling's
	     approximation.  */
	  long double n = __ceill (24.0L - x);
	  x_adj = x + n;
	  x_eps = (x - (x_adj - n));
	  prod = __gamma_productl (x_adj - n, x_eps, n, &eps);
	}
      /* The result is now gamma (X_ADJ + X_EPS) / (PROD * (1 + EPS)).
	 Compute gamma (X_ADJ + X_EPS) using Stirling's approximation,
	 starting by computing pow (X_ADJ, X_ADJ) with a power of 2
	 factored out.  */
      long double exp_adj = -eps;
      long double x_adj_int = __roundl (x_adj);
      long double x_adj_frac = x_adj - x_adj_int;
      int x_adj_log2;
      long double x_adj_mant = __frexpl (x_adj, &x_adj_log2);
      if (x_adj_mant < M_SQRT1_2l)
	{
	  x_adj_log2--;
	  x_adj_mant *= 2.0L;
	}
      *exp2_adj = x_adj_log2 * (int) x_adj_int;
      long double ret = (__ieee754_powl (x_adj_mant, x_adj)
			 * __ieee754_exp2l (x_adj_log2 * x_adj_frac)
			 * __ieee754_expl (-x_adj)
			 * __ieee754_sqrtl (2 * M_PIl / x_adj)
			 / prod);
      exp_adj += x_eps * __ieee754_logl (x_adj);
      long double bsum = gamma_coeff[NCOEFF - 1];
      long double x_adj2 = x_adj * x_adj;
      for (size_t i = 1; i <= NCOEFF - 1; i++)
	bsum = bsum / x_adj2 + gamma_coeff[NCOEFF - 1 - i];
      exp_adj += bsum / x_adj;
      return ret + ret * __expm1l (exp_adj);
    }
}
예제 #20
0
파일: s_cexpl.c 프로젝트: AubrCool/glibc
__complex__ long double
__cexpl (__complex__ long double x)
{
  __complex__ long double retval;
  int rcls = fpclassify (__real__ x);
  int icls = fpclassify (__imag__ x);

  if (__glibc_likely (rcls >= FP_ZERO))
    {
      /* Real part is finite.  */
      if (__glibc_likely (icls >= FP_ZERO))
	{
	  /* Imaginary part is finite.  */
	  const int t = (int) ((LDBL_MAX_EXP - 1) * M_LN2l);
	  long double sinix, cosix;

	  if (__glibc_likely (icls != FP_SUBNORMAL))
	    {
	      __sincosl (__imag__ x, &sinix, &cosix);
	    }
	  else
	    {
	      sinix = __imag__ x;
	      cosix = 1.0;
	    }

	  if (__real__ x > t)
	    {
	      long double exp_t = __ieee754_expl (t);
	      __real__ x -= t;
	      sinix *= exp_t;
	      cosix *= exp_t;
	      if (__real__ x > t)
		{
		  __real__ x -= t;
		  sinix *= exp_t;
		  cosix *= exp_t;
		}
	    }
	  if (__real__ x > t)
	    {
	      /* Overflow (original real part of x > 3t).  */
	      __real__ retval = LDBL_MAX * cosix;
	      __imag__ retval = LDBL_MAX * sinix;
	    }
	  else
	    {
	      long double exp_val = __ieee754_expl (__real__ x);
	      __real__ retval = exp_val * cosix;
	      __imag__ retval = exp_val * sinix;
	    }
	  if (fabsl (__real__ retval) < LDBL_MIN)
	    {
	      volatile long double force_underflow
		= __real__ retval * __real__ retval;
	      (void) force_underflow;
	    }
	  if (fabsl (__imag__ retval) < LDBL_MIN)
	    {
	      volatile long double force_underflow
		= __imag__ retval * __imag__ retval;
	      (void) force_underflow;
	    }
	}
      else
	{
	  /* If the imaginary part is +-inf or NaN and the real part
	     is not +-inf the result is NaN + iNaN.  */
	  __real__ retval = __nanl ("");
	  __imag__ retval = __nanl ("");

	  feraiseexcept (FE_INVALID);
	}
    }
  else if (__glibc_likely (rcls == FP_INFINITE))
    {
      /* Real part is infinite.  */
      if (__glibc_likely (icls >= FP_ZERO))
	{
	  /* Imaginary part is finite.  */
	  long double value = signbit (__real__ x) ? 0.0 : HUGE_VALL;

	  if (icls == FP_ZERO)
	    {
	      /* Imaginary part is 0.0.  */
	      __real__ retval = value;
	      __imag__ retval = __imag__ x;
	    }
	  else
	    {
	      long double sinix, cosix;

	      if (__glibc_likely (icls != FP_SUBNORMAL))
	        {
		  __sincosl (__imag__ x, &sinix, &cosix);
	        }
	      else
		{
		  sinix = __imag__ x;
		  cosix = 1.0;
		}

	      __real__ retval = __copysignl (value, cosix);
	      __imag__ retval = __copysignl (value, sinix);
	    }
	}
      else if (signbit (__real__ x) == 0)
	{
	  __real__ retval = HUGE_VALL;
	  __imag__ retval = __nanl ("");

	  if (icls == FP_INFINITE)
	    feraiseexcept (FE_INVALID);
	}
      else
	{
	  __real__ retval = 0.0;
	  __imag__ retval = __copysignl (0.0, __imag__ x);
	}
    }
  else
    {
      /* If the real part is NaN the result is NaN + iNaN unless the
	 imaginary part is zero.  */
      __real__ retval = __nanl ("");
      if (icls == FP_ZERO)
	__imag__ retval = __imag__ x;
      else
	{
	  __imag__ retval = __nanl ("");

	  if (rcls != FP_NAN || icls != FP_NAN)
	    feraiseexcept (FE_INVALID);
	}
    }

  return retval;
}
예제 #21
0
__complex__ long double
__ctanhl (__complex__ long double x)
{
  __complex__ long double res;

  if (!isfinite (__real__ x) || !isfinite (__imag__ x))
    {
      if (__isinfl (__real__ x))
	{
	  __real__ res = __copysignl (1.0L, __real__ x);
	  __imag__ res = __copysignl (0.0L, __imag__ x);
	}
      else if (__imag__ x == 0.0)
	{
	  res = x;
	}
      else
	{
	  __real__ res = __nanl ("");
	  __imag__ res = __nanl ("");

#ifdef FE_INVALID
	  if (__isinfl (__imag__ x))
	    feraiseexcept (FE_INVALID);
#endif
	}
    }
  else
    {
      long double sinix, cosix;
      long double den;
      const int t = (int) ((LDBL_MAX_EXP - 1) * M_LN2l / 2.0L);

      /* tanh(x+iy) = (sinh(2x) + i*sin(2y))/(cosh(2x) + cos(2y))
        = (sinh(x)*cosh(x) + i*sin(y)*cos(y))/(sinh(x)^2 + cos(y)^2).  */

      __sincosl (__imag__ x, &sinix, &cosix);

      if (fabsl (__real__ x) > t)
	{
	  /* Avoid intermediate overflow when the imaginary part of
	     the result may be subnormal.  Ignoring negligible terms,
	     the real part is +/- 1, the imaginary part is
	     sin(y)*cos(y)/sinh(x)^2 = 4*sin(y)*cos(y)/exp(2x).  */
	  long double exp_2t = __ieee754_expl (2 * t);
	  __real__ res = __copysignl (1.0L, __real__ x);
	  __imag__ res = 4 * sinix * cosix;
	  __real__ x = fabsl (__real__ x);
	  __real__ x -= t;
	  __imag__ res /= exp_2t;
	  if (__real__ x > t)
	    {
	      /* Underflow (original real part of x has absolute value
		 > 2t).  */
	      __imag__ res /= exp_2t;
	    }
	  else
	    __imag__ res /= __ieee754_expl (2.0L * __real__ x);
	}
      else
	{
	  long double sinhrx, coshrx;
	  if (fabs (__real__ x) > LDBL_MIN)
	    {
	      sinhrx = __ieee754_sinhl (__real__ x);
	      coshrx = __ieee754_coshl (__real__ x);
	    }
	  else
	    {
	      sinhrx = __real__ x;
	      coshrx = 1.0L;
	    }

	  if (fabsl (sinhrx) > fabsl (cosix) * ldbl_eps)
	    den = sinhrx * sinhrx + cosix * cosix;
	  else
	    den = cosix * cosix;
	  __real__ res = sinhrx * (coshrx / den);
	  __imag__ res = sinix * (cosix / den);
	}
      /* __gcc_qmul does not respect -0.0 so we need the following fixup.  */
      if ((__real__ res == 0.0L) && (__real__ x == 0.0L))
        __real__ res = __real__ x;

      if ((__real__ res == 0.0L) && (__imag__ x == 0.0L))
        __imag__ res = __imag__ x;
    }

  return res;
}