summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorzimmerma <zimmerma@280ebfd0-de03-0410-8827-d642c229c3f4>2016-07-13 14:22:34 +0000
committerzimmerma <zimmerma@280ebfd0-de03-0410-8827-d642c229c3f4>2016-07-13 14:22:34 +0000
commit7917bbd60f34e2dc521816ba302edee4f2472a40 (patch)
tree4fa4ccb2ffb71eeaf997813792a0a98d1fd6f42e
parent213c75399bb7603f9e59d567a6591145f26e70c5 (diff)
downloadmpfr-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.c10
-rw-r--r--src/mpfr-longlong.h63
2 files changed, 45 insertions, 28 deletions
diff --git a/src/div.c b/src/div.c
index 0a473bd86..d9f9109ba 100644
--- a/src/div.c
+++ b/src/div.c
@@ -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 */