summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorvlefevre <vlefevre@280ebfd0-de03-0410-8827-d642c229c3f4>2016-06-03 09:21:00 +0000
committervlefevre <vlefevre@280ebfd0-de03-0410-8827-d642c229c3f4>2016-06-03 09:21:00 +0000
commit48d7357b564fb208526641a4b415ba20b17e86cb (patch)
treefc0a956e512e587ee22ff5cb7be230b1f42375c4
parentce6db01917269702e951ad9310f68dce26f4f3db (diff)
downloadmpfr-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.c28
-rw-r--r--src/sub.c30
2 files changed, 44 insertions, 14 deletions
diff --git a/src/add.c b/src/add.c
index 43a4507d1..969a64d0a 100644
--- a/src/add.c
+++ b/src/add.c
@@ -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);
diff --git a/src/sub.c b/src/sub.c
index f6a4e16d5..c95cfdb0a 100644
--- a/src/sub.c
+++ b/src/sub.c
@@ -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);