diff options
author | zimmerma <zimmerma@280ebfd0-de03-0410-8827-d642c229c3f4> | 2016-07-13 14:22:34 +0000 |
---|---|---|
committer | zimmerma <zimmerma@280ebfd0-de03-0410-8827-d642c229c3f4> | 2016-07-13 14:22:34 +0000 |
commit | 7917bbd60f34e2dc521816ba302edee4f2472a40 (patch) | |
tree | 4fa4ccb2ffb71eeaf997813792a0a98d1fd6f42e | |
parent | 213c75399bb7603f9e59d567a6591145f26e70c5 (diff) | |
download | mpfr-7917bbd60f34e2dc521816ba302edee4f2472a40.tar.gz |
[src/div.c] changed __udiv_qrnnd_ld into __udiv_qrnnd_preinv (no dependency
any more on long double)
git-svn-id: svn://scm.gforge.inria.fr/svn/mpfr/trunk@10611 280ebfd0-de03-0410-8827-d642c229c3f4
-rw-r--r-- | src/div.c | 10 | ||||
-rw-r--r-- | src/mpfr-longlong.h | 63 |
2 files changed, 45 insertions, 28 deletions
@@ -270,10 +270,7 @@ mpfr_divsp1 (mpfr_ptr q, mpfr_srcptr u, mpfr_srcptr v, mpfr_rnd_t rnd_mode) if (up[0] >= vp[0]) { - if (MPFR_LDBL_MANT_DIG == 64) - __udiv_qrnnd_ld (h, sb, up[0] - vp[0], vp[0]); - else - udiv_qrnnd (h, sb, up[0] - vp[0], 0, vp[0]); + __udiv_qrnnd_preinv (h, sb, up[0] - vp[0], 0, vp[0]); /* Noting W = 2^GMP_NUMB_BITS, we have up[0]*W = (W + h) * vp[0] + sb, thus up[0]/vp[0] = 1 + h/W + sb/vp[0]/W, with 0 <= sb < vp[0]. */ qx ++; @@ -285,10 +282,7 @@ mpfr_divsp1 (mpfr_ptr q, mpfr_srcptr u, mpfr_srcptr v, mpfr_rnd_t rnd_mode) } else { - if (MPFR_LDBL_MANT_DIG == 64) - __udiv_qrnnd_ld (h, sb, up[0], vp[0]); - else - udiv_qrnnd (h, sb, up[0], 0, vp[0]); + __udiv_qrnnd_preinv (h, sb, up[0], 0, vp[0]); rb = h & (MPFR_LIMB_ONE << (sh - 1)); sb |= (h & mask) ^ rb; qp[0] = h & ~mask; diff --git a/src/mpfr-longlong.h b/src/mpfr-longlong.h index 7a707ecbd..affb1b62c 100644 --- a/src/mpfr-longlong.h +++ b/src/mpfr-longlong.h @@ -2095,34 +2095,57 @@ extern __longlong_h_C UWtype mpn_udiv_qrnnd_r (UWtype, UWtype, UWtype, UWtype *) } while (0) /* beginning of code specific to MPFR */ -/* Same as __udiv_qrnnd_c, using "long double" (assuming 64-bit significand), - and assuming n0 = 0. */ -#define __udiv_qrnnd_ld(q, r, n1, d) \ +/* Same as __udiv_qrnnd_c, but using a single UWtype/UWtype division */ +/* instead of two. */ +#define __udiv_qrnnd_preinv(q, r, n1, n0, d) \ do { \ - UWtype __q, __h, __l; \ - long double __Q, __N1, __D; \ + UWtype __d1, __d0, __q1, __q0, __r1, __r0, __m, __i; \ \ ASSERT ((d) != 0); \ ASSERT ((n1) < (d)); \ \ - __N1 = 18446744073709551616.0 /* 2^64 */ * (long double) (n1); \ - __D = (long double) (d); \ + __d1 = __ll_highpart (d); \ + __d0 = __ll_lowpart (d); \ + __i = ~(UWtype) 0 / __d1; \ + \ + __q1 = (((n1) >> (W_TYPE_SIZE / 2)) * __i) >> (W_TYPE_SIZE / 2); \ + __r1 = (n1) - __q1 * __d1; \ + while (__r1 >= __d1) \ + { \ + __q1 ++; \ + __r1 -= __d1; \ + } \ + __m = __q1 * __d0; \ + __r1 = __r1 << (W_TYPE_SIZE / 2) | __ll_highpart (n0); \ + if (__r1 < __m) \ + { \ + __q1--, __r1 += (d); \ + if (__r1 >= (d)) /* i.e. we didn't get carry when adding to __r1 */\ + if (__r1 < __m) \ + __q1--, __r1 += (d); \ + } \ + __r1 -= __m; \ \ - __Q = __N1 / __D; \ - /* either __Q is the quotient rounded toward zero, in which case */ \ - /* it is exactly what we want, or it is rounded away from zero, */ \ - /* then subtracting 1 to __q should give the quotient rounded */ \ - /* toward zero. */ \ - __q = (UWtype) __Q; \ - umul_ppmm (__h, __l, __q, (d)); \ - if (__h > (n1) || (__h == (n1) && __l > 0)) \ + __q0 = ((__r1 >> (W_TYPE_SIZE / 2)) * __i) >> (W_TYPE_SIZE / 2); \ + __r0 = __r1 - __q0 * __d1; \ + while (__r0 >= __d1) \ { \ - __q--; \ - __h -= (__l < (d)); \ - __l -= (d); \ + __q0 ++; \ + __r0 -= __d1; \ } \ - (q) = __q; \ - (r) = -__l; \ + __m = __q0 * __d0; \ + __r0 = __r0 << (W_TYPE_SIZE / 2) | __ll_lowpart (n0); \ + if (__r0 < __m) \ + { \ + __q0--, __r0 += (d); \ + if (__r0 >= (d)) \ + if (__r0 < __m) \ + __q0--, __r0 += (d); \ + } \ + __r0 -= __m; \ + \ + (q) = __q1 * __ll_B | __q0; \ + (r) = __r0; \ } while (0) /* end of code specific to MPFR */ |