diff options
-rw-r--r-- | mpf/sub.c | 72 |
1 files changed, 23 insertions, 49 deletions
@@ -1,6 +1,6 @@ /* mpf_sub -- Subtract two floats. -Copyright 1993-1996, 1999-2002, 2004, 2005, 2011 Free Software Foundation, Inc. +Copyright 1993-1996, 1999-2002, 2004, 2005, 2011, 2014 Free Software Foundation, Inc. This file is part of the GNU MP Library. @@ -92,7 +92,7 @@ mpf_sub (mpf_ptr r, mpf_srcptr u, mpf_srcptr v) rp = r->_mp_d; prec = r->_mp_prec + 1; exp = u->_mp_exp; - ediff = u->_mp_exp - v->_mp_exp; + ediff = exp - v->_mp_exp; /* If ediff is 0 or 1, we might have a situation where the operands are extremely close. We need to scan the operands from the most significant @@ -102,10 +102,8 @@ mpf_sub (mpf_ptr r, mpf_srcptr u, mpf_srcptr v) if (ediff == 0) { /* Skip leading limbs in U and V that are equal. */ - if (up[usize - 1] == vp[vsize - 1]) - { /* This loop normally exits immediately. Optimize for that. */ - do + while (up[usize - 1] == vp[vsize - 1]) { usize--; vsize--; @@ -138,8 +136,6 @@ mpf_sub (mpf_ptr r, mpf_srcptr u, mpf_srcptr v) goto cancellation; } } - while (up[usize - 1] == vp[vsize - 1]); - } if (up[usize - 1] < vp[vsize - 1]) { @@ -192,8 +188,7 @@ mpf_sub (mpf_ptr r, mpf_srcptr u, mpf_srcptr v) exp--; } } - - if (usize > prec - 1) + else if (usize > prec - 1) { up += usize - (prec - 1); usize = prec - 1; @@ -209,32 +204,18 @@ mpf_sub (mpf_ptr r, mpf_srcptr u, mpf_srcptr v) mp_limb_t cy_limb; if (vsize == 0) { - mp_size_t size, i; - size = usize; - for (i = 0; i < size; i++) - tp[i] = up[i]; - tp[size] = 1; - rsize = size + 1; + MPN_COPY (tp, up, usize); + tp[usize] = 1; + rsize = usize + 1; exp++; - goto normalize; + goto normalized; } if (usize == 0) { - mp_size_t size, i; - size = vsize; - for (i = 0; i < size; i++) - tp[i] = ~vp[i] & GMP_NUMB_MASK; - cy_limb = 1 - mpn_add_1 (tp, tp, vsize, (mp_limb_t) 1); + cy_limb = mpn_neg (tp, vp, vsize); rsize = vsize; - if (cy_limb == 0) - { - tp[rsize] = 1; - rsize++; - exp++; - } - goto normalize; } - if (usize >= vsize) + else if (usize >= vsize) { /* uuuu */ /* vv */ @@ -248,13 +229,10 @@ mpf_sub (mpf_ptr r, mpf_srcptr u, mpf_srcptr v) { /* uuuu */ /* vvvvvvv */ - mp_size_t size, i; + mp_size_t size; size = vsize - usize; - for (i = 0; i < size; i++) - tp[i] = ~vp[i] & GMP_NUMB_MASK; - cy_limb = mpn_sub_n (tp + size, up, vp + size, usize); - cy_limb+= mpn_sub_1 (tp + size, tp + size, usize, (mp_limb_t) 1); - cy_limb-= mpn_add_1 (tp, tp, vsize, (mp_limb_t) 1); + cy_limb = mpn_neg (tp, vp, size); + cy_limb = mpn_sub_nc (tp + size, up, vp + size, usize, cy_limb); rsize = vsize; } if (cy_limb == 0) @@ -262,6 +240,7 @@ mpf_sub (mpf_ptr r, mpf_srcptr u, mpf_srcptr v) tp[rsize] = 1; rsize++; exp++; + goto normalized; } goto normalize; } @@ -348,13 +327,10 @@ general_case: { /* uuuu */ /* vvvvvvv */ - mp_size_t size, i; + mp_size_t size; size = vsize - usize; - tp[0] = -vp[0] & GMP_NUMB_MASK; - for (i = 1; i < size; i++) - tp[i] = ~vp[i] & GMP_NUMB_MASK; - mpn_sub_n (tp + size, up, vp + size, usize); - mpn_sub_1 (tp + size, tp + size, usize, (mp_limb_t) 1); + ASSERT_CARRY (mpn_neg (tp, vp, size)); + mpn_sub_nc (tp + size, up, vp + size, usize, CNST_LIMB (1)); rsize = vsize; } } @@ -374,13 +350,12 @@ general_case: { /* uuuu */ /* vvvvv */ - mp_size_t size, i; + mp_size_t size; size = vsize + ediff - usize; - tp[0] = -vp[0] & GMP_NUMB_MASK; - for (i = 1; i < size; i++) - tp[i] = ~vp[i] & GMP_NUMB_MASK; + ASSERT_CARRY (mpn_neg (tp, vp, size)); mpn_sub (tp + size, up, usize, vp + size, usize - ediff); - mpn_sub_1 (tp + size, tp + size, usize, (mp_limb_t) 1); + /* Should we use sub_nc then sub_1? */ + MPN_DECR_U (tp + size, usize, CNST_LIMB (1)); rsize = vsize + ediff; } } @@ -391,9 +366,7 @@ general_case: /* vv */ mp_size_t size, i; size = vsize + ediff - usize; - tp[0] = -vp[0] & GMP_NUMB_MASK; - for (i = 1; i < vsize; i++) - tp[i] = ~vp[i] & GMP_NUMB_MASK; + ASSERT_CARRY (mpn_neg (tp, vp, vsize)); for (i = vsize; i < size; i++) tp[i] = GMP_NUMB_MAX; mpn_sub_1 (tp + size, up, usize, (mp_limb_t) 1); @@ -407,6 +380,7 @@ general_case: rsize--; exp--; } + normalized: MPN_COPY (rp, tp, rsize); } |