diff options
author | vlefevre <vlefevre@280ebfd0-de03-0410-8827-d642c229c3f4> | 2016-06-03 09:21:00 +0000 |
---|---|---|
committer | vlefevre <vlefevre@280ebfd0-de03-0410-8827-d642c229c3f4> | 2016-06-03 09:21:00 +0000 |
commit | 48d7357b564fb208526641a4b415ba20b17e86cb (patch) | |
tree | fc0a956e512e587ee22ff5cb7be230b1f42375c4 | |
parent | ce6db01917269702e951ad9310f68dce26f4f3db (diff) | |
download | mpfr-48d7357b564fb208526641a4b415ba20b17e86cb.tar.gz |
[src/{add,sub}.c] Consider UBF numbers as special cases so that
mpfr_sub1sp and mpfr_add1sp, which do not support UBF, are never
called on UBF numbers. This should also (very slightly) speed up
the normal cases.
git-svn-id: svn://scm.gforge.inria.fr/svn/mpfr/branches/ubf@10416 280ebfd0-de03-0410-8827-d642c229c3f4
-rw-r--r-- | src/add.c | 28 | ||||
-rw-r--r-- | src/sub.c | 30 |
2 files changed, 44 insertions, 14 deletions
@@ -31,7 +31,7 @@ mpfr_add (mpfr_ptr a, mpfr_srcptr b, mpfr_srcptr c, mpfr_rnd_t rnd_mode) mpfr_get_prec (c), mpfr_log_prec, c, rnd_mode), ("a[%Pu]=%.*Rg", mpfr_get_prec (a), mpfr_log_prec, a)); - if (MPFR_ARE_SINGULAR(b,c)) + if (MPFR_ARE_SINGULAR_OR_UBF (b, c)) { if (MPFR_IS_NAN(b) || MPFR_IS_NAN(c)) { @@ -59,7 +59,7 @@ mpfr_add (mpfr_ptr a, mpfr_srcptr b, mpfr_srcptr c, mpfr_rnd_t rnd_mode) MPFR_SET_SAME_SIGN(a, c); MPFR_RET(0); /* exact */ } - /* now either b or c is zero */ + /* now both b and c are finite numbers */ else if (MPFR_IS_ZERO(b)) { if (MPFR_IS_ZERO(c)) @@ -78,15 +78,27 @@ mpfr_add (mpfr_ptr a, mpfr_srcptr b, mpfr_srcptr c, mpfr_rnd_t rnd_mode) } return mpfr_set (a, c, rnd_mode); } - else + else if (MPFR_IS_ZERO(c)) { - MPFR_ASSERTD(MPFR_IS_ZERO(c)); return mpfr_set (a, b, rnd_mode); } + else + { + MPFR_ASSERTD (MPFR_IS_PURE_UBF (b)); + MPFR_ASSERTD (MPFR_IS_PURE_UBF (c)); + /* mpfr_sub1sp and mpfr_add1sp are not intended to support UBF, + for which optimization is less important. */ + if (MPFR_SIGN(b) != MPFR_SIGN(c)) + return mpfr_sub1 (a, b, c, rnd_mode); + else if (MPFR_EXP_LESS_P (b, c)) + return mpfr_add1 (a, c, b, rnd_mode); + else + return mpfr_add1 (a, b, c, rnd_mode); + } } - MPFR_ASSERTD (MPFR_IS_PURE_UBF (b)); - MPFR_ASSERTD (MPFR_IS_PURE_UBF (c)); + MPFR_ASSERTD (MPFR_IS_PURE_FP (b)); + MPFR_ASSERTD (MPFR_IS_PURE_FP (c)); if (MPFR_UNLIKELY(MPFR_SIGN(b) != MPFR_SIGN(c))) { /* signs differ, it is a subtraction */ @@ -100,12 +112,12 @@ mpfr_add (mpfr_ptr a, mpfr_srcptr b, mpfr_srcptr c, mpfr_rnd_t rnd_mode) { /* signs are equal, it's an addition */ if (MPFR_LIKELY(MPFR_PREC(a) == MPFR_PREC(b) && MPFR_PREC(b) == MPFR_PREC(c))) - if (MPFR_EXP_LESS_P (b, c)) + if (MPFR_GET_EXP(b) < MPFR_GET_EXP(c)) return mpfr_add1sp(a, c, b, rnd_mode); else return mpfr_add1sp(a, b, c, rnd_mode); else - if (MPFR_EXP_LESS_P (b, c)) + if (MPFR_GET_EXP(b) < MPFR_GET_EXP(c)) return mpfr_add1(a, c, b, rnd_mode); else return mpfr_add1(a, b, c, rnd_mode); @@ -31,7 +31,7 @@ mpfr_sub (mpfr_ptr a, mpfr_srcptr b, mpfr_srcptr c, mpfr_rnd_t rnd_mode) mpfr_get_prec (c), mpfr_log_prec, c, rnd_mode), ("a[%Pu]=%.*Rg", mpfr_get_prec (a), mpfr_log_prec, a)); - if (MPFR_ARE_SINGULAR (b,c)) + if (MPFR_ARE_SINGULAR_OR_UBF (b,c)) { if (MPFR_IS_NAN (b) || MPFR_IS_NAN (c)) { @@ -72,15 +72,33 @@ mpfr_sub (mpfr_ptr a, mpfr_srcptr b, mpfr_srcptr c, mpfr_rnd_t rnd_mode) else return mpfr_neg (a, c, rnd_mode); } - else + else if (MPFR_IS_ZERO (c)) { - MPFR_ASSERTD (MPFR_IS_ZERO (c)); return mpfr_set (a, b, rnd_mode); } + else + { + MPFR_ASSERTD (MPFR_IS_PURE_UBF (b)); + MPFR_ASSERTD (MPFR_IS_PURE_UBF (c)); + /* mpfr_sub1sp and mpfr_add1sp are not intended to support UBF, + for which optimization is less important. */ + if (MPFR_SIGN(b) == MPFR_SIGN(c)) + return mpfr_sub1 (a, b, c, rnd_mode); + else if (MPFR_EXP_LESS_P (b, c)) + { + int inexact; + rnd_mode = MPFR_INVERT_RND (rnd_mode); + inexact = mpfr_add1 (a, c, b, rnd_mode); + MPFR_CHANGE_SIGN (a); + return -inexact; + } + else + return mpfr_add1 (a, b, c, rnd_mode); + } } - MPFR_ASSERTD (MPFR_IS_PURE_UBF (b)); - MPFR_ASSERTD (MPFR_IS_PURE_UBF (c)); + MPFR_ASSERTD (MPFR_IS_PURE_FP (b)); + MPFR_ASSERTD (MPFR_IS_PURE_FP (c)); if (MPFR_LIKELY (MPFR_SIGN (b) == MPFR_SIGN (c))) { /* signs are equal, it's a real subtraction */ @@ -92,7 +110,7 @@ mpfr_sub (mpfr_ptr a, mpfr_srcptr b, mpfr_srcptr c, mpfr_rnd_t rnd_mode) } else { /* signs differ, it's an addition */ - if (MPFR_EXP_LESS_P (b, c)) + if (MPFR_GET_EXP (b) < MPFR_GET_EXP (c)) { /* exchange rounding modes toward +/- infinity */ int inexact; rnd_mode = MPFR_INVERT_RND (rnd_mode); |