diff --git a/mpn/generic/sb_divappr_q.c b/mpn/generic/sb_divappr_q.c index dc4033bf..d41a4c41 100644 --- a/mpn/generic/sb_divappr_q.c +++ b/mpn/generic/sb_divappr_q.c @@ -108,7 +108,7 @@ mpn_sb_divappr_q (mp_ptr qp, qn++; dp = dp + dn - qn - 1; /* make dp length qn + 1 */ - for ( ; qn > 0; qn--) + for ( ; qn > 1; qn--) { /* fetch next word */ cy = np[0]; @@ -139,8 +139,39 @@ mpn_sb_divappr_q (mp_ptr qp, qp[qn - 1] = q; dp++; } + + if (qn > 0) + { + /* fetch next word */ + cy = np[0]; + + np--; + /* rare case where truncation ruins normalisation */ + if (cy > dp[1] || (cy == dp[1] && np[0] >= dp[0])) + { + __divappr_helper(qp, np - 1, dp, 1); + return qh; + } + + mpir_divapprox32_preinv2(q, cy, np[0], d1inv); + + /* np -= dp*q */ + cy -= mpn_submul_1(np - 1, dp, 2, q); + + /* correct if remainder is too large */ + if (UNLIKELY(cy || np[0] >= dp[1])) + { + if (cy || mpn_cmp(np - 1, dp, 2) >= 0) + { + q++; + cy -= mpn_sub_n(np - 1, np - 1, dp, 2); + } + } + + qp[0] = q; + } + np[1] = cy; - } else { diff --git a/mpn/generic/tdiv_q.c b/mpn/generic/tdiv_q.c index 22e4ed95..6df70f07 100644 --- a/mpn/generic/tdiv_q.c +++ b/mpn/generic/tdiv_q.c @@ -167,8 +167,7 @@ mpn_tdiv_q (mp_ptr qp, } else /* divisor is already normalised */ { - if (new_np != np) - MPN_COPY (new_np, np, nn); + MPN_COPY (new_np, np, nn); if (dn == 2) { @@ -203,12 +202,7 @@ mpn_tdiv_q (mp_ptr qp, new_np = scratch; new_nn = 2 * qn + 1; - if (new_np == np) - /* We need {np,nn} to remain untouched until the final adjustment, so - we need to allocate separate space for new_np. */ - new_np = TMP_ALLOC_LIMBS (new_nn + 1); - - + dh = dp[dn - 1]; if (LIKELY ((dh & GMP_NUMB_HIGHBIT) == 0)) { @@ -286,7 +280,7 @@ mpn_tdiv_q (mp_ptr qp, } MPN_COPY (qp, tp + 1, qn); - if (tp[0] <= 4) + if (UNLIKELY(tp[0] <= 4)) { mp_size_t rn;