Пример #1
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;
}
Пример #2
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;
}
Пример #3
0
static inline int
dfp_compare_op (dfp_binary_func op, DFP_C_TYPE arg_a, DFP_C_TYPE arg_b)
{
  IEEE_TYPE a, b;
  decContext context;
  decNumber arg1, arg2, res;
  int result;

  HOST_TO_IEEE (arg_a, &a);
  HOST_TO_IEEE (arg_b, &b);

  decContextDefault (&context, CONTEXT_INIT);
  context.round = CONTEXT_ROUND;

  TO_INTERNAL (&a, &arg1);
  TO_INTERNAL (&b, &arg2);

  /* Perform the comparison.  */
  op (&res, &arg1, &arg2, &context);

  if (CONTEXT_TRAPS && CONTEXT_ERRORS (context))
    DFP_RAISE (0);

  if (decNumberIsNegative (&res))
    result = -1;
  else if (decNumberIsZero (&res))
    result = 0;
  else
    result = 1;

  return result;
}
Пример #4
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);
}
Пример #5
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;
}
Пример #6
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;
}
Пример #7
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;
}
Пример #8
0
// -------------------------------------
// Appends the digit to the digit list if it's not out of scope.
// Ignores the digit, otherwise.
//
// This function is horribly inefficient to implement with decNumber because
// the digits are stored least significant first, which requires moving all
// existing digits down one to make space for the new one to be appended.
//
void
DigitList::append(char digit)
{
    U_ASSERT(digit>='0' && digit<='9');
    // Ignore digits which exceed the precision we can represent
    //    And don't fix for larger precision.  Fix callers instead.
    if (decNumberIsZero(fDecNumber)) {
        // Zero needs to be special cased because of the difference in the way
        // that the old DigitList and decNumber represent it.
        // digit cout was zero for digitList, is one for decNumber
        fDecNumber->lsu[0] = digit & 0x0f;
        fDecNumber->digits = 1;
        fDecNumber->exponent--;     // To match the old digit list implementation.
    } else {
        int32_t nDigits = fDecNumber->digits;
        if (nDigits < fContext.digits) {
            int i;
            for (i=nDigits; i>0; i--) {
                fDecNumber->lsu[i] = fDecNumber->lsu[i-1];
            }
            fDecNumber->lsu[0] = digit & 0x0f;
            fDecNumber->digits++;
            // DigitList emulation - appending doesn't change the magnitude of existing
            //                       digits.  With decNumber's decimal being after the
            //                       least signficant digit, we need to adjust the exponent.
            fDecNumber->exponent--;
        }
    }
    internalClear();
}
Пример #9
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;
}
Пример #10
0
int32_t
DigitList::getDecimalAt() {
    U_ASSERT((fDecNumber->bits & DECSPECIAL) == 0);  // Not Infinity or NaN
    if (decNumberIsZero(fDecNumber) || ((fDecNumber->bits & DECSPECIAL) != 0)) {
        return fDecNumber->exponent;  // Exponent should be zero for these cases.
    }
    return fDecNumber->exponent + fDecNumber->digits;
}
Пример #11
0
/* Compute a factorial.
 * Currently, only for positive integer arguments.  Needs to be extended
 * to a full gamma function.
 */
decNumber *decNumberFactorial(decNumber *r, const decNumber *x, decContext *ctx) {
	decNumber y, const_1;

	int_to_dn(&const_1, 1, ctx);
	decNumberCopy(&y, x);
	if (!decNumberIsNegative(x) || decNumberIsZero(x)) {
		decNumberCopy(r, &const_1);
		for (;;) {
			if (decNumberIsZero(&y))
				break;
			if (decNumberIsInfinite(r))
				break;
			decNumberMultiply(r, r, &y, ctx);
			decNumberSubtract(&y, &y, &const_1, ctx);
		}
	}
	return r;
}
Пример #12
0
int32_t
DigitList::getCount() const {
    if (decNumberIsZero(fDecNumber) && fDecNumber->exponent==0) {
       // The extra test for exponent==0 is needed because parsing sometimes appends
       // zero digits.  It's bogus, decimalFormatter parsing needs to be cleaned up.
       return 0;
    } else {
       return fDecNumber->digits;
    }
}
Пример #13
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;
}
Пример #14
0
void
DigitList::setDecimalAt(int32_t d) {
    U_ASSERT((fDecNumber->bits & DECSPECIAL) == 0);  // Not Infinity or NaN
    U_ASSERT(d-1>-999999999);
    U_ASSERT(d-1< 999999999);
    int32_t adjustedDigits = fDecNumber->digits;
    if (decNumberIsZero(fDecNumber)) {
        // Account for difference in how zero is represented between DigitList & decNumber.
        adjustedDigits = 0;
    }
    fDecNumber->exponent = d - adjustedDigits;
    internalClear();
}
Пример #15
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;
}
Пример #16
0
// -------------------------------------
//      comparison function.   Returns
//         Not Comparable :  -2
//                      < :  -1
//                     == :   0
//                      > :  +1
int32_t DigitList::compare(const DigitList &other) {
    decNumber   result;
    int32_t     savedDigits = fContext.digits;
    fContext.digits = 1;
    uprv_decNumberCompare(&result, this->fDecNumber, other.fDecNumber, &fContext);
    fContext.digits = savedDigits;
    if (decNumberIsZero(&result)) {
        return 0;
    } else if (decNumberIsSpecial(&result)) {
        return -2;
    } else if (result.bits & DECNEG) {
        return -1;
    } else {
        return 1;
    }
}
Пример #17
0
UBool
DigitList::operator==(const DigitList& that) const
{
    if (this == &that) {
        return TRUE;
    }
    decNumber n;  // Has space for only a none digit value.
    decContext c;
    uprv_decContextDefault(&c, DEC_INIT_BASE);
    c.digits = 1;
    c.traps = 0;

    uprv_decNumberCompare(&n, this->fDecNumber, that.fDecNumber, &c);
    UBool result = decNumberIsZero(&n);
    return result;
}
Пример #18
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);
}
Пример #19
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));
}
Пример #20
0
/**
 * Return true if the number represented by this object can fit into
 * a long.
 */
UBool
DigitList::fitsIntoInt64(UBool ignoreNegativeZero) /*const*/
{
    if (decNumberIsSpecial(this->fDecNumber)) {
        // NaN or Infinity.  Does not fit in int32.
        return FALSE;
    }
    uprv_decNumberTrim(this->fDecNumber);
    if (fDecNumber->exponent < 0) {
        // Number contains fraction digits.
        return FALSE;
    }
    if (decNumberIsZero(this->fDecNumber) && !ignoreNegativeZero &&
        (fDecNumber->bits & DECNEG) != 0) {
        // Negative Zero, not ingored.  Cannot represent as a long.
        return FALSE;
    }
    if (getUpperExponent() < 19) {
        // The number is 18 or fewer digits.
        // The max and min int64 are 19 digts, so this number fits.
        // This is the common case.
        return TRUE;
    }

    // TODO:  Should cache these constants; construction is relatively costly.
    //        But not of huge consequence; they're only needed for 19 digit ints.
    UErrorCode status = U_ZERO_ERROR;
    DigitList min64; min64.set("-9223372036854775808", status);
    if (this->compare(min64) < 0) {
        return FALSE;
    }
    DigitList max64; max64.set("9223372036854775807", status);
    if (this->compare(max64) > 0) {
        return FALSE;
    }
    if (U_FAILURE(status)) {
        return FALSE;
    }
    return true;
}
Пример #21
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;
}
Пример #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
bool DecimalDecNumber::isZero() const
{
   return decNumberIsZero(&m_value);
}
Пример #24
0
// -------------------------------------
UBool
DigitList::isZero() const
{
    return decNumberIsZero(fDecNumber);
}
Пример #25
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;
}
Пример #26
0
/* ------------------------------------------------------------------ */
decimal64 *
decimal64FromNumber (decimal64 * d64, const decNumber *dn, decContext *set)
{
  uInt status = 0;
  Int ae;			/* adjusted exponent */
  decNumber dw;
  decContext dc;
  uInt exp;
  uInt uiwork;
  uInt targhi = 0;
  uInt targlo = 0;
  Int  shift;

  /* If the number has too many digits, or the exponent could be
     out of range then reduce the number under the appropriate
     constraints.  This could push the number to Infinity or zero,
     so this check and rounding must be done before generating the
     decimal64.  */
  ae = dn->exponent + dn->digits - 1;	/* [0 if special] */
  if (dn->digits > DECIMAL64_Pmax	/* too many digits */
      || ae > DECIMAL64_Emax		/* likely overflow */
      || ae < DECIMAL64_Emin)
    {					/* likely underflow */
      decContextDefault (&dc, DEC_INIT_DECIMAL64);
      dc.round = set->round;
      decNumberPlus (&dw, dn, &dc);	/* (round and check) */
      /* [this changes -0 to 0, so enforce the sign...] */
      dw.bits |= dn->bits & DECNEG;
      status = dc.status;
      dn = &dw;
    }

  if (dn->bits & DECSPECIAL)
    {
      if (dn->bits & DECINF)
	targhi = DECIMAL_Inf << 24;
      else
	{
	  /* sNaN or qNaN */
	  if ((*dn->lsu != 0 || dn->digits > 1)	/* non-zero coefficient */
	      && (dn->digits < DECIMAL64_Pmax))
	    decDigitsToBID (dn, &targhi, &targlo);
	  if (dn->bits & DECNAN)
	    targhi |= DECIMAL_NaN << 24;
	  else
	    targhi |= DECIMAL_sNaN << 24;
	}
    }
  else
    {
      /* is finite */
      if (decNumberIsZero (dn))
	{
	  /* set and clamp exponent */
	  if (dn->exponent < -DECIMAL64_Bias)
	    {
	      exp = 0;
	      status |= DEC_Clamped;
	    }
	  else
	    {
	      exp = dn->exponent + DECIMAL64_Bias;
	      if (exp > DECIMAL64_Ehigh)
		{
		  exp = DECIMAL64_Ehigh;
		  status |= DEC_Clamped;
		}
	    }
	}
      else
	{
	  /* non-zero finite number  */
	  exp = (uInt) (dn->exponent + DECIMAL64_Bias);	
	  if (exp > DECIMAL64_Ehigh)
	    {
	      exp = DECIMAL64_Ehigh;
	      status |= DEC_Clamped;
	    }
	  decDigitsToBID (dn, &targhi, &targlo);
        }

      /* Exponent is enconded as:
         - If coefficient fits in 53 bits:
           | sign - 1bit | exponent - 10 bits | coefficient - 53 bits |
	 - Otherwise
           | sign - 1bit | 11 | exponent - 10 bits | coefficient - 51 bits |

	 Since decDigitsToBID will set '11' mask if coefficient does not fit
	 53 bits, we check it to adjust the exponent shift in higher word.  */
      if ((targhi & BID_EXPONENT_ENC_MASK) == BID_EXPONENT_ENC_MASK)
	shift = BID_EXP_SHIFT_LARGE64;
      else
	shift = BID_EXP_SHIFT_SMALL64;

      targhi |= (exp & BID_EXP_MASK64) << shift;
    }

  if (dn->bits & DECNEG)
    targhi |= BID_SIGN_MASK;

  /* now write to storage; this is now always endian */
  UBFROMUIBW (d64->bytes,     targhi);
  UBFROMUIBW (d64->bytes + 4, targlo);

  if (status != 0)
    decContextSetStatus (set, status);
  /*decimal64Show(d64);*/
  return d64;
}