Пример #1
0
Файл: agm.c Проект: BigEd/wp34s
decNumber *decNumberAGM(decNumber *res, const decNumber *x, const decNumber *y) {
	int n;
	decNumber a, g, t, u;

	if (decNumberIsNegative(x) || decNumberIsNegative(y))
		goto nan;
	if (decNumberIsSpecial(x) || decNumberIsSpecial(y)) {
		if (decNumberIsNaN(x) || decNumberIsNaN(y))
			goto nan;
		if (dn_eq0(x) || dn_eq0(y))
			goto nan;
		return set_inf(res);
	}
	decNumberCopy(&a, x);
	decNumberCopy(&g, y);
	for (n=0; n<1000; n++) {
		if (relative_error(&a, &g, &const_1e_32))
			return decNumberCopy(res, &a);

		dn_add(&t, &a, &g);
		dn_div2(&u, &t);

		dn_multiply(&t, &a, &g);
		if (dn_eq0(&t))
			return decNumberZero(res);
		dn_sqrt(&g, &t);
		decNumberCopy(&a, &u);
	}
nan:	return set_NaN(res);
}
Пример #2
0
int DecimalDecNumber::comparedTo(const DecimalDecNumber &rhs) const
{
	if (decNumberIsNaN(&m_value) || decNumberIsNaN(&rhs.m_value))
	{
		throw("Performing comparison on uninitialised decimal [Nan]");
	}

   // TODO: the commented out lines below do a strict comparison between two numbers.
   // However, the unit tests assert that comparison should be done within a tolerance
   //decNumberCompare(&result, &m_value, &rhs.m_value, &contextComparison);
   //return decNumberToInt32(&result, &m_context);

   decContext contextComparison;
   decContextDefault(&contextComparison, DEC_INIT_BASE); // initialize
   contextComparison.traps=0;                            // no traps, thank you
   contextComparison.digits=DECNUMCOMPARISONDIGITS;      // set precision

   decNumber tmp(m_value);
   decNumberSubtract(&tmp, &m_value, &rhs.m_value, &m_context);

   decNumber result;
   decNumberCompare(&result, &tmp, &comparisonThreshold.m_value, &contextComparison);
   if (decNumberToInt32(&result, &m_context) >= 1)
   {
      return 1;
   }

   decNumberCompare(&result, &tmp, &comparisonThresholdNegative.m_value, &contextComparison);
   if (decNumberToInt32(&result, &m_context) <= -1)
   {
      return -1;
   }
   return 0;
}
Пример #3
0
const DecimalDecNumber &DecimalDecNumber::operator *=(const DecimalDecNumber &rhs)
{
	if (decNumberIsNaN(&m_value) || decNumberIsNaN(&rhs.m_value))
	{
		// FTHROW(InvalidStateException, "Performing arithmetic on uninitialised decimal [Nan]");
		throw("Performing arithmetic on uninitialised decimal [Nan]");
	}

   decNumberMultiply(&m_value, &m_value, &rhs.m_value, &m_context);
	return *this;
}
Пример #4
0
CMPtype
DFP_UNORD (DFP_C_TYPE arg_a, DFP_C_TYPE arg_b)
{
  decNumber arg1, arg2;
  IEEE_TYPE a, b;

  HOST_TO_IEEE (arg_a, &a);
  HOST_TO_IEEE (arg_b, &b);
  TO_INTERNAL (&a, &arg1);
  TO_INTERNAL (&b, &arg2);
  return (decNumberIsNaN (&arg1) || decNumberIsNaN (&arg2));
}
Пример #5
0
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); */
}
Пример #6
0
int
PREFIXED_FUNCTION_NAME (DEC_TYPE x, DEC_TYPE y)
{
  decNumber dn_x, dn_y, result;
  decContext context;
  decContextDefault(&context, DEFAULT_CONTEXT);

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

  if(decNumberIsNaN(&dn_x) || decNumberIsNaN(&dn_y))
    return -1;

  decNumberCompare(&result, &dn_x, &dn_y, &context);
  return !decNumberIsNegative(&result) && !decNumberIsZero(&result);
}
Пример #7
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;
}
Пример #8
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;
}
Пример #9
0
int
__fpclassifyd64 (_Decimal64 x)
{
  decNumber dn_x;
  decContext context;

  FUNC_CONVERT_TO_DN (&x, &dn_x);

  if (decNumberIsNaN (&dn_x))
    return FP_NAN;
  else if (decNumberIsInfinite (&dn_x))
    return FP_INFINITE;
  else if (decNumberIsZero (&dn_x))
    return FP_ZERO;

  /* Since DFP value are not normalized, checking the exponent for
     normal/subnormal is not suffice.  For instance, the value 10e-96 will
     result in a expoenent below the minimum, however it is still a FP_NORMAL
     number due implicit normalization.  TO avoid such traps the check relies
     on runtime comparisons.  */
  decContextDefault (&context, DEC_INIT_DECIMAL64);
  if (decNumberIsSubnormal (&dn_x, &context))
    return FP_SUBNORMAL;

  return FP_NORMAL;
}
Пример #10
0
static void
decimal_from_decnumber (REAL_VALUE_TYPE *r, decNumber *dn, decContext *context)
{
  memset (r, 0, sizeof (REAL_VALUE_TYPE));

  r->cl = rvc_normal;
  if (decNumberIsZero (dn))
    r->cl = rvc_zero;
  if (decNumberIsNaN (dn))
    r->cl = rvc_nan;
  if (decNumberIsInfinite (dn))
    r->cl = rvc_inf;
  if (context->status & DEC_Overflow)
    r->cl = rvc_inf;
  if (decNumberIsNegative (dn))
    r->sign = 1;
  r->decimal = 1;

  if (r->cl != rvc_normal)
    return;

  decContextDefault (context, DEC_INIT_DECIMAL128);
  context->traps = 0;

  decimal128FromNumber ((decimal128 *) r->sig, dn, context);
}
Пример #11
0
_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;
}
Пример #12
0
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;
}
Пример #13
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;
}
Пример #14
0
_Decimal128
__quantumd128 (_Decimal128 x)
{
  decNumber dn_x;
  decNumber dn_result;
  decContext context;
  _Decimal128 result;

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

  /* The quantum of a finite number is defined as 1 x 10^exponent, so
     first get input absolute value and then sets its coefficient to 1.  */
  decContextDefault (&context, DEFAULT_CONTEXT);
  decNumberAbs (&dn_result, &dn_x, &context);
  dn_result.digits = 1;
  dn_result.lsu[0] = 1;

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

  return result;
}
Пример #15
0
int
INTERNAL_FUNCTION_NAME (DEC_TYPE x, DEC_TYPE y)
{
  decNumber dn_x;
  decNumber dn_y;
  decNumber dn_result;
  decContext context;

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

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

  decNumberCompare (&dn_result, &dn_x, &dn_y, &context);
  return (-decNumberIsNegative (&dn_result)) ||
	 (!decNumberIsNegative (&dn_result) && !decNumberIsZero (&dn_result));
}
Пример #16
0
DecimalDecNumber DecimalDecNumber::operator +() const
{
	if (decNumberIsNaN(&m_value))
	{
		throw("Performing arithmetic on uninitialised decimal [Nan]");
	}

	return DecimalDecNumber(*this);
}
Пример #17
0
const DecimalDecNumber &DecimalDecNumber::operator --()
{
	if (decNumberIsNaN(&m_value))
	{
		throw("Performing arithmetic on uninitialised decimal [Nan]");
	}

   decNumberSubtract(&m_value, &m_value, &ONE.m_value, &m_context);
	return *this;
}
Пример #18
0
DecimalDecNumber DecimalDecNumber::operator -() const
{
	if (decNumberIsNaN(&m_value))
	{
		throw("Performing arithmetic on uninitialised decimal [Nan]");
	}

	DecimalDecNumber temp(*this);
   decNumberCopyNegate(&temp.m_value, &m_value);
	return temp;
}
Пример #19
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;
}
Пример #20
0
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;
}
Пример #21
0
Файл: sign.c Проект: BigEd/wp34s
// 60 bytes
decNumber *decNumberSign(decNumber *r, const decNumber *x) {
	const decNumber *z;

	if (decNumberIsNaN(x))
		z = x;
	else if (dn_eq0(x))
		z = &const_0;
	else if (decNumberIsNegative(x))
		z = &const__1;
	else
		z = &const_1;
	return decNumberCopy(r, z);
}
Пример #22
0
const DecimalDecNumber &DecimalDecNumber::operator /=(const DecimalDecNumber &rhs)
{
	if (decNumberIsNaN(&m_value) || decNumberIsNaN(&rhs.m_value))
	{
		// FTHROW(InvalidStateException, "Performing arithmetic on uninitialised decimal [Nan]");
		throw("Performing arithmetic on uninitialised decimal [Nan]");
	}

   if (decNumberIsZero(&rhs.m_value))
	{
		// FTHROW(LogicError, "Division by zero");
		throw("Division by zero");

	}
	
	if (decNumberIsInfinite(&m_value) || decNumberIsInfinite(&rhs.m_value))
	{
		throw("Cannot divide infinity by infinity");
	}

   decNumberDivide(&m_value, &m_value, &rhs.m_value, &m_context);
	return *this;
}
Пример #23
0
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;
}
Пример #24
0
std::string DecimalDecNumber::toStringAllowScientific(uint32 decimalPlaces) const
{
   if (!isZero() && !isInfinity() && !decNumberIsNaN(&m_value))
   {
      static const int BUFFER_SIZE = 256;
      char buffer[BUFFER_SIZE];
      {
         DecimalDecNumber rounded(*this);
         rounded.round(decimalPlaces, RoundingMode::ROUND_TO_ZERO);
         decNumberToString(&rounded.m_value, buffer);
      }

      char * e = buffer + strlen(buffer);
      char * f = std::find(buffer, e, '+');
      if (f != e)
         return buffer;
   }
   return toString(decimalPlaces);
}
Пример #25
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;
}
Пример #26
0
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;
}
Пример #27
0
bool DecimalDecNumber::isValid() const
{
   return !decNumberIsNaN(&m_value) && !decNumberIsInfinite(&m_value);
}
Пример #28
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;
}
Пример #29
0
// Lalit: toString should "truncate" values rather than round
std::string DecimalDecNumber::toString(uint32 decimalPlaces) const
{
   // Remove these statics if we ever get a short string optimisation in place (gcc 4.1)
   static const std::string zero = "0.0";
   static const std::string posinf = "+INF";
   static const std::string neginf = "-INF";
   static const std::string nan = "NaN";

   if (isZero())
      return zero;
   else if (isInfinity())
   {
      return isNegative() ? neginf : posinf;
   }
   else if (decNumberIsNaN(&m_value))
   {
      // TODO: is it possible to have positive/negative nans?
      return nan;
   }
  
   static const int BUFFER_SIZE = 256;
   char buffer[BUFFER_SIZE];
   {
      DecimalDecNumber rounded(*this);
      rounded.round(decimalPlaces, RoundingMode::ROUND_TO_ZERO);
      decNumberToString(&rounded.m_value, buffer);
   }

   // printf("after round: %s\n", buffer);

   char * b = buffer;
   char * e = buffer + strlen(buffer);
   unpackScientificFormat(b, e, BUFFER_SIZE, decimalPlaces);

   if ((e-b) == 3 && strcmp(buffer, "NaN") == 0)
   {
      return buffer;
   }
   else if (std::find(b, e, '.') == e)
   {
      strcpy(e, ".0");
      return buffer;
   }

   {
      // This code makes the unit tests pass (which were based on the old Decimal implementation)
      // Ensure that there are no trailing zeros, except when the value is an integer, in which case there should be one trailing zero.
      char * lastNonZeroDigitAfterDecimal = e - 1;
      while (*lastNonZeroDigitAfterDecimal == '0')
      {
         --lastNonZeroDigitAfterDecimal;
      }

      if (*lastNonZeroDigitAfterDecimal == '.')
      {
         *(++lastNonZeroDigitAfterDecimal) = '0';
      }
      *(lastNonZeroDigitAfterDecimal + 1) = 0;
   }

   // printf("last return\n");
   return buffer;
}