Пример #1
0
void
mpd_finalize(mpd_t *result, mpd_context_t *ctx)
{
	uint32_t status = 0;
	mpd_qfinalize(result, ctx, &status);
	mpd_addstatus_raise(ctx, status);
}
Пример #2
0
static _Decimal128 mpd_to_dec128(mpd_t *in){
  uint64_t exp_part,significand[2];
  uint16_t *bases_data;
  ud128 ret;
  mpd_context_t ctx;
  size_t bases;
  uint32_t status = 0;

  mpd_ieee_context(&ctx,MPD_DECIMAL128);
  mpd_qfinalize(in, &ctx,&status);
  exp_part = in->exp + (uint64_t)mpd_trail_zeros(in) + 6176LL; /* rough guess? */
  in->exp = 0;
  bases = mpd_sizeinbase(in, UINT16_MAX+1);
  bases_data = __mingw_dfp_get_globals()->mpd_callocfunc(bases < 8 ? 8 : bases,sizeof(uint16_t));
  mpd_qexport_u16(bases_data,bases,UINT16_MAX+1,in,&status);
  significand[0] = bases_data[0] | (uint64_t)bases_data[1] << 16 | (uint64_t)bases_data[2] << 32 | (uint64_t)bases_data[3] << 48;
  significand[1] = bases_data[4] | (uint64_t)bases_data[5] << 16 | (uint64_t)bases_data[6] << 32 | (uint64_t)bases_data[7] << 48;
  __mingw_dfp_get_globals()->mpd_free(bases_data);
  ret.t0.sign = mpd_isnegative(in);
  if((significand[1] & (0x7ULL << 57)) == (0x1ULL << 49)) { /* 100 MSB? */
    ret.t2.bits = 0x3;
    ret.t2.mantissaL = significand[0];
    ret.t2.mantissaH = significand[1];
    ret.t2.exponent = exp_part;
  } else {
    ret.t1.mantissaL = significand[0];
    ret.t1.mantissaH = significand[1];
    ret.t1.exponent = exp_part;
  }
  return ret.d;

}
Пример #3
0
static _Decimal64 mpd_to_dec64(mpd_t *in){
  uint64_t exp_part, significand;
  uint32_t status = 0;
  size_t bases;
  uint16_t *bases_data;
  ud64 ret;
  mpd_context_t ctx;

  mpd_ieee_context(&ctx,MPD_DECIMAL64);
  mpd_qfinalize(in, &ctx,&status);

  exp_part = in->exp + (uint64_t)mpd_trail_zeros(in) + 398LL; /* rough guess? */
  in->exp = 0;
  bases = mpd_sizeinbase(in, UINT16_MAX+1);
  bases_data = __mingw_dfp_get_globals()->mpd_callocfunc(bases < 4 ? 4 : bases,sizeof(uint16_t));
  mpd_qexport_u16(bases_data,bases,UINT16_MAX+1,in,&status);
  significand = bases_data[0] | (uint64_t)bases_data[1] << 16 | (uint64_t)bases_data[2] << 32 | (uint64_t)bases_data[3] << 48;
  __mingw_dfp_get_globals()->mpd_free(bases_data);
  ret.t0.sign = mpd_isnegative(in);
  if((significand & (0x7ULL << 51)) == (0x1ULL << 53)) { /* 100 MSB? */
    ret.t2.bits = 0x3;
    ret.t2.mantissa = significand;
    ret.t2.exponent = exp_part;
  } else {
    ret.t1.mantissa = significand;
    ret.t1.exponent = exp_part;
  }
  return ret.d;
}
Пример #4
0
/* convert a character string to a decimal */
void
mpd_qset_string(mpd_t *dec, const char *s, const mpd_context_t *ctx,
                uint32_t *status)
{
    mpd_ssize_t q, r, len;
    const char *coeff, *end;
    const char *dpoint = NULL, *exp = NULL;
    size_t digits;
    uint8_t sign = MPD_POS;

    mpd_set_flags(dec, 0);
    dec->len = 0;
    dec->exp = 0;

    /* sign */
    if (*s == '+') {
        s++;
    }
    else if (*s == '-') {
        mpd_set_negative(dec);
        sign = MPD_NEG;
        s++;
    }

    if (_mpd_strneq(s, "nan", "NAN", 3)) { /* NaN */
        s += 3;
        mpd_setspecial(dec, sign, MPD_NAN);
        if (*s == '\0')
            return;
        /* validate payload: digits only */
        if ((coeff = scan_payload(s, &end)) == NULL)
            goto conversion_error;
        /* payload consists entirely of zeros */
        if (*coeff == '\0')
            return;
        digits = end - coeff;
        /* prec >= 1, clamp is 0 or 1 */
        if (digits > (size_t)(ctx->prec-ctx->clamp))
            goto conversion_error;
    } /* sNaN */
    else if (_mpd_strneq(s, "snan", "SNAN", 4)) {
        s += 4;
        mpd_setspecial(dec, sign, MPD_SNAN);
        if (*s == '\0')
            return;
        /* validate payload: digits only */
        if ((coeff = scan_payload(s, &end)) == NULL)
            goto conversion_error;
        /* payload consists entirely of zeros */
        if (*coeff == '\0')
            return;
        digits = end - coeff;
        if (digits > (size_t)(ctx->prec-ctx->clamp))
            goto conversion_error;
    }
    else if (_mpd_strneq(s, "inf", "INF", 3)) {
        s += 3;
        if (*s == '\0' || _mpd_strneq(s, "inity", "INITY", 6)) {
            /* numeric-value: infinity */
            mpd_setspecial(dec, sign, MPD_INF);
            return;
        }
        goto conversion_error;
    }
    else {
        /* scan for start of coefficient, decimal point, indicator, end */
        if ((coeff = scan_dpoint_exp(s, &dpoint, &exp, &end)) == NULL)
            goto conversion_error;

        /* numeric-value: [exponent-part] */
        if (exp) {
            /* exponent-part */
            end = exp; exp++;
            dec->exp = strtoexp(exp);
            if (errno) {
                if (!(errno == ERANGE &&
                     (dec->exp == MPD_SSIZE_MAX ||
                      dec->exp == MPD_SSIZE_MIN)))
                    goto conversion_error;
            }
        }

            digits = end - coeff;
        if (dpoint) {
            size_t fracdigits = end-dpoint-1;
            if (dpoint > coeff) digits--;

            if (fracdigits > MPD_MAX_PREC) {
                goto conversion_error;
            }
            if (dec->exp < MPD_SSIZE_MIN+(mpd_ssize_t)fracdigits) {
                dec->exp = MPD_SSIZE_MIN;
            }
            else {
                dec->exp -= (mpd_ssize_t)fracdigits;
            }
        }
        if (digits > MPD_MAX_PREC) {
            goto conversion_error;
        }
        if (dec->exp > MPD_EXP_INF) {
            dec->exp = MPD_EXP_INF;
        }
        if (dec->exp == MPD_SSIZE_MIN) {
            dec->exp = MPD_SSIZE_MIN+1;
        }
    }

    _mpd_idiv_word(&q, &r, (mpd_ssize_t)digits, MPD_RDIGITS);

    len = (r == 0) ? q : q+1;
    if (len == 0) {
        goto conversion_error; /* GCOV_NOT_REACHED */
    }
    if (!mpd_qresize(dec, len, status)) {
        mpd_seterror(dec, MPD_Malloc_error, status);
        return;
    }
    dec->len = len;

    string_to_coeff(dec->data, coeff, dpoint, (int)r, len);

    mpd_setdigits(dec);
    mpd_qfinalize(dec, ctx, status);
    return;

conversion_error:
    /* standard wants a positive NaN */
    mpd_seterror(dec, MPD_Conversion_syntax, status);
}