コード例 #1
0
ファイル: ilogbd32.c プロジェクト: gftg85/libdfp
_RETURN_TYPE
INTERNAL_FUNCTION_NAME (DEC_TYPE x)
{
  DEC_TYPE result;
  decContext context;
  decNumber dn_result;
  decNumber dn_x;
  decNumber dn_absx;
  decNumber dn_logx;
  decNumber dn_one;
  decNumber dn_cmp;
  enum rounding round;

  FUNC_CONVERT_TO_DN (&x, &dn_x);
  if (decNumberIsZero (&dn_x))
    {
      DFP_EXCEPT (FE_INVALID);
      DFP_ERRNO (EDOM);
      return _FBLOG0;
    }
  if (decNumberIsInfinite (&dn_x))
    {
      DFP_EXCEPT (FE_INVALID);
      DFP_ERRNO (EDOM);
      return decNumberIsNegative (&dn_x) ? _MIN_VALUE : _MAX_VALUE;
    }
  if (decNumberIsNaN (&dn_x))
    {
      DFP_EXCEPT (FE_INVALID);
      DFP_ERRNO (EDOM);
      return _FBLOGNAN;
    }

  decContextDefault (&context, DEFAULT_CONTEXT);

  decNumberAbs (&dn_absx, &dn_x, &context);

  /* For DFP, we use radix 10 instead of whatever FLT_RADIX happens to be */
  decNumberLog10 (&dn_logx, &dn_absx, &context);

  /* Capture the case where truncation will return the wrong result,
     by rounding up if -1.0 < x < 1.0  */
  round = DEC_ROUND_DOWN;
  decNumberFromInt32 (&dn_one, 1);
  decNumberCompare (&dn_cmp, &dn_x, &dn_one, &context);
  if (-decNumberIsNegative(&dn_cmp))
    {
      decNumberFromInt32 (&dn_one, -1);
      decNumberCompare (&dn_cmp, &dn_x, &dn_one, &context);
      if (!decNumberIsNegative(&dn_cmp) && !decNumberIsZero(&dn_cmp))
	round = DEC_ROUND_UP;
    }
  context.round = round;

  decNumberToIntegralValue (&dn_result, &dn_logx, &context);

  FUNC_CONVERT_FROM_DN (&dn_result, &result, &context);
  /* Use _Decimal* to int casting.  */
  return (_RETURN_TYPE) result;
}
コード例 #2
0
ファイル: logd32.c プロジェクト: rzinsly/libdfp
static DEC_TYPE
IEEE_FUNCTION_NAME (DEC_TYPE x)
{
  decContext context;
  decNumber dn_result;
  DEC_TYPE result;
  decNumber dn_x;

  FUNC_CONVERT_TO_DN(&x, &dn_x);
  if (decNumberIsNaN (&dn_x))
    return x+x;
  if (decNumberIsZero (&dn_x))	/*  If x == 0: Pole Error */
    {
      DFP_EXCEPT (FE_DIVBYZERO);
      return -DFP_HUGE_VAL;
    }
  if (decNumberIsNegative (&dn_x))	/*  If x < 0,: Domain Error */
    {
      DFP_EXCEPT (FE_INVALID);
      return DFP_NAN;
    }
  if (decNumberIsInfinite (&dn_x))
    return x;

  decContextDefault (&context, DEFAULT_CONTEXT);
  decNumberLn(&dn_result, &dn_x, &context);

  FUNC_CONVERT_FROM_DN(&dn_result, &result, &context);

  return result;
}
コード例 #3
0
ファイル: atanhd32.c プロジェクト: rzinsly/libdfp
static DEC_TYPE
IEEE_FUNCTION_NAME (DEC_TYPE x)
{
  decContext context;
  decNumber dn_result;
  DEC_TYPE result, one, temp;
  decNumber dn_x, dn_temp, dn_one;
/*  int comp;*/

  one=DFP_CONSTANT(1.0);
  FUNC_CONVERT_TO_DN (&one, &dn_one);
  FUNC_CONVERT_TO_DN (&x, &dn_x);

  /*  Handle NaN and early exit for x==0 */
  if (decNumberIsNaN (&dn_x) || decNumberIsZero (&dn_x))
    return x + x;

  decContextDefault (&context, DEFAULT_CONTEXT);
  decNumberAbs (&dn_temp, &dn_x, &context);

  FUNC_CONVERT_FROM_DN (&dn_temp, &temp, &context);
  if(temp==one) {
	/*  |x| == 1 -> Pole Error */
	DFP_EXCEPT (FE_DIVBYZERO);
	return decNumberIsNegative(&dn_x) ? -DFP_HUGE_VAL:DFP_HUGE_VAL;
  } else if (temp>one) {
	/*  |x| > 1 -> Domain Error (this handles +-Inf too) */
	DFP_EXCEPT (FE_INVALID);
	return DFP_NAN;
  }

//  comp = decCompare (&dn_temp, &dn_one);
//  switch (comp)
//    {
//      case 0: /*  |x| == 1 -> Pole Error */
//	DFP_EXCEPT (FE_DIVBYZERO);
//	return decNumberIsNegative(&dn_x) ? -DFP_HUGE_VAL:DFP_HUGE_VAL;
//      case 1: /*  |x| > 1 -> Domain Error (this handles +-Inf too) */
//	DFP_EXCEPT (FE_INVALID);
//	return DFP_NAN;
//    }

  /* Using trig identity: atanh(x) = 1/2 * log((1+x)/(1-x)) */
  decNumberAdd (&dn_result, &dn_one, &dn_x, &context);
  decNumberSubtract (&dn_temp, &dn_one, &dn_x, &context);
  decNumberDivide (&dn_result, &dn_result, &dn_temp, &context);
  decNumberLn (&dn_result, &dn_result, &context);
  decNumberAdd (&dn_temp, &dn_one, &dn_one, &context); /* 2 */
  decNumberDivide (&dn_result, &dn_result, &dn_temp, &context);

  FUNC_CONVERT_FROM_DN (&dn_result, &result, &context);

  return result;
}
コード例 #4
0
ファイル: ldexpd32.c プロジェクト: gftg85/libdfp
static DEC_TYPE
IEEE_FUNCTION_NAME (DEC_TYPE x, int y)
{
  DEC_TYPE result;
  long newexp;

#if NUMDIGITS_SUPPORT==1
  newexp = FUNC_D (getexp) (x) + y + 1;
  if (newexp > PASTE(DECIMAL,PASTE(_DECIMAL_SIZE,_Emax)))
    {
    result = DFP_HUGE_VAL;
    DFP_EXCEPT (FE_OVERFLOW);
    }
  else if (newexp < PASTE(DECIMAL,PASTE(_DECIMAL_SIZE,_Emin)))
    {
    result = -DFP_HUGE_VAL;
    DFP_EXCEPT (FE_OVERFLOW);
    }
  else
    result = FUNC_D(setexp) (x, newexp);

#else
  decContext context;
  decNumber dn_x;

  FUNC_CONVERT_TO_DN (&x, &dn_x);
  if (___decNumberIsNaN (&dn_x) || ___decNumberIsZero (&dn_x) ||
	___decNumberIsInfinite (&dn_x))
    return x+x;
  if (y == 0)
    return x;

  /* ldexp(x,y) is just x*10**y, which is equivalent to increasing the exponent
   * by y + 1.  */
  newexp = dn_x.exponent + y + 1;
  if(newexp > INT_MAX)
    newexp = INT_MAX;
  if(newexp < -INT_MAX)
    newexp = -INT_MAX;
  dn_x.exponent = newexp;

  decContextDefault (&context, DEFAULT_CONTEXT);
  FUNC_CONVERT_FROM_DN (&dn_x, &result, &context);

  if (context.status & DEC_Overflow)
    DFP_EXCEPT (FE_OVERFLOW);
#endif

  return result;
}
コード例 #5
0
ファイル: exp2d32.c プロジェクト: rzinsly/libdfp
static DEC_TYPE
IEEE_FUNCTION_NAME (DEC_TYPE x)
{
  decContext context;
  decNumber dn_result;
  DEC_TYPE result;
  decNumber dn_x;
  decNumber dn_two;
  DEC_TYPE two = DFP_CONSTANT(2.0);

  FUNC_CONVERT_TO_DN (&two, &dn_two);
  FUNC_CONVERT_TO_DN (&x, &dn_x);

  if (decNumberIsNaN (&dn_x))
    return x+x;

  if (decNumberIsInfinite (&dn_x) )
    return decNumberIsNegative (&dn_x) ? DFP_CONSTANT(0.0) : x;

  decContextDefault (&context, DEFAULT_CONTEXT);
  /* decNumberPow (&dn_result, &dn_two, &dn_x, &context);  */
  decNumberPower (&dn_result, &dn_two, &dn_x, &context);

  FUNC_CONVERT_FROM_DN (&dn_result, &result, &context);

  if(context.status & DEC_Overflow)
    DFP_EXCEPT (FE_OVERFLOW);

  return result;
}
コード例 #6
0
ファイル: expm1d32.c プロジェクト: gftg85/libdfp
static DEC_TYPE
IEEE_FUNCTION_NAME (DEC_TYPE x)
{
  decContext context;
  decNumber dn_result;
  DEC_TYPE result;
  decNumber dn_x;
  decNumber dn_one;
  decNumber dn_exponent;
  DEC_TYPE one = DFP_CONSTANT(1.0);

  FUNC_CONVERT_TO_DN(&x, &dn_x);
  FUNC_CONVERT_TO_DN(&one, &dn_one);
  if (decNumberIsNaN (&dn_x))
    return x+x;

  if (decNumberIsInfinite (&dn_x))
    return decNumberIsNegative (&dn_x) ? DFP_CONSTANT(-1.0) : x;

  decContextDefault(&context, DEFAULT_CONTEXT);
  decNumberExp(&dn_exponent, &dn_x, &context);
  decNumberSubtract(&dn_result, &dn_exponent, &dn_one, &context);

  FUNC_CONVERT_FROM_DN(&dn_result, &result, &context);
  if (context.status & DEC_Overflow)
    DFP_EXCEPT (FE_OVERFLOW);

  return result;
}
コード例 #7
0
ファイル: llroundd32.c プロジェクト: gftg85/libdfp
static __ROUND_RETURN_TYPE
IEEE_FUNCTION_NAME (DEC_TYPE x)
{
  DEC_TYPE result;
  decContext context;
  decNumber dn_result;
  decNumber dn_x;

  FUNC_CONVERT_TO_DN (&x, &dn_x);
  if (decNumberIsNaN (&dn_x) || decNumberIsInfinite (&dn_x)
	|| x > __MAX_VALUE || x < __MIN_VALUE)
    {
      DFP_EXCEPT (FE_INVALID);
      return (__ROUND_RETURN_TYPE) x;
    }

  decContextDefault (&context, DEFAULT_CONTEXT);
  context.round = __ROUND_MODE;
  decNumberToIntegralValue (&dn_result,&dn_x,&context);

  FUNC_CONVERT_FROM_DN(&dn_result, &result, &context);
  /* Use _Decimal* to __ROUND_RETURN_TYPE casting.  */
  return (__ROUND_RETURN_TYPE)result;

/*  return (__ROUND_RETURN_TYPE)decNumberToInteger (&dn_result); */
}
コード例 #8
0
ファイル: logbd32.c プロジェクト: gftg85/libdfp
DEC_TYPE
INTERNAL_FUNCTION_NAME (DEC_TYPE x)
{
  decContext context;
  decNumber dn_result;
  DEC_TYPE result;
  decNumber dn_x;
  decNumber dn_tmp;
  decNumber dn_log10;
  decNumber dn_one;
  decNumber dn_cmp;
  enum rounding round;

  FUNC_CONVERT_TO_DN (&x, &dn_x);
  if (decNumberIsNaN (&dn_x))
    return x+x;
  if (decNumberIsInfinite (&dn_x))	/* +-Inf: Inf  */
    return DEC_INFINITY;
  if (decNumberIsZero (&dn_x))	/*  Pole Error if x==0 */
    {
      DFP_ERRNO (ERANGE);
      DFP_EXCEPT (FE_DIVBYZERO);
      return -DFP_HUGE_VAL;
    }
  if (decNumberIsInfinite (&dn_x) && decNumberIsNegative (&dn_x))
    return -x;

  decContextDefault (&context, DEFAULT_CONTEXT);
  decNumberAbs (&dn_tmp, &dn_x, &context);
  /*  For DFP, we use radix 10 instead of whatever FLT_RADIX
      happens to be */
  decNumberLog10 (&dn_log10, &dn_tmp, &context);

  /* Capture the case where truncation will return the wrong result,
     by rounding up if -1.0 < x < 1.0  */
  round = DEC_ROUND_DOWN;
  decNumberFromInt32 (&dn_one, 1);
  decNumberCompare (&dn_cmp, &dn_x, &dn_one, &context);
  if (-decNumberIsNegative(&dn_cmp))
    {
      decNumberFromInt32 (&dn_one, -1);
      decNumberCompare (&dn_cmp, &dn_x, &dn_one, &context);
      if (!decNumberIsNegative(&dn_cmp) && !decNumberIsZero(&dn_cmp))
	round = DEC_ROUND_UP;
    }
  context.round = round;

  decNumberToIntegralValue (&dn_result, &dn_log10, &context);

  FUNC_CONVERT_FROM_DN (&dn_result, &result, &context);

  return result;
}
コード例 #9
0
ファイル: log1pd32.c プロジェクト: gftg85/libdfp
static DEC_TYPE
IEEE_FUNCTION_NAME (DEC_TYPE x)
{
  decContext context;
  decNumber dn_result;
  DEC_TYPE result;
  decNumber dn_x;
  decNumber dn_sum;
  decNumber dn_one;
  DEC_TYPE one = DFP_CONSTANT(1.0);

  FUNC_CONVERT_TO_DN (&x, &dn_x);
  FUNC_CONVERT_TO_DN (&one, &dn_one);

  /*  For NaN, 0, or +Inf, just return x */
  if (decNumberIsNaN (&dn_x) || decNumberIsZero (&dn_x) ||
	(decNumberIsInfinite (&dn_x) && !decNumberIsNegative (&dn_x)))
    return x+x;

  decContextDefault(&context, DEFAULT_CONTEXT);
  decNumberAdd(&dn_sum, &dn_x, &dn_one, &context);
  if (decNumberIsZero(&dn_sum)) /*  Pole Error if x was -1 */
    {
      DFP_EXCEPT (FE_DIVBYZERO);
      return -DFP_HUGE_VAL;
    }
  if (decNumberIsNegative(&dn_sum)) /*  Domain Error if x < -1 */
    {
      DFP_EXCEPT (FE_INVALID);
      return DFP_NAN;
    }

  decNumberLn(&dn_result, &dn_sum, &context);
  FUNC_CONVERT_FROM_DN(&dn_result, &result, &context);


  return result;
}
コード例 #10
0
ファイル: tgammad32.c プロジェクト: gftg85/libdfp
static DEC_TYPE
IEEE_FUNCTION_NAME (DEC_TYPE x)
{
  DEC_TYPE result, gamma;
  int local_signgam;

  if (x == DFP_CONSTANT(0.0))	/*  Pole error if x== +-0 */
    {
      DFP_EXCEPT (FE_DIVBYZERO);
//      return FUNC_D (__builtin_signbit) (x) ? -DFP_HUGE_VAL : DFP_HUGE_VAL;
      return (x<0) ? -DFP_HUGE_VAL : DFP_HUGE_VAL;
    }
  if (x < DFP_CONSTANT(0.0) && (!FUNC_D (__isinf) (x) && FUNC_D (__rint) (x) == x) )
    {
      DFP_EXCEPT (FE_INVALID);
      return DFP_NAN;
    }

  gamma = FUNC_D(__lgamma_r) (x,&local_signgam);
  result = local_signgam * FUNC_D(__exp) (gamma);

  return result;
}
コード例 #11
0
ファイル: roundd32.c プロジェクト: rzinsly/libdfp
DEC_TYPE
INTERNAL_FUNCTION_NAME (DEC_TYPE x)
{
  decContext context;
  decNumber dn_result;
  DEC_TYPE result;
  decNumber dn_x;

  FUNC_CONVERT_TO_DN (&x, &dn_x);
  if (decNumberIsNaN (&dn_x) || decNumberIsInfinite (&dn_x) ||
	decNumberIsZero (&dn_x))
    return x+x;

  decContextDefault (&context, DEFAULT_CONTEXT);
  context.round = __ROUND_MODE;
  decNumberToIntegralValue (&dn_result, &dn_x, &context);

  FUNC_CONVERT_FROM_DN (&dn_result, &result, &context);
  if (context.status & DEC_Overflow)
    DFP_EXCEPT (FE_OVERFLOW);

  return result;
}
コード例 #12
0
ファイル: fdimd32.c プロジェクト: gftg85/libdfp
static DEC_TYPE
IEEE_FUNCTION_NAME (DEC_TYPE x, DEC_TYPE y)
{
  decContext context;
  decNumber dn_result;
  DEC_TYPE result;
  decNumber dn_x;
  decNumber dn_y;
  decNumber dn_diff;
  DEC_TYPE temp_diff;
  DEC_TYPE temp_result;

  FUNC_CONVERT_TO_DN (&x, &dn_x);
  FUNC_CONVERT_TO_DN (&y, &dn_y);

  if(decNumberIsNaN (&dn_x) || decNumberIsNaN (&dn_y))
    return x;

  decContextDefault (&context, DEFAULT_CONTEXT);
  decNumberSubtract (&dn_diff, &dn_x, &dn_y, &context);
  decNumberSubtract (&dn_result, &dn_x, &dn_x, &context);

  FUNC_CONVERT_FROM_DN (&dn_diff, &temp_diff, &context);
  FUNC_CONVERT_FROM_DN (&dn_result, &temp_result, &context);
  if(temp_diff>temp_result)
    decNumberAdd (&dn_result,&dn_result,&dn_diff,&context);
 /* if(decCompare (&dn_diff,&dn_result) == 1)
    decNumberAdd (&dn_result,&dn_result,&dn_diff,&context);
    */

  FUNC_CONVERT_FROM_DN (&dn_result, &result, &context);
  if (context.status & DEC_Overflow)
    DFP_EXCEPT (FE_OVERFLOW);

  return result;
}
コード例 #13
0
ファイル: powd32.c プロジェクト: gftg85/libdfp
static DEC_TYPE
IEEE_FUNCTION_NAME (DEC_TYPE x, DEC_TYPE y)
{
  decContext context;
  decNumber dn_result;
  DEC_TYPE result;
  DEC_TYPE absx;
  decNumber dn_x;
  decNumber dn_absx;
  decNumber dn_y;
  decNumber dn_one;
  decNumber dn_two;
  decNumber dn_temp;
  decNumber dn_temp2;
  decNumber dn_temp3;
  int y_is_int;
  int y_is_oddint=0;
  int abs_x_vs_1;
  DEC_TYPE one = DFP_CONSTANT(1.0);
  DEC_TYPE two = DFP_CONSTANT(2.0);

  FUNC_CONVERT_TO_DN (&x, &dn_x);
  FUNC_CONVERT_TO_DN (&y, &dn_y);
  FUNC_CONVERT_TO_DN (&one, &dn_one);

  decContextDefault (&context, DEFAULT_CONTEXT);
  if (decNumberIsZero (&dn_y))
    return one;
  if (decNumberIsNaN (&dn_x))
    return x+x;

  decNumberAbs (&dn_absx, &dn_x, &context);

  FUNC_CONVERT_FROM_DN (&dn_absx, &absx, &context);
  if(absx<one)
    abs_x_vs_1 = -1;
  else if (absx==one)
    abs_x_vs_1 = 0;
  else
    abs_x_vs_1 = 1;

/*  abs_x_vs_1 = decCompare(&dn_absx, &dn_one); */
  if(abs_x_vs_1 == 0 && !decNumberIsNegative (&dn_x)) /*  If x == +1 */
    return one;
  if (decNumberIsNaN (&dn_y))
    return y+y;

  /*  Detect if y is odd/an integer */
  decNumberToIntegralValue (&dn_temp, &dn_y, &context);
  decNumberSubtract (&dn_temp2, &dn_temp, &dn_y, &context);
  y_is_int = decNumberIsZero (&dn_temp2);
  if (y_is_int)
    {
      FUNC_CONVERT_TO_DN (&two, &dn_two);
      decNumberDivide (&dn_temp, &dn_y, &dn_two, &context);
      decNumberToIntegralValue (&dn_temp2, &dn_temp, &context);
      decNumberSubtract (&dn_temp3, &dn_temp2, &dn_temp, &context);
      y_is_oddint = !decNumberIsZero (&dn_temp3);
    }

  /*  Handle all special cases for which x = +-0 */
  if (decNumberIsZero (&dn_x))
    {
      if(decNumberIsNegative (&dn_y))
	{
	  if (decNumberIsInfinite (&dn_y))	/*  +-0^-Inf = +Inf */
	    return -y;
	  /*  Pole Error for x = +-0, y < 0 */
	  DFP_EXCEPT (FE_DIVBYZERO);
	  return decNumberIsNegative(&dn_x) && y_is_oddint ?
		-DFP_HUGE_VAL : DFP_HUGE_VAL;
	}
      return decNumberIsNegative(&dn_x) && y_is_oddint ?
		-DFP_CONSTANT(0.0) : DFP_CONSTANT(0.0);
    }

  /* Handle remaining special cases for x = +-Inf or y = +-Inf */
  if (decNumberIsInfinite (&dn_x) || decNumberIsInfinite (&dn_y))
    {
      if (abs_x_vs_1 == 0)	/*  If (-1)^(+-Inf) */
	return one;
      if (abs_x_vs_1 < 0)	/*  x^(+-Inf), where 0<x<1 */
	return decNumberIsNegative (&dn_y) ? DFP_HUGE_VAL
		: DFP_CONSTANT(0.0);
      if (decNumberIsNegative (&dn_y))
	result = DFP_CONSTANT(0.0);
      else
	result = (DEC_TYPE)DEC_INFINITY;
      if (y_is_oddint && decNumberIsNegative(&dn_x))
	result = -result;
      return result;
    }

  /* Domain Error: x < 0 && y is a finite non-int */
  if (decNumberIsNegative (&dn_x) && !y_is_int)
    {
      DFP_EXCEPT (FE_INVALID);
      return DFP_NAN;
    }

  decNumberPower (&dn_result, &dn_x, &dn_y, &context);
  FUNC_CONVERT_FROM_DN (&dn_result, &result, &context);

  if (context.status & DEC_Overflow)
    DFP_EXCEPT (FE_OVERFLOW);
  if (context.status & DEC_Underflow)
    DFP_EXCEPT (FE_UNDERFLOW);

  return result;
}
コード例 #14
0
ファイル: acosd32.c プロジェクト: rzinsly/libdfp
static DEC_TYPE
IEEE_FUNCTION_NAME (DEC_TYPE x)
{
  _Decimal128 z, r, w, p, q, s, t, f2, ix;
  int32_t sign;

  if(isnan(x))
    return x+x;

  sign = (x > 0.0DL)?0:1;
  ix = FUNC_D(__fabs) (x);

  if (ix >= 1.0DL)		/* |x| >= 1 */
    {
      if (ix == 1.0DL)
	{			/* |x| == 1 */
	  if (sign == 0)
	    return (DEC_TYPE)(0.0DL);		/* acos(1) = 0  */
	  else
	    return (DEC_TYPE)((2.0DL * pio2_hi) + (2.0DL * pio2_lo));	/* acos(-1)= pi */
	}
      /* acos(|x| > 1) is NaN */
      DFP_EXCEPT (FE_INVALID);
      return DFP_NAN;
    }
  else if (ix < 0.5DL)	/* |x| < 0.5 */
    {
      /* |x| < 2**-57 */
      if (ix < 0.000000000000000000000000000000000000000000000000000000002DL)
	return (DEC_TYPE)(pio2_hi + pio2_lo); //Should raise INEXACT
      if (ix < 0.4375DL)	/* |x| < .4375 */
	{
	  /* Arcsine of x.  */
	  z = x * x;
	  p = (((((((((pS9 * z
		       + pS8) * z
		      + pS7) * z
		     + pS6) * z
		    + pS5) * z
		   + pS4) * z
		  + pS3) * z
		 + pS2) * z
		+ pS1) * z
	       + pS0) * z;
	  q = (((((((( z
		       + qS8) * z
		     + qS7) * z
		    + qS6) * z
		   + qS5) * z
		  + qS4) * z
		 + qS3) * z
		+ qS2) * z
	       + qS1) * z
	    + qS0;
	  r = x + x * p / q;
	  z = pio2_hi - (r - pio2_lo);
	  return (DEC_TYPE)z;
	}
      /* .4375 <= |x| < .5 */
      t = ix - 0.4375DL;
      p = ((((((((((P10 * t
		    + P9) * t
		   + P8) * t
		  + P7) * t
		 + P6) * t
		+ P5) * t
	       + P4) * t
	      + P3) * t
	     + P2) * t
	    + P1) * t
	   + P0) * t;

      q = (((((((((t
		   + Q9) * t
		  + Q8) * t
		 + Q7) * t
		+ Q6) * t
	       + Q5) * t
	      + Q4) * t
	     + Q3) * t
	    + Q2) * t
	   + Q1) * t
	+ Q0;
      r = p / q;
      if (sign)
	r = pimacosr4375 - r;
      else
	r = acosr4375 + r;
      return (DEC_TYPE)r;
    }
  else if (ix < 0.625DL)	/* |x| < 0.625 */
    {
      t = ix - 0.5625DL;
      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;
      if (sign)
	r = pimacosr5625 - p / q;
      else
	r = acosr5625 + p / q;
      return (DEC_TYPE)r;
    }
  else
    {				/* |x| >= .625 */
      z = (one - ix) * 0.5DL;
      s = __sqrtd128 (z);
      /* Compute an extended precision square root from
	 the Newton iteration  s -> 0.5 * (s + z / s).
         The change w from s to the improved value is
	    w = 0.5 * (s + z / s) - s  = (s^2 + z)/2s - s = (z - s^2)/2s.
          Express s = f1 + f2 where f1 * f1 is exactly representable.
	  w = (z - s^2)/2s = (z - f1^2 - 2 f1 f2 - f2^2)/2s .
          s + w has extended precision.  */
      p = s;
     /*
      u.value = s;
      u.parts32.w2 = 0;
      u.parts32.w3 = 0;
      */
      f2 = s - p;
      w = z - p * p;
      w = w - 2.0DL * p * f2;
      w = w - f2 * f2;
      w = w / (2.0DL * s);
      /* Arcsine of s.  */
      p = (((((((((pS9 * z
		   + pS8) * z
		  + pS7) * z
		 + pS6) * z
		+ pS5) * z
	       + pS4) * z
	      + pS3) * z
	     + pS2) * z
	    + pS1) * z
	   + pS0) * z;
      q = (((((((( z
		   + qS8) * z
		 + qS7) * z
		+ qS6) * z
	       + qS5) * z
	      + qS4) * z
	     + qS3) * z
	    + qS2) * z
	   + qS1) * z
	+ qS0;
      r = s + (w + s * p / q);

      if (sign)
	w = pio2_hi + (pio2_lo - r);
      else
	w = r;
      return (DEC_TYPE)(2.0DL * w);
    }
}
コード例 #15
0
ファイル: logd64.c プロジェクト: rzinsly/libdfp
static DEC_TYPE
IEEE_FUNCTION_NAME (DEC_TYPE val)
{

    _Decimal64 result, top, fraction, a, x, tp;
    _Decimal64 t1, t2, t3, t4, t5, t6, t7, t8;
    _Decimal64 t9, t10, t11, t12, t13, t14, t15, t16;
    int exp;
    long tmp;

    if (__isnand64(val))
        return val+val;
    if (val == DFP_CONSTANT(0.0))
    {
        DFP_EXCEPT (FE_DIVBYZERO);
        return -DFP_HUGE_VAL;
    }
    if (val < DFP_CONSTANT(0.0))
    {
        DFP_EXCEPT (FE_INVALID);
        return DFP_NAN;
    }
    if (__isinfd64(val))
        return val;

    result = __frexpd64 (val, &exp);

    tmp = result * 100.0DD;
    top = tmp;
    top = top * 0.01DD;
    fraction = result - top;

    if (fraction != 0.00DD)
    {
        a = top;
        x = result;
        t1 = (x - a) / a;
        tp = t1 * t1; /* tp == ((x-a)/a)^2 */
        t2 = tp / 2.0DD; /* t2 == (((x-a)/a)^2)/2 */
        tp = tp * t1; /* tp == ((x-a)/a)^3 */
        t3 = tp / 3.0DD; /* t3 == (((x-a)/a)^3)/3 */
        tp = tp * t1; /* tp == ((x-a)/a)^4 */
        t4 = tp / 4.0DD; /* t4 == (((x-a)/a)^4)/4 */
        tp = tp * t1; /* tp == ((x-a)/a)^5 */
        t5 = tp / 5.0DD; /* t5 == (((x-a)/a)^5)/5 */
        tp = tp * t1; /* tp == ((x-a)/a)^6 */
        t6 = tp / 6.0DD; /* t6 == (((x-a)/a)^6)/6 */
        tp = tp * t1; /* tp == ((x-a)/a)^7 */
        t7 = tp / 7.0DD; /* t7 == (((x-a)/a)^7)/7 */
        tp = tp * t1; /* tp == ((x-a)/a)^8 */
        t8 = tp / 8.0DD; /* t8 == (((x-a)/a)^8)/8 */
        if ( t8 > 1.0E-16DD)
        {
            tp = tp * t1; /* tp == ((x-a)/a)^9 */
            t9 = tp / 9.0DD; /* t9 == (((x-a)/a)^9)/9 */
            tp = tp * t1; /* tp == ((x-a)/a)^10 */
            t10 = tp / 10.0DD; /* t10 == (((x-a)/a)^10)/10 */
            tp = tp * t1; /* tp == ((x-a)/a)^11 */
            t11 = tp / 11.0DD; /* t12 == (((x-a)/a)^11)/11 */
            tp = tp * t1; /* tp == ((x-a)/a)^12 */
            t12 = tp / 12.0DD; /* t12 == (((x-a)/a)^11)/12 */
            if  (t12 > 1.0E-16DD)
            {
                tp = tp * t1; /* tp == ((x-a)/a)^13 */
                t13 = tp / 13.0DD; /* t13 == (((x-a)/a)^13)/13 */
                tp = tp * t1; /* tp == ((x-a)/a)^14 */
                t14 = tp / 14.0DD; /* t14 == (((x-a)/a)^14)/14 */
                tp = tp * t1; /* tp == ((x-a)/a)^15 */
                t15 = tp / 15.0DD; /* t15 == (((x-a)/a)^15)/15 */
                tp = tp * t1; /* tp == ((x-a)/a)^16 */
                t16 = tp / 16.0DD; /* t16 == (((x-a)/a)^16)/16 */
                tp = t15 - t16;
                tp = tp + (t13 - t14);
                tp = tp + (t11 - t12);
            }
            else
            {
                tp = t11 - t12;
            }
            tp = tp + (t9 - t10);
            tp = tp + (t7 - t8);
        }
        else
            tp = t7 - t8;

        /* now sum the terms from smallest to largest to avoid loss of percision */
        tp = tp + (t5 - t6);
        tp = tp + (t3 - t4);
        tp = tp + (t1 - t2);

        if (exp!=0)
            result = (__LN_10 * exp) + __LN2digits[tmp] + tp;
        else
            result = __LN2digits[tmp] + tp;
    }
    else
    {
        if (exp!=0)
            result = (__LN_10 * exp) + __LN2digits[tmp];
        else
            result = __LN2digits[tmp];
    }
    return result;
}