=================================================================== RCS file: /home/cvs/OpenXM_contrib/gmp/mpn/generic/Attic/divrem_2.c,v retrieving revision 1.1 retrieving revision 1.1.1.2 diff -u -p -r1.1 -r1.1.1.2 --- OpenXM_contrib/gmp/mpn/generic/Attic/divrem_2.c 2000/09/09 14:12:24 1.1 +++ OpenXM_contrib/gmp/mpn/generic/Attic/divrem_2.c 2003/08/25 16:06:20 1.1.1.2 @@ -7,8 +7,8 @@ RELEASE. -Copyright (C) 1993, 1994, 1995, 1996, 1999, 2000 Free Software Foundation, -Inc. +Copyright 1993, 1994, 1995, 1996, 1999, 2000, 2001, 2002 Free Software +Foundation, Inc. This file is part of the GNU MP Library. @@ -31,6 +31,20 @@ MA 02111-1307, USA. */ #include "gmp-impl.h" #include "longlong.h" + +/* The size where udiv_qrnnd_preinv should be used rather than udiv_qrnnd, + meaning the quotient size where that should happen, the quotient size + being how many udiv divisions will be done. + + The default is to use preinv always, CPUs where this doesn't suit have + tuned thresholds. Note in particular that preinv should certainly be + used if that's the only division available (USE_PREINV_ALWAYS). */ + +#ifndef DIVREM_2_THRESHOLD +#define DIVREM_2_THRESHOLD 0 +#endif + + /* Divide num (NP/NSIZE) by den (DP/2) and write the NSIZE-2 least significant quotient limbs at QP and the 2 long remainder at NP. If QEXTRA_LIMBS is @@ -48,27 +62,25 @@ MA 02111-1307, USA. */ 3. NSIZE >= 2, even if QEXTRA_LIMBS is non-zero. */ mp_limb_t -#if __STDC__ mpn_divrem_2 (mp_ptr qp, mp_size_t qxn, - mp_ptr np, mp_size_t nsize, + mp_ptr np, mp_size_t nn, mp_srcptr dp) -#else -mpn_divrem_2 (qp, qxn, np, nsize, dp) - mp_ptr qp; - mp_size_t qxn; - mp_ptr np; - mp_size_t nsize; - mp_srcptr dp; -#endif { mp_limb_t most_significant_q_limb = 0; mp_size_t i; mp_limb_t n1, n0, n2; mp_limb_t d1, d0; mp_limb_t d1inv; - int have_preinv; + int use_preinv; - np += nsize - 2; + ASSERT (nn >= 2); + ASSERT (qxn >= 0); + ASSERT (dp[1] & GMP_NUMB_HIGHBIT); + ASSERT (! MPN_OVERLAP_P (qp, nn-2+qxn, np, nn) || qp+2 >= np); + ASSERT_MPN (np, nn); + ASSERT_MPN (dp, 2); + + np += nn - 2; d1 = dp[1]; d0 = dp[0]; n1 = np[1]; @@ -76,23 +88,21 @@ mpn_divrem_2 (qp, qxn, np, nsize, dp) if (n1 >= d1 && (n1 > d1 || n0 >= d0)) { +#if GMP_NAIL_BITS == 0 sub_ddmmss (n1, n0, n1, n0, d1, d0); +#else + n0 = n0 - d0; + n1 = n1 - d1 - (n0 >> GMP_LIMB_BITS - 1); + n0 &= GMP_NUMB_MASK; +#endif most_significant_q_limb = 1; } - /* If multiplication is much faster than division, preinvert the most - significant divisor limb before entering the loop. */ - if (UDIV_TIME > 2 * UMUL_TIME + 6) - { - have_preinv = 0; - if ((UDIV_TIME - (2 * UMUL_TIME + 6)) * (nsize - 2) > UDIV_TIME) - { - invert_limb (d1inv, d1); - have_preinv = 1; - } - } + use_preinv = ABOVE_THRESHOLD (qxn + nn - 2, DIVREM_2_THRESHOLD); + if (use_preinv) + invert_limb (d1inv, d1); - for (i = qxn + nsize - 2 - 1; i >= 0; i--) + for (i = qxn + nn - 2 - 1; i >= 0; i--) { mp_limb_t q; mp_limb_t r; @@ -104,27 +114,35 @@ mpn_divrem_2 (qp, qxn, np, nsize, dp) if (n1 == d1) { - /* Q should be either 111..111 or 111..110. Need special treatment + /* Q should be either 111..111 or 111..110. Need special handling of this rare case as normal division would give overflow. */ - q = ~(mp_limb_t) 0; + q = GMP_NUMB_MASK; - r = n0 + d1; + r = (n0 + d1) & GMP_NUMB_MASK; if (r < d1) /* Carry in the addition? */ { +#if GMP_NAIL_BITS == 0 add_ssaaaa (n1, n0, r - d0, np[0], 0, d0); +#else + n0 = np[0] + d0; + n1 = (r - d0 + (n0 >> GMP_NUMB_BITS)) & GMP_NUMB_MASK; + n0 &= GMP_NUMB_MASK; +#endif qp[i] = q; continue; } n1 = d0 - (d0 != 0); - n0 = -d0; + n0 = -d0 & GMP_NUMB_MASK; } else { - if (UDIV_TIME > 2 * UMUL_TIME + 6 && have_preinv) + if (use_preinv) udiv_qrnnd_preinv (q, r, n1, n0, d1, d1inv); else - udiv_qrnnd (q, r, n1, n0, d1); - umul_ppmm (n1, n0, d0, q); + udiv_qrnnd (q, r, n1, n0 << GMP_NAIL_BITS, d1 << GMP_NAIL_BITS); + r >>= GMP_NAIL_BITS; + umul_ppmm (n1, n0, d0, q << GMP_NAIL_BITS); + n0 >>= GMP_NAIL_BITS; } n2 = np[0]; @@ -135,14 +153,26 @@ mpn_divrem_2 (qp, qxn, np, nsize, dp) /* The estimated Q was too large. */ q--; +#if GMP_NAIL_BITS == 0 sub_ddmmss (n1, n0, n1, n0, 0, d0); +#else + n0 = n0 - d0; + n1 = n1 - (n0 >> GMP_LIMB_BITS - 1); + n0 &= GMP_NUMB_MASK; +#endif r += d1; if (r >= d1) /* If not carry, test Q again. */ goto q_test; } qp[i] = q; +#if GMP_NAIL_BITS == 0 sub_ddmmss (n1, n0, r, n2, n1, n0); +#else + n0 = n2 - n0; + n1 = r - n1 - (n0 >> GMP_LIMB_BITS - 1); + n0 &= GMP_NUMB_MASK; +#endif } np[1] = n1; np[0] = n0;