summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStefan Krah <skrah@bytereef.org>2012-06-20 21:34:58 (GMT)
committerStefan Krah <skrah@bytereef.org>2012-06-20 21:34:58 (GMT)
commit22385011ed32d528d2d736e60f28d890f17ee122 (patch)
treee7a336da10f2b481ec5ab3baf5d7054da1ef802c
parent42c9b04278205ce0a7d3a91a552d60d7d1eb6d86 (diff)
downloadcpython-22385011ed32d528d2d736e60f28d890f17ee122.zip
cpython-22385011ed32d528d2d736e60f28d890f17ee122.tar.gz
cpython-22385011ed32d528d2d736e60f28d890f17ee122.tar.bz2
Many cleanups of redundant code in mpd_qrem_near():
1) _mpd_qdivmod() uses the context precision only in two places, and the new code should be exactly equivalent to the previous code. 2) Remove misleading comment. 3) The quotient *is* an integer with exponent 0, so calling mpd_qtrunc() is pointless. 4) Replace two instances of identical code by a single one. 5) Use _mpd_cmp_abs() instead of mpd_cmp_total_mag(): the operands are not special. 6) Don't clear MPD_Rounded in the status (with the current code it should not be set within the function).
-rw-r--r--Modules/_decimal/libmpdec/mpdecimal.c38
1 files changed, 15 insertions, 23 deletions
diff --git a/Modules/_decimal/libmpdec/mpdecimal.c b/Modules/_decimal/libmpdec/mpdecimal.c
index 38756e0..09a51fc 100644
--- a/Modules/_decimal/libmpdec/mpdecimal.c
+++ b/Modules/_decimal/libmpdec/mpdecimal.c
@@ -6679,7 +6679,7 @@ mpd_qrem_near(mpd_t *r, const mpd_t *a, const mpd_t *b,
mpd_context_t workctx;
MPD_NEW_STATIC(btmp,0,0,0,0);
MPD_NEW_STATIC(q,0,0,0,0);
- mpd_ssize_t expdiff, floordigits;
+ mpd_ssize_t expdiff, qdigits;
int cmp, isodd, allnine;
if (mpd_isspecial(a) || mpd_isspecial(b)) {
@@ -6716,53 +6716,45 @@ mpd_qrem_near(mpd_t *r, const mpd_t *a, const mpd_t *b,
b = &btmp;
}
- workctx = *ctx;
- workctx.prec = a->digits;
- workctx.prec = (workctx.prec > ctx->prec) ? workctx.prec : ctx->prec;
-
- _mpd_qdivmod(&q, r, a, b, &workctx, status);
- if (mpd_isnan(&q) || mpd_isnan(r) || q.digits > ctx->prec) {
- mpd_seterror(r, MPD_Division_impossible, status);
+ _mpd_qdivmod(&q, r, a, b, ctx, status);
+ if (mpd_isnan(&q) || mpd_isnan(r)) {
goto finish;
}
if (mpd_iszerocoeff(r)) {
goto finish;
}
- /* Deal with cases like rmnx078:
- * remaindernear 999999999.5 1 -> NaN Division_impossible */
expdiff = mpd_adjexp(b) - mpd_adjexp(r);
if (-1 <= expdiff && expdiff <= 1) {
- mpd_qtrunc(&q, &q, &workctx, &workctx.status);
allnine = mpd_coeff_isallnine(&q);
- floordigits = q.digits;
+ qdigits = q.digits;
isodd = mpd_isodd(&q);
mpd_maxcontext(&workctx);
if (mpd_sign(a) == mpd_sign(b)) {
+ /* sign(r) == sign(b) */
_mpd_qsub(&q, r, b, &workctx, &workctx.status);
- if (workctx.status&MPD_Errors) {
- mpd_seterror(r, workctx.status&MPD_Errors, status);
- goto finish;
- }
}
else {
+ /* sign(r) != sign(b) */
_mpd_qadd(&q, r, b, &workctx, &workctx.status);
- if (workctx.status&MPD_Errors) {
- mpd_seterror(r, workctx.status&MPD_Errors, status);
- goto finish;
- }
}
- cmp = mpd_cmp_total_mag(&q, r);
+ if (workctx.status&MPD_Errors) {
+ mpd_seterror(r, workctx.status&MPD_Errors, status);
+ goto finish;
+ }
+
+ cmp = _mpd_cmp_abs(&q, r);
if (cmp < 0 || (cmp == 0 && isodd)) {
- if (allnine && floordigits == ctx->prec) {
+ /* abs(r) > abs(b)/2 or abs(r) == abs(b)/2 and isodd(quotient) */
+ if (allnine && qdigits == ctx->prec) {
+ /* abs(quotient) + 1 == 10**prec */
mpd_seterror(r, MPD_Division_impossible, status);
goto finish;
}
mpd_qcopy(r, &q, status);
- *status &= ~MPD_Rounded;
}
}