void mpd_finalize(mpd_t *result, mpd_context_t *ctx) { uint32_t status = 0; mpd_qfinalize(result, ctx, &status); mpd_addstatus_raise(ctx, status); }
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; }
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; }
/* 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); }