Esempio n. 1
0
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;
}
Esempio n. 2
0
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;
}
Esempio n. 3
0
DEC_TYPE
INTERNAL_FUNCTION_NAME (DEC_TYPE x)
{
  DEC_TYPE z = IEEE_FUNCTION_NAME (x);
  if (x > DFP_CONSTANT(1.0) || x < DFP_CONSTANT(-1.0))
    DFP_ERRNO (EDOM);
  return z;
}
Esempio n. 4
0
DEC_TYPE
INTERNAL_FUNCTION_NAME (DEC_TYPE x)
{
  DEC_TYPE z = IEEE_FUNCTION_NAME (x);
  if (x == DFP_CONSTANT(0.0))
    DFP_ERRNO (ERANGE);
  if (x < DFP_CONSTANT(0.0))
    DFP_ERRNO (EDOM);
  return z;
}
Esempio n. 5
0
DEC_TYPE
INTERNAL_FUNCTION_NAME (DEC_TYPE x)
{
  DEC_TYPE z = IEEE_FUNCTION_NAME (x);
  if (x < DFP_CONSTANT(-1.0) || x > DFP_CONSTANT(1.0))
    DFP_ERRNO (EDOM);
  /* The normal glibc ieee754 k_standard.c file does not follow c99 or POSIX
   * with regard to atanh pole errors. atan(+-1.0) [the binary version] will
   * set errno to EDOM.  Hopefully this will get worked out soon. */
  if (x == DFP_CONSTANT(-1.0) || x == DFP_CONSTANT(1.0))
    DFP_ERRNO (ERANGE);
  return z;
}
Esempio n. 6
0
DEC_TYPE
INTERNAL_FUNCTION_NAME (DEC_TYPE x)
{
  decContext context;
  decNumber dn_result;
  DEC_TYPE result, one;
  decNumber dn_x, dn_one;

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

  if (decNumberIsNaN (&dn_x) || decNumberIsZero (&dn_x)
	|| decNumberIsInfinite (&dn_x))
    {
      return x + x;
    }
  decContextDefault (&context, DEFAULT_CONTEXT);

  /* using trig identity: acosh(x) = log(x+sqrt(x*x-1)) */
  decNumberMultiply (&dn_result, &dn_x, &dn_x, &context);
  decNumberAdd (&dn_result, &dn_result, &dn_one, &context);
  decNumberSquareRoot (&dn_result, &dn_result, &context);
  decNumberAdd (&dn_result, &dn_result, &dn_x, &context);
  decNumberLn (&dn_result, &dn_result, &context);

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

  return result;
}
Esempio n. 7
0
DEC_TYPE
INTERNAL_FUNCTION_NAME (DEC_TYPE x, DEC_TYPE y)
{
  DEC_TYPE z = IEEE_FUNCTION_NAME (x, y);
  /* Pole error: x = 0, y < 0 (non-inf). Set ERANGE in accordance with C99 */
  if (x == DFP_CONSTANT(0.0) && FUNC_D(__isfinite)(y) && y < DFP_CONSTANT(0.0))
      DFP_ERRNO (ERANGE);
  if (!FUNC_D(__isfinite) (z) && FUNC_D(__isfinite) (x) && FUNC_D(__isfinite) (y))
    {
      if (FUNC_D(__isnan) (z)) /*  Domain error was triggered, x < 0 and y was not an
			odd int */
	DFP_ERRNO (EDOM);
      else	/*  Overflow */
	DFP_ERRNO (ERANGE);
    }
  return z;
}
Esempio n. 8
0
DEC_TYPE
INTERNAL_FUNCTION_NAME (DEC_TYPE x)
{
  DEC_TYPE z = IEEE_FUNCTION_NAME (x);
  if (!FUNC_D(__isfinite) (z) && FUNC_D(__isfinite) (x))
    DFP_ERRNO (ERANGE);
  if (x < DFP_CONSTANT(0.0) && (FUNC_D (__isinf) (x) && FUNC_D (__rint) (x) == x) )
    DFP_ERRNO (EDOM);
  return z;
}
Esempio n. 9
0
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;
}
Esempio n. 10
0
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;
}
Esempio n. 11
0
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;
}
Esempio n. 12
0
DEC_TYPE
INTERNAL_FUNCTION_NAME (DEC_TYPE x)
{
  int e, rem, sign;
  _Decimal128 z;

  if (! FUNC_D(__isfinite) (x)) /* cbrt(x:x=inf/nan/-inf) = x+x (for sNaN) */
    return x + x;

  if (x == DFP_CONSTANT(0.0)) /*  cbrt(0) = 0 */
    return (x);

  if (x > DFP_CONSTANT(0.0))
    sign = 1;
  else
    {
      sign = -1;
      x = -x;
    }

  z = x;
 /* extract power of 2, leaving mantissa between 0.5 and 1  */
  x = FUNC_D(__frexp) (x, &e);

  /* Approximate cube root of number between .5 and 1,
     peak relative error = 1.2e-6  */
  x = ((((1.3584464340920900529734e-1DL * x
	  - 6.3986917220457538402318e-1DL) * x
	 + 1.2875551670318751538055e0DL) * x
	- 1.4897083391357284957891e0DL) * x
       + 1.3304961236013647092521e0DL) * x + 3.7568280825958912391243e-1DL;

  /* exponent divided by 3 */
  if (e >= 0)
    {
      rem = e;
      e /= 3;
      rem -= 3 * e;
      if (rem == 1)
	//x *= CBRT2;
	x *= CBRT10;
      else if (rem == 2)
	//x *= CBRT4;
	x *= CBRT100;
    }
  else
    {				/* argument less than 1 */
      e = -e;
      rem = e;
      e /= 3;
      rem -= 3 * e;
      if (rem == 1)
	//x *= CBRT2I;
	x *= CBRT10I;
      else if (rem == 2)
	//x *= CBRT4I;
	x *= CBRT100I;
      e = -e;
    }

  /* multiply by power of 2 */
  x = FUNC_D(__ldexp) (x, e);

  /* Newton iteration */
  x -= (x - (z / (x * x))) * 0.3333333333333333333333333333333333333333DL;
  x -= (x - (z / (x * x))) * 0.3333333333333333333333333333333333333333DL;
  x -= (x - (z / (x * x))) * 0.3333333333333333333333333333333333333333DL;

  if (sign < 0)
    x = -x;
  return (x);
}
Esempio n. 13
0
/* Core implementation of expd64(x).
   Separate into integer and fractional parts, where e^(i+f) == (e^i)*(e^f).
   We use a table lookup (expIntXDL(i)) for e^i and taylor series for e^f.
   Effectively:

   e^x = e^i * (1 + (x-i) + (((x-i)^2)/2!) + (((x-i)^3)/3!) + ...)

   The real expd64 will need add checks for NAN, INF and handle negative
   values of x.
 */
static DEC_TYPE
IEEE_FUNCTION_NAME (DEC_TYPE val)
{
  DEC_TYPE result, top, fraction, a, x, tp;
  DEC_TYPE t1, t2, t3, t4, t5, t6, t7, t8;
  DEC_TYPE t9, t10, t11, t12, t13, t14, t15, t16;
  DEC_TYPE t17, t18, t19, t20;
  long exp;
  long tmp;

  int neg = 0;

  if (__isinfd64(val))
    {
      if (val < DFP_CONSTANT(0.0))
	return DFP_CONSTANT(0.0); /* exp(-inf) = 0  */
      else
	return val;               /* exp(inf) = inf  */
    }

  if (val < DFP_CONSTANT(0.0))
    {
      neg = 1;
      val = FUNC_D(__fabs) (val);
    }

  tmp = val;
  top = tmp;
  fraction = val - top;
  exp = tmp;
  if (fraction != 0.0DD)
    {
      a = top; x = val;
      t1 = (x - a);
      tp = t1 * t1; /* tp == ((x-a))^2 */
      t2 = tp * __oneOverfactDD[2]; /* t2 == (((x-a))^2)/2! */
      tp = tp * t1; /* tp == ((x-a))^3 */
      t3 = tp * __oneOverfactDD[3]; /* t3 == (((x-a))^3)/3! */
      tp = tp * t1; /* tp == ((x-a)/a)^4 */
      t4 = tp * __oneOverfactDD[4]; /* t4 == (((x-a))^4)/4! */
      tp = tp * t1; /* tp == ((x-a))^5 */
      t5 = tp * __oneOverfactDD[5]; /* t5 == (((x-a))^5)/5! */
      tp = tp * t1; /* tp == ((x-a))^6 */
      t6 = tp * __oneOverfactDD[6]; /* t6 == (((x-a))^6)/6! */
      tp = tp * t1; /* tp == ((x-a))^7 */
      t7 = tp * __oneOverfactDD[7]; /* t7 == (((x-a))^7)/7! */
      tp = tp * t1; /* tp == ((x-a))^8 */
      t8 = tp * __oneOverfactDD[8]; /* t8 == (((x-a))^8)/8! */
      if ( t8 > 1.0E-16DD)
	{
	  tp = tp * t1; /* tp == ((x-a))^9 */
	  t9 = tp * __oneOverfactDD[9]; /* t9 == (((x-a))^9)/9! */
	  tp = tp * t1; /* tp == ((x-a))^10 */
	  t10 = tp * __oneOverfactDD[10]; /* t10 == (((x-a))^10)/10! */
	  tp = tp * t1; /* tp == ((x-a))^11 */
	  t11 = tp * __oneOverfactDD[11]; /* t12 == (((x-a))^11)/11! */
	  tp = tp * t1; /* tp == ((x-a))^12 */
	  t12 = tp * __oneOverfactDD[12]; /* t12 == (((x-a))^11)/12! */
	  if  (t12 > 1.0E-16DD)
	    {
	      tp = tp * t1; /* tp == ((x-a))^13 */
	      t13 = tp * __oneOverfactDD[13]; /* t13 == (((x-a))^13)/13! */
	      tp = tp * t1; /* tp == ((x-a))^14 */
	      t14 = tp * __oneOverfactDD[14]; /* t14 == (((x-a))^14)/14! */
	      tp = tp * t1; /* tp == ((x-a))^15 */
	      t15 = tp * __oneOverfactDD[15]; /* t15 == (((x-a))^15)/15! */
	      tp = tp * t1; /* tp == ((x-a))^16 */
	      t16 = tp * __oneOverfactDD[16]; /* t16 == (((x-a))^16)/16! */
	      if  (t12 > 1.0E-16DD)
		{
		  tp = tp * t1; /* tp == ((x-a))^17 */
		  t17 = tp * __oneOverfactDD[17]; /* t17 == (((x-a))^17)/17! */
		  tp = tp * t1; /* tp == ((x-a))^18 */
		  t18 = tp * __oneOverfactDD[18]; /* t18 == (((x-a))^18)/18! */
		  tp = tp * t1; /* tp == ((x-a))^19 */
		  t19 = tp * __oneOverfactDD[19]; /* t19 == (((x-a))^19)/19! */
		  tp = tp * t1; /* tp == ((x-a))^20 */
		  t20 = tp * __oneOverfactDD[20]; /* t20 == (((x-a))^20)/20! */
		  tp = t19 + t20;
		  tp = tp + t18;
		  tp = tp + t17;
		  tp = tp + t16;
		  tp = tp + t15;
		}
	      else
		{
		  tp = t15 + t16;
		}
	      tp = tp + t14;
	      tp = tp + t13;
	      tp = tp + t12;
	      tp = tp + t11;
	    }
	  else
	    {
	      tp = t11 + t12;
	    }
	  tp = tp + t10;
	  tp = tp + t9;
	  tp = tp + t8;
	  tp = tp + t7;
	}
      else
        tp = t7 + t8;

/* now sum the terms from smallest to largest to avoid lose of percision */
      tp = tp + t6;
      tp = tp + t5;
      tp = tp + t4;
      tp = tp + t3;
      tp = tp + t2;
      tp = tp + t1;
      tp = tp + 1.DD;

      if (exp!=0)
	result = __expIntXDL[exp] * tp;
      else
        result = tp;
    }
  else
    {
      if (exp!=0)
	result = __expIntXDL[exp];
      else
        result = 1.DD;
    }

  if (neg)
    result = 1/result;

  return result;
}
Esempio n. 14
0
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;
}
Esempio n. 15
0
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;
}