예제 #1
0
double
__ieee754_gamma_r (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.  */
  int32_t hx;
  u_int32_t lx;

  EXTRACT_WORDS (hx, lx, x);

  if (((hx & 0x7fffffff) | lx) == 0)
    {
      /* Return value for x == 0 is NaN with invalid exception.  */
      *signgamp = 0;
      return x / x;
    }
  if (hx < 0 && (u_int32_t) hx < 0xfff00000 && __rint (x) == x)
    {
      /* Return value for integer x < 0 is NaN with invalid exception.  */
      *signgamp = 0;
      return (x - x) / (x - x);
    }
  if ((unsigned int) hx == 0xfff00000 && lx==0)
    {
      /* x == -Inf.  According to ISO this is NaN.  */
      *signgamp = 0;
      return x - x;
    }

  /* XXX FIXME.  */
  return __ieee754_exp (__ieee754_lgamma_r (x, signgamp));
}
예제 #2
0
	double lgamma_r(double x, int *signgamp) /* wrapper lgamma_r */
{
#ifdef _IEEE_LIBM
	return __ieee754_lgamma_r(x,signgamp);
#else
        double y;
        y = __ieee754_lgamma_r(x,signgamp);
        if(_LIB_VERSION == _IEEE_) return y;
        if(!finite(y)&&finite(x)) {
            if(floor(x)==x&&x<=0.0)
                return __kernel_standard(x,x,15); /* lgamma pole */
            else
                return __kernel_standard(x,x,14); /* lgamma overflow */
        } else
            return y;
#endif
}
예제 #3
0
파일: e_lgamma.c 프로젝트: iblis17/openlibm
DLLEXPORT double
__ieee754_lgamma(double x)
{
#ifdef OPENLIBM_ONLY_THREAD_SAFE
	int signgam;
#endif

	return __ieee754_lgamma_r(x,&signgam);
}
예제 #4
0
파일: math.c 프로젝트: JamesLinus/inferno
void
Math_lgamma(void *fp)
{
	F_Math_lgamma *f;

	f = fp;

	f->ret->t1 = __ieee754_lgamma_r(f->x, &f->ret->t0);
}
예제 #5
0
파일: w_gamma.c 프로젝트: efidroid/edk2
double
gamma(double x)
{
#ifdef _IEEE_LIBM
	return __ieee754_lgamma_r(x,&signgam);
#else
        double y;
        y = __ieee754_lgamma_r(x,&signgam);
        if(_LIB_VERSION == _IEEE_) return y;
        if(!finite(y)&&finite(x)) {
            if(floor(x)==x&&x<=0.0)
                return __kernel_standard(x,x,41); /* gamma pole */
            else
                return __kernel_standard(x,x,40); /* gamma overflow */
        } else
            return y;
#endif
}
예제 #6
0
double lgamma_r(double x, int *signgamp)
{
	double y = __ieee754_lgamma_r(x, signgamp);
	if (_LIB_VERSION == _IEEE_)
		return y;
	if (!isfinite(y) && isfinite(x)) {
		if (floor(x) == x && x <= 0.0)
			return __kernel_standard(x, x, 15); /* lgamma pole */
		return __kernel_standard(x, x, 14); /* lgamma overflow */
	}
	return y;
}
예제 #7
0
파일: w_lgamma_r.c 프로젝트: imbaqian/glibc
double
__lgamma_r(double x, int *signgamp)
{
    double y = __ieee754_lgamma_r(x,signgamp);
    if(__builtin_expect(!__finite(y), 0)
            && __finite(x) && _LIB_VERSION != _IEEE_)
        return __kernel_standard(x, x,
                                 __floor(x)==x&&x<=0.0
                                 ? 15 /* lgamma pole */
                                 : 14); /* lgamma overflow */

    return y;
}
예제 #8
0
double
__lgamma(double x)
{
    int local_signgam = 0;
    double y = __ieee754_lgamma_r(x, &local_signgam);

    //if(__builtin_expect(!__finite(y), 0)
    //   && __finite(x) && _LIB_VERSION != _IEEE_)
    //	return __kernel_standard(x, x,
    //				 __floor(x)==x&&x<=0.0
    //				 ? 15 /* lgamma pole */
    //				 : 14); /* lgamma overflow */
    
    return y;
}
예제 #9
0
파일: w_lgamma.c 프로젝트: AdvancedC/glibc
double
__lgamma(double x)
{
	int local_signgam = 0;
	double y = __ieee754_lgamma_r(x,
				      _LIB_VERSION != _ISOC_
				      /* ISO C99 does not define the
					 global variable.  */
				      ? &signgam
				      : &local_signgam);
	if(__builtin_expect(!__finite(y), 0)
	   && __finite(x) && _LIB_VERSION != _IEEE_)
		return __kernel_standard(x, x,
					 __floor(x)==x&&x<=0.0
					 ? 15 /* lgamma pole */
					 : 14); /* lgamma overflow */

	return y;
}
예제 #10
0
double
__ieee754_gamma_r(double x, int *signgamp)
{
	return __ieee754_lgamma_r(x,signgamp);
}
예제 #11
0
double
__ieee754_lgamma(double x)
{
	return __ieee754_lgamma_r(x,&signgam);
}
예제 #12
0
파일: e_gamma_r.c 프로젝트: AubrCool/glibc
static double
gamma_positive (double x, int *exp2_adj)
{
  int local_signgam;
  if (x < 0.5)
    {
      *exp2_adj = 0;
      return __ieee754_exp (__ieee754_lgamma_r (x + 1, &local_signgam)) / x;
    }
  else if (x <= 1.5)
    {
      *exp2_adj = 0;
      return __ieee754_exp (__ieee754_lgamma_r (x, &local_signgam));
    }
  else if (x < 6.5)
    {
      /* Adjust into the range for using exp (lgamma).  */
      *exp2_adj = 0;
      double n = __ceil (x - 1.5);
      double x_adj = x - n;
      double eps;
      double prod = __gamma_product (x_adj, 0, n, &eps);
      return (__ieee754_exp (__ieee754_lgamma_r (x_adj, &local_signgam))
	      * prod * (1.0 + eps));
    }
  else
    {
      double eps = 0;
      double x_eps = 0;
      double x_adj = x;
      double prod = 1;
      if (x < 12.0)
	{
	  /* Adjust into the range for applying Stirling's
	     approximation.  */
	  double n = __ceil (12.0 - x);
#if FLT_EVAL_METHOD != 0
	  volatile
#endif
	  double x_tmp = x + n;
	  x_adj = x_tmp;
	  x_eps = (x - (x_adj - n));
	  prod = __gamma_product (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.  */
      double exp_adj = -eps;
      double x_adj_int = __round (x_adj);
      double x_adj_frac = x_adj - x_adj_int;
      int x_adj_log2;
      double x_adj_mant = __frexp (x_adj, &x_adj_log2);
      if (x_adj_mant < M_SQRT1_2)
	{
	  x_adj_log2--;
	  x_adj_mant *= 2.0;
	}
      *exp2_adj = x_adj_log2 * (int) x_adj_int;
      double ret = (__ieee754_pow (x_adj_mant, x_adj)
		    * __ieee754_exp2 (x_adj_log2 * x_adj_frac)
		    * __ieee754_exp (-x_adj)
		    * __ieee754_sqrt (2 * M_PI / x_adj)
		    / prod);
      exp_adj += x_eps * __ieee754_log (x);
      double bsum = gamma_coeff[NCOEFF - 1];
      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 * __expm1 (exp_adj);
    }
}
예제 #13
0
파일: lgamma.cpp 프로젝트: chenbk85/QOR
    //------------------------------------------------------------------------------
    double Cmath::lgamma( double x )
    {
        double y;
        struct fexception exc;
        y = __ieee754_lgamma_r( x, &m_isigngam );
        if( m_fdlib_version == _IEEE_ )
        {
            return y;
        }

        if( !finite( y ) && finite( x ) )
        {
#	ifndef HUGE_VAL
#		define HUGE_VAL inf
            double inf = 0.0;
            set_high_word( inf, 0x7ff00000 ); // set inf to infinite
#	endif
            exc.name = "lgamma";
            exc.err = 0;
            exc.arg1 = x;
            exc.arg2 = x;
            if( m_fdlib_version == _SVID_ )
            {
                exc.retval = Huge();
            }
            else
            {
                exc.retval = HUGE_VAL;
            }

            if( floor( x ) == x && x <= 0.0 )
            {
                // lgamma(-integer)
                exc.type = EX_SING;
                if( m_fdlib_version == _POSIX_ )
                {
                    errno = EDOM;
                }
                else if( !matherr( &exc ) )
                {
                    errno = EDOM;
                }

            }
            else
            {
                // lgamma(finite) overflow
                exc.type = EX_OVERFLOW;
                if( m_fdlib_version == _POSIX_ )
                {
                    errno = ERANGE;
                }
                else if( !matherr( &exc ) )
                {
                    errno = ERANGE;
                }
            }

            if( exc.err != 0 )
            {
                errno = exc.err;
            }
            return exc.retval;
        }
        else
        {
            return y;
        }
    }