Beispiel #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;
}
Beispiel #2
0
Datei: agm.c Projekt: 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);
}
Beispiel #3
0
INT_TYPE
DFP_TO_INT (DFP_C_TYPE x)
{
  /* decNumber's decimal* types have the same format as C's _Decimal*
     types, but they have different calling conventions.  */

  IEEE_TYPE s;
  char buf[BUFMAX];
  char *pos;
  decNumber qval, n1, n2;
  decContext context;

  decContextDefault (&context, CONTEXT_INIT);
  /* Need non-default rounding mode here.  */
  context.round = DEC_ROUND_DOWN;

  HOST_TO_IEEE (x, &s);
  TO_INTERNAL (&s, &n1);
  /* Rescale if the exponent is less than zero.  */
  decNumberToIntegralValue (&n2, &n1, &context);
  /* Get a value to use for the quantize call.  */
  decNumberFromString (&qval, (char *) "1.0", &context);
  /* Force the exponent to zero.  */
  decNumberQuantize (&n1, &n2, &qval, &context);
  /* This is based on text in N1107 section 5.1; it might turn out to be
     undefined behavior instead.  */
  if (context.status & DEC_Invalid_operation)
    {
#if defined (L_sd_to_si) || defined (L_dd_to_si) || defined (L_td_to_si)
      if (decNumberIsNegative(&n2))
        return INT_MIN;
      else
        return INT_MAX;
#elif defined (L_sd_to_di) || defined (L_dd_to_di) || defined (L_td_to_di)
      if (decNumberIsNegative(&n2))
        /* Find a defined constant that will work here.  */
        return (-9223372036854775807LL - 1LL);
      else
        /* Find a defined constant that will work here.  */
        return 9223372036854775807LL;
#elif defined (L_sd_to_usi) || defined (L_dd_to_usi) || defined (L_td_to_usi)
      return UINT_MAX;
#elif defined (L_sd_to_udi) || defined (L_dd_to_udi) || defined (L_td_to_udi)
        /* Find a defined constant that will work here.  */
      return 18446744073709551615ULL;
#endif
    }
  /* Get a string, which at this point will not include an exponent.  */
  decNumberToString (&n1, buf);
  /* Ignore the fractional part.  */
  pos = strchr (buf, '.');
  if (pos)
    *pos = 0;
  /* Use a C library function to convert to the integral type.  */
  return STR_TO_INT (buf, NULL, 10);
}
Beispiel #4
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;
}
/**
 *  convert this number to an int64_t.   Truncate if there is a fractional part.
 *  Return zero if the number cannot be represented.
 */
int64_t DigitList::getInt64() /*const*/ {
    if(fHave==kInt64) {
      return fUnion.fInt64;
    } 
    // Truncate if non-integer.
    // Return 0 if out of range.
    // Range of in64_t is -9223372036854775808 to 9223372036854775807  (19 digits)
    //
    if (fDecNumber->digits + fDecNumber->exponent > 19) {
        // Overflow, absolute value too big.
        return 0;
    }

    // The number of integer digits may differ from the number of digits stored
    //   in the decimal number.
    //     for 12.345  numIntDigits = 2, number->digits = 5
    //     for 12E4    numIntDigits = 6, number->digits = 2
    // The conversion ignores the fraction digits in the first case,
    // and fakes up extra zero digits in the second.
    // TODO:  It would be faster to store a table of powers of ten to multiply by
    //        instead of looping over zero digits, multiplying each time.

    int32_t numIntDigits = fDecNumber->digits + fDecNumber->exponent;
    uint64_t value = 0;
    for (int32_t i = 0; i < numIntDigits; i++) {
        // Loop is iterating over digits starting with the most significant.
        // Numbers are stored with the least significant digit at index zero.
        int32_t digitIndex = fDecNumber->digits - i - 1;
        int32_t v = (digitIndex >= 0) ? fDecNumber->lsu[digitIndex] : 0;
        value = value * (uint64_t)10 + (uint64_t)v;
    }

    if (decNumberIsNegative(fDecNumber)) {
        value = ~value;
        value += 1;
    }
    int64_t svalue = (int64_t)value;

    // Check overflow.  It's convenient that the MSD is 9 only on overflow, the amount of
    //                  overflow can't wrap too far.  The test will also fail -0, but
    //                  that does no harm; the right answer is 0.
    if (numIntDigits == 19) {
        if (( decNumberIsNegative(fDecNumber) && svalue>0) ||
            (!decNumberIsNegative(fDecNumber) && svalue<0)) {
            svalue = 0;
        }
    }
        
    return svalue;
}
Beispiel #6
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;
}
Beispiel #7
0
Datei: agm.c Projekt: BigEd/wp34s
void cmplxAGM(decNumber *rx, decNumber *ry,
		const decNumber *a, const decNumber *b,
		const decNumber *c, const decNumber *d) {
	decNumber x1, x2, y1, y2, t1, t2, u1, u2;
	int n;

	if (decNumberIsSpecial(a) || decNumberIsSpecial(b) ||
			decNumberIsSpecial(c) || decNumberIsSpecial(d)) {
			goto nan;
	}
	cmplxCopy(&x1, &x2, a, b);
	cmplxCopy(&y1, &y2, c, d);
	for (n=0; n<1000; n++) {
		cmplxSubtract(&t1, &t2, &x1, &x2, &y1, &y2);
		cmplxR(&u1, &t1, &t2);
		dn_compare(&u2, &u1, &const_1e_32);
		if (decNumberIsNegative(&u2)) {
			cmplxCopy(rx, ry, &x1, &x2);
			return;
		}

		cmplxAdd(&t1, &t2, &x1, &x2, &y1, &y2);
		cmplxDiv2(&u1, &u2, &t1, &t2);

		cmplxMultiply(&t1, &t2, &x1, &x2, &y1, &y2);
		cmplxSqrt(&y1, &y2, &t1, &t2);

		cmplxCopy(&x1, &x2, &u1, &u2);
	}
nan:	cmplx_NaN(rx, ry);
}
Beispiel #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;
}
Beispiel #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;
}
Beispiel #10
0
static void
decimal_to_decnumber (const REAL_VALUE_TYPE *r, decNumber *dn)
{
  decContext set;
  decContextDefault (&set, DEC_INIT_DECIMAL128);
  set.traps = 0;

  switch (r->cl)
    {
    case rvc_zero:
      decNumberZero (dn);
      break;
    case rvc_inf:
      decNumberFromString (dn, (char *)"Infinity", &set);
      break;
    case rvc_nan:
      if (r->signalling)
        decNumberFromString (dn, (char *)"snan", &set);
      else
        decNumberFromString (dn, (char *)"nan", &set);
      break;
    case rvc_normal:
      gcc_assert (r->decimal);
      decimal128ToNumber ((decimal128 *) r->sig, dn);
      break;
    default:
      gcc_unreachable ();
    }

  /* Fix up sign bit.  */
  if (r->sign != decNumberIsNegative (dn))
    dn->bits ^= DECNEG;
}
Beispiel #11
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);
}
Beispiel #12
0
/* Take a matrix descriptor and return the base register number.
 * Optionally return the number of rows and columns in the matrix.
 * Optionally return the sign of the initial descriptor as well.
 */
static int matrix_decompose(const decNumber *x, int *rows, int *cols, int *up) {
    decNumber ax, y;
    unsigned int n, base;
    int r, c, u;

    if (decNumberIsNegative(x)) {
        dn_abs(&ax, x);
        x = &ax;
        u = 0;
    } else
        u = 1;
    if (up)		*up = u;

    dn_mulpow10(&y, x, 4);
    n = dn_to_int(&y);
    base = n / 10000;
    c = n % 100;
    r = (n / 100) % 100;
    if (c == 0)
        c = r;
    if (! matrix_range_check(base, r, c))
        return -1;
    if (c == 0) {
        err(ERR_BAD_PARAM);
        return -1;
    }
    if (rows)	*rows = r;
    if (cols)	*cols = c;
    return base;
}
Beispiel #13
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;
}
Beispiel #14
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);

    decContextDefault (&context, DEFAULT_CONTEXT);
    if (decNumberIsInfinite (&dn_x))
    {
        if (decNumberIsNegative (&dn_x))
            result = -M_PI_2dl;
        else
            result = M_PI_2dl;
    }
    else
    {
        decNumberAtan (&dn_result, &dn_x, &context);
        FUNC_CONVERT_FROM_DN (&dn_result, &result, &context);
    }

    return result;
}
Beispiel #15
0
Datei: dfp.c Projekt: AHelper/gcc
static void
decimal_to_decnumber (const REAL_VALUE_TYPE *r, decNumber *dn)
{
  decContext set;
  decContextDefault (&set, DEC_INIT_DECIMAL128);
  set.traps = 0;

  switch (r->cl)
    {
    case rvc_zero:
      decNumberZero (dn);
      break;
    case rvc_inf:
      decNumberFromString (dn, "Infinity", &set);
      break;
    case rvc_nan:
      if (r->signalling)
        decNumberFromString (dn, "snan", &set);
      else
        decNumberFromString (dn, "nan", &set);
      break;
    case rvc_normal:
      if (!r->decimal)
	{
	  /* dconst{1,2,m1,half} are used in various places in
	     the middle-end and optimizers, allow them here
	     as an exception by converting them to decimal.  */
	  if (memcmp (r, &dconst1, sizeof (*r)) == 0)
	    {
	      decNumberFromString (dn, "1", &set);
	      break;
	    }
	  if (memcmp (r, &dconst2, sizeof (*r)) == 0)
	    {
	      decNumberFromString (dn, "2", &set);
	      break;
	    }
	  if (memcmp (r, &dconstm1, sizeof (*r)) == 0)
	    {
	      decNumberFromString (dn, "-1", &set);
	      break;
	    }
	  if (memcmp (r, &dconsthalf, sizeof (*r)) == 0)
	    {
	      decNumberFromString (dn, "0.5", &set);
	      break;
	    }
	  gcc_unreachable ();
	}
      decimal128ToNumber ((const decimal128 *) r->sig, dn);
      break;
    default:
      gcc_unreachable ();
    }

  /* Fix up sign bit.  */
  if (r->sign != decNumberIsNegative (dn))
    dn->bits ^= DECNEG;
}
/**
 * Currently, getDouble() depends on atof() to do its conversion.
 *
 * WARNING!!
 * This is an extremely costly function. ~1/2 of the conversion time
 * can be linked to this function.
 */
double
DigitList::getDouble() const
{
    // TODO:  fix thread safety.  Can probably be finessed some by analyzing
    //        what public const functions can see which DigitLists.
    //        Like precompute fDouble for DigitLists coming in from a parse
    //        or from a Formattable::set(), but not for any others.
    if (fHaveDouble) {
        return fDouble;
    }
    DigitList *nonConstThis = const_cast<DigitList *>(this);

    if (isZero()) {
        nonConstThis->fDouble = 0.0;
        if (decNumberIsNegative(fDecNumber)) {
            nonConstThis->fDouble /= -1;
        }
    } else if (isInfinite()) {
        if (std::numeric_limits<double>::has_infinity) {
            nonConstThis->fDouble = std::numeric_limits<double>::infinity();
        } else {
            nonConstThis->fDouble = std::numeric_limits<double>::max();
        }
        if (!isPositive()) {
            nonConstThis->fDouble = -fDouble;
        } 
    } else {
        MaybeStackArray<char, MAX_DBL_DIGITS+18> s;
           // Note:  14 is a  magic constant from the decNumber library documentation,
           //        the max number of extra characters beyond the number of digits 
           //        needed to represent the number in string form.  Add a few more
           //        for the additional digits we retain.

        // Round down to appx. double precision, if the number is longer than that.
        // Copy the number first, so that we don't modify the original.
        if (getCount() > MAX_DBL_DIGITS + 3) {
            DigitList numToConvert(*this);
            numToConvert.reduce();    // Removes any trailing zeros, so that digit count is good.
            numToConvert.round(MAX_DBL_DIGITS+3);
            uprv_decNumberToString(numToConvert.fDecNumber, s);
            // TODO:  how many extra digits should be included for an accurate conversion?
        } else {
            uprv_decNumberToString(this->fDecNumber, s);
        }
        U_ASSERT(uprv_strlen(&s[0]) < MAX_DBL_DIGITS+18);
        
        loadDecimalChar();
        if (gDecimal != '.') {
            char *decimalPt = strchr(s, '.');
            if (decimalPt != NULL) {
                *decimalPt = gDecimal;
            }
        }
        char *end = NULL;
        nonConstThis->fDouble = uprv_strtod(s, &end);
    }
    nonConstThis->fHaveDouble = TRUE;
    return fDouble;
}
Beispiel #17
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));
}
Beispiel #18
0
DEC_TYPE
INTERNAL_FUNCTION_NAME (DEC_TYPE x, DEC_TYPE y)
{
  decContext context;
  DEC_TYPE result;
  decNumber dn_x;
  decNumber dn_y;

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

  if(decNumberIsNegative (&dn_x) != decNumberIsNegative (&dn_y))
    decNumberNegate (&dn_x);

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

  return result;
}
Beispiel #19
0
int64_t DigitList::getInt64() /*const*/ {
    // Round if non-integer.   (Truncate or round?)
    // Return 0 if out of range.
    // Range of in64_t is -9223372036854775808 to 9223372036854775807  (19 digits)
    //
    if (fDecNumber->digits + fDecNumber->exponent > 19) {
        // Overflow, absolute value too big.
        return 0;
    }
    decNumber *workingNum = fDecNumber;

    if (fDecNumber->exponent != 0) {
        // Force to an integer, with zero exponent, rounding if necessary.
        DigitList copy(*this);
        DigitList zero;
        uprv_decNumberQuantize(copy.fDecNumber, copy.fDecNumber, zero.fDecNumber, &fContext);
        workingNum = copy.fDecNumber;
    }

    uint64_t value = 0;
    int32_t numDigits = workingNum->digits;
    for (int i = numDigits-1; i>=0 ; --i) {
        int v = workingNum->lsu[i];
        value = value * (uint64_t)10 + (uint64_t)v;
    }
    if (decNumberIsNegative(workingNum)) {
        value = ~value;
        value += 1;
    }
    int64_t svalue = (int64_t)value;

    // Check overflow.  It's convenient that the MSD is 9 only on overflow, the amount of
    //                  overflow can't wrap too far.  The test will also fail -0, but
    //                  that does no harm; the right answer is 0.
    if (numDigits == 19) {
        if (( decNumberIsNegative(fDecNumber) && svalue>0) ||
            (!decNumberIsNegative(fDecNumber) && svalue<0)) {
            svalue = 0;
        }
    }
        
    return svalue;
}
Beispiel #20
0
/**
 * Currently, getDouble() depends on strtod() to do its conversion.
 *
 * WARNING!!
 * This is an extremely costly function. ~1/2 of the conversion time
 * can be linked to this function.
 */
double
DigitList::getDouble() const
{
    {
        Mutex mutex;
        if (fHave == kDouble) {
            return fUnion.fDouble;
        }
    }

    double tDouble = 0.0;
    if (isZero()) {
        tDouble = 0.0;
        if (decNumberIsNegative(fDecNumber)) {
            tDouble /= -1;
        }
    } else if (isInfinite()) {
        if (std::numeric_limits<double>::has_infinity) {
            tDouble = std::numeric_limits<double>::infinity();
        } else {
            tDouble = std::numeric_limits<double>::max();
        }
        if (!isPositive()) {
            tDouble = -tDouble; //this was incorrectly "-fDouble" originally.
        }
    } else {
        MaybeStackArray<char, MAX_DBL_DIGITS+18> s;
           // Note:  14 is a  magic constant from the decNumber library documentation,
           //        the max number of extra characters beyond the number of digits
           //        needed to represent the number in string form.  Add a few more
           //        for the additional digits we retain.

        // Round down to appx. double precision, if the number is longer than that.
        // Copy the number first, so that we don't modify the original.
        if (getCount() > MAX_DBL_DIGITS + 3) {
            DigitList numToConvert(*this);
            numToConvert.reduce();    // Removes any trailing zeros, so that digit count is good.
            numToConvert.round(MAX_DBL_DIGITS+3);
            uprv_decNumberToString(numToConvert.fDecNumber, s.getAlias());
            // TODO:  how many extra digits should be included for an accurate conversion?
        } else {
            uprv_decNumberToString(this->fDecNumber, s.getAlias());
        }
        U_ASSERT(uprv_strlen(&s[0]) < MAX_DBL_DIGITS+18);

        char *end = NULL;
        tDouble = decimalStrToDouble(s.getAlias(), &end);
    }
    {
        Mutex mutex;
        DigitList *nonConstThis = const_cast<DigitList *>(this);
        nonConstThis->internalSetDouble(tDouble);
    }
    return tDouble;
}
Beispiel #21
0
/* Convert a decimal real to a date.
 * We have to honour the current date mode and make sure that things
 * don't go out of range.
 */
static int extract_date(const decNumber *x, int *year, int *month, int *day) {
	int ip, fp, y, m, d;
	decNumber z, a;
    int neg = 1;

	if (is_intmode())
		return 1;

	if (decNumberIsNegative(x)) {
		dn_minus(&z, x);
        neg = -1;
	} else {
		decNumberCopy(&z, x);
	}
	decNumberTrunc(&a, &z);			// a = iii	z = iii.ffrrrr
	ip = dn_to_int(&a);
	dn_subtract(&a, &z, &a);		// a = .ffrrrr
	dn_mul100(&z, &a);			// z = ff.rrrr
	decNumberTrunc(&a, &z);			// a = ff
	fp = dn_to_int(&a);
	dn_subtract(&z, &z, &a);		// z = .rrrr
	switch (UState.date_mode) {
	default:
	case DATE_YMD:
		y = ip;
		m = fp;
		dn_mul100(&a, &z);
		decNumberTrunc(&z, &a);
		d = dn_to_int(&z);
		break;

	case DATE_DMY:
		d = ip;
		m = fp;
		goto year;

	case DATE_MDY:
		m = ip;
		d = fp;
year:		dn_mulpow10(&a, &z, 4);
		decNumberTrunc(&z, &a);
		y = dn_to_int(&z);
		break;
	}
	/* Make sense of things
	 */
    y *= neg;
	if (year != NULL)
		*year = y;
	if (month != NULL)
		*month = m;
	if (day != NULL)
		*day = d;
	return check_date(y, m, d);
}
Beispiel #22
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;
}
Beispiel #23
0
// 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);
}
Beispiel #24
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;
}
Beispiel #25
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);
}
Beispiel #26
0
void convertToIntX<int64>(const decNumber* pDecNum, decContext* pContext, int64& result)
{
	static const uint64 s_arrPowerOfTen[19] = {
			1, 10, 100, 1000, 10000, 100000, 1000000,
			10000000, 100000000, 1000000000, 10000000000ULL,
			100000000000ULL, 1000000000000ULL, 10000000000000ULL,
			100000000000000ULL, 1000000000000000ULL, 10000000000000000ULL,
			100000000000000000ULL, 1000000000000000000ULL };

	if (decNumberIsSpecial(pDecNum))
	{
		char sNumber[1024];
		throw("Attempt to get an integer from invalid number");
	}
	else if (pDecNum->exponent != 0)
	{
		char sNumber[1024];
		// FTHROW(InvalidArgumentException, "Unsupported exponent %d, only zero exponent is supported, number %s", pDecNum->exponent, decNumberToString(pDecNum, sNumber));
		throw("Unsupported exponent , only zero exponent is supported, number ");
	}
	else if (pDecNum->digits > (int)(sizeof(s_arrPowerOfTen)/sizeof(*s_arrPowerOfTen)))
	{
		char sNumber[1024];
		// FTHROW(InvalidArgumentException, "Overflow during conversion, number of digits is %d, number %s", pDecNum->digits, decNumberToString(pDecNum, sNumber));
		throw("Overflow during conversion, number of digits is number ");
	}
	const decNumberUnit* pDigit = pDecNum->lsu;
	uint64 nUnsignedResult = 0;
	const bool isNegative = decNumberIsNegative(pDecNum);
	const uint64 nMaxValue = isNegative ? -std::numeric_limits<int64>::min() : std::numeric_limits<int64>::max();

	for (int i = 0; i < pDecNum->digits; ++pDigit, i += DECDPUN)
	{
			const uint64 nPrev = nUnsignedResult;														// to be able to check on 'overflow'
			nUnsignedResult += *pDigit * s_arrPowerOfTen[i];
			if ((nUnsignedResult < nPrev) || (nUnsignedResult > nMaxValue))
			{
				char sNumber[1024];
				throw("Overflow during conversion, step");
				// FTHROW(InvalidArgumentException, "Overflow during conversion, step %d (%llu, %llu, %llu), number %s",
				// 		i, nUnsignedResult, nPrev, nMaxValue, decNumberToString(pDecNum, sNumber));
			}
	}
	result = isNegative ? -((int64)nUnsignedResult) : (int64)nUnsignedResult;
}
Beispiel #27
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;
}
/**
 * Currently, getDouble() depends on strtod() to do its conversion.
 *
 * WARNING!!
 * This is an extremely costly function. ~1/2 of the conversion time
 * can be linked to this function.
 */
double
DigitList::getDouble() const
{
    static char gDecimal = 0;
    char decimalSeparator;
    {
        Mutex mutex;
        if (fHave == kDouble) {
            return fUnion.fDouble;
        } else if(fHave == kInt64) {
            return (double)fUnion.fInt64;
        }
        decimalSeparator = gDecimal;
    }

    if (decimalSeparator == 0) {
        // We need to know the decimal separator character that will be used with strtod().
        // Depends on the C runtime global locale.
        // Most commonly is '.'
        // TODO: caching could fail if the global locale is changed on the fly.
        char rep[MAX_DIGITS];
        sprintf(rep, "%+1.1f", 1.0);
        decimalSeparator = rep[2];
    }

    double tDouble = 0.0;
    if (isZero()) {
        tDouble = 0.0;
        if (decNumberIsNegative(fDecNumber)) {
            tDouble /= -1;
        }
    } else if (isInfinite()) {
        if (std::numeric_limits<double>::has_infinity) {
            tDouble = std::numeric_limits<double>::infinity();
        } else {
            tDouble = std::numeric_limits<double>::max();
        }
        if (!isPositive()) {
            tDouble = -tDouble; //this was incorrectly "-fDouble" originally.
        } 
    } else {
        MaybeStackArray<char, MAX_DBL_DIGITS+18> s;
           // Note:  14 is a  magic constant from the decNumber library documentation,
           //        the max number of extra characters beyond the number of digits 
           //        needed to represent the number in string form.  Add a few more
           //        for the additional digits we retain.

        // Round down to appx. double precision, if the number is longer than that.
        // Copy the number first, so that we don't modify the original.
        if (getCount() > MAX_DBL_DIGITS + 3) {
            DigitList numToConvert(*this);
            numToConvert.reduce();    // Removes any trailing zeros, so that digit count is good.
            numToConvert.round(MAX_DBL_DIGITS+3);
            uprv_decNumberToString(numToConvert.fDecNumber, s);
            // TODO:  how many extra digits should be included for an accurate conversion?
        } else {
            uprv_decNumberToString(this->fDecNumber, s);
        }
        U_ASSERT(uprv_strlen(&s[0]) < MAX_DBL_DIGITS+18);
        
        if (decimalSeparator != '.') {
            char *decimalPt = strchr(s, '.');
            if (decimalPt != NULL) {
                *decimalPt = decimalSeparator;
            }
        }
        char *end = NULL;
        tDouble = uprv_strtod(s, &end);
    }
    {
        Mutex mutex;
        DigitList *nonConstThis = const_cast<DigitList *>(this);
        nonConstThis->internalSetDouble(tDouble);
        gDecimal = decimalSeparator;
    }
    return tDouble;
}
Beispiel #29
0
/* Smart CDF helper routine that return three values */ 
void cdf_Q_helper(enum nilop op) {
	decNumber a, b, t, u, x2, d, absx, x;
	int i;

	getX(&x);
	dn_abs(&absx, &x);
	if (dn_lt(&absx, &const_2_326)) {
		decNumberSquare(&x2, &absx);
		decNumberCopy(&t, &absx);
		decNumberCopy(&a, &absx);
		decNumberCopy(&d, &const_3);
		for (i=0;i<500; i++) {
			dn_multiply(&u, &t, &x2);
			dn_divide(&t, &u, &d);
			dn_add(&u, &a, &t);
			if (dn_eq(&u, &a))
				break;
			decNumberCopy(&a, &u);
			dn_p2(&d, &d);
		}
		decNumberCopy(&b, &const_0_5);
		if (decNumberIsNegative(&x))
			dn_minus(&a, &a);
	} else {
		const decNumber *nom, *extra, *sub;
		//dn_minus(&x2, &absx);
		//n = ceil(extra + nom / (|x| - sub))
		if (is_usrdblmode()) {
			sub = &const_1_5;
			nom = &const_300;
			extra = &const_8;
		}
		else {
			sub = &const_1_3;
			nom = &const_100;
			extra = &const_4;
		}
		dn_subtract(&b, &absx, sub);
		dn_divide(&t, nom, &b);
		dn_add(&u, &t, extra);
		decNumberCeil(&b, &u);
		decNumberZero(&t);
		do {
			dn_add(&u, &x, &t);
			dn_divide(&t, &b, &u);
			dn_dec(&b);
		} while (! dn_eq0(&b));

		dn_add(&u, &t, &x);
		decNumberRecip(&a, &u);

		if (decNumberIsNegative(&a)) {
			dn_minus(&a, &a);
			decNumberZero(&b);
		} else {
			dn_1(&b);
			dn_minus(&a, &a);
		}
	}
	pdf_Q(&t, &x);
	setXYZ(&t, &a, &b);
}
Beispiel #30
0
void dn_elliptic(decNumber *sn, decNumber *cn, decNumber *dn, const decNumber *u, const decNumber *m) {
	decNumber a, b, e, f, g;
	decNumber s_n, c_n, d_n;
	decNumber MU[ELLIPTIC_N], NU[ELLIPTIC_N], C[ELLIPTIC_N], D[ELLIPTIC_N];
	decNumber sin_umu, cos_umu, t, r;
	int n = 0;
	
#define mu(n)	(MU + (n))
#define nu(n)	(NU + (n))
#define c(n)	(C + (n))
#define d(n)	(D + (n))

	if (sn == NULL) sn = &s_n;
	if (cn == NULL) cn = &c_n;
	if (dn == NULL) dn = &d_n;

	dn_abs(&a, m);
	if (dn_lt(&const_1, &a)) {
		cmplx_NaN(sn, cn);
		set_NaN(dn);
		return;
	}
	if (dn_lt(&a, &const_1e_32)) {
		dn_sincos(u, sn, cn);
		dn_1(dn);
		return;
	}
	dn_m1(&a, m);
	if (dn_abs_lt(&a, &const_1e_32)) {
		dn_sinhcosh(u, &a, &b);
		decNumberRecip(cn, &b);
		dn_multiply(sn, &a, cn);
		decNumberCopy(dn, cn);
		return;
	}
	dn_1(mu(0));
	dn_1m(&a, m);
	dn_sqrt(nu(0), &a);
	for (;;) {
		dn_add(&g, mu(n), nu(n));
		dn_abs(&a, &g);
		dn_mulpow10(&b, &a, 32);
		dn_mul2(&a, &b);
		dn_subtract(&e, mu(n), nu(n));
		dn_abs(&f, &e);
		if (dn_gt(&a, &f))
			break;
		dn_div2(mu(n+1), &g);
		dn_multiply(&a, mu(n), nu(n));
		dn_sqrt(nu(n+1), &a);
		n++;
		if (n >= ELLIPTIC_N-1)
			break;
	}

	dn_multiply(&a, u, mu(n));
	dn_sincos(&a, &sin_umu, &cos_umu);
	if (dn_abs_lt(&sin_umu, dn_abs(&b, &cos_umu)))
		dn_divide(&t, &sin_umu, &cos_umu);
	else
		dn_divide(&t, &cos_umu, &sin_umu);

	dn_multiply(c(n), mu(n), &t);
	dn_1(d(n));

	while (n > 0) {
		n--;
		dn_multiply(c(n), d(n+1), c(n+1));
		decNumberSquare(&a, c(n+1));
		dn_divide(&r, &a, mu(n+1));
		dn_add(&a, &r, nu(n));
		dn_add(&b, &r, mu(n));
		dn_divide(d(n), &a, &b);
	}
	cmplxAbs(&f, &b, &const_1, c(0));
	if (decNumberIsNegative(&e)) {
		dn_1m(&a, m);
		dn_sqrt(&g, &a);
		dn_divide(dn, &g, d(0));

		dn_divide(cn, dn, &f);
		if (decNumberIsNegative(&cos_umu))
			dn_minus(cn, cn);

		dn_divide(&a, c(0), &g);
		dn_multiply(sn, cn, &a);
	} else {
		decNumberCopy(dn, d(0));

		dn_divide(sn, &const_1, &f);
		if (decNumberIsNegative(&sin_umu))
			dn_minus(sn, sn);
		dn_multiply(cn, c(0), sn);
	}
#undef mu
#undef nu
#undef c
#undef d
}