void mpz_divexact (mpz_ptr quot, mpz_srcptr num, mpz_srcptr den) { mp_ptr qp; mp_size_t qn; mp_srcptr np, dp; mp_size_t nn, dn; TMP_DECL; #if WANT_ASSERT { mpz_t rem; mpz_init (rem); mpz_tdiv_r (rem, num, den); ASSERT (SIZ(rem) == 0); mpz_clear (rem); } #endif nn = ABSIZ (num); dn = ABSIZ (den); if (nn < dn) { /* This special case avoids segfaults below when the function is incorrectly called with |N| < |D|, N != 0. It also handles the well-defined case N = 0. */ SIZ(quot) = 0; return; } qn = nn - dn + 1; TMP_MARK; if (quot == num || quot == den) qp = TMP_ALLOC_LIMBS (qn); else qp = MPZ_REALLOC (quot, qn); np = PTR(num); dp = PTR(den); mpn_divexact (qp, np, nn, dp, dn); MPN_NORMALIZE (qp, qn); if (qp != PTR(quot)) MPN_COPY (MPZ_REALLOC (quot, qn), qp, qn); SIZ(quot) = (SIZ(num) ^ SIZ(den)) >= 0 ? qn : -qn; TMP_FREE; }
/* Computes |v| = |(g - u a)| / b, where u may be positive or negative, and v is of the opposite sign. a, b are of size n, u and v at most size n, and v must have space for n+1 limbs. */ static mp_size_t compute_v (mp_ptr vp, mp_srcptr ap, mp_srcptr bp, mp_size_t n, mp_srcptr gp, mp_size_t gn, mp_srcptr up, mp_size_t usize, mp_ptr tp) { mp_size_t size; mp_size_t an; mp_size_t bn; mp_size_t vn; ASSERT (n > 0); ASSERT (gn > 0); ASSERT (usize != 0); size = ABS (usize); ASSERT (size <= n); an = n; MPN_NORMALIZE (ap, an); if (an >= size) mpn_mul (tp, ap, an, up, size); else mpn_mul (tp, up, size, ap, an); size += an; size -= tp[size - 1] == 0; ASSERT (gn <= size); if (usize > 0) { /* |v| = -v = (u a - g) / b */ ASSERT_NOCARRY (mpn_sub (tp, tp, size, gp, gn)); MPN_NORMALIZE (tp, size); if (size == 0) return 0; } else { /* usize < 0 */ /* |v| = v = (c - u a) / b = (c + |u| a) / b */ mp_limb_t cy = mpn_add (tp, tp, size, gp, gn); if (cy) tp[size++] = cy; } /* Now divide t / b. There must be no remainder */ bn = n; MPN_NORMALIZE (bp, bn); ASSERT (size >= bn); vn = size + 1 - bn; ASSERT (vn <= n + 1); mpn_divexact (vp, tp, size, bp, bn); vn -= (vp[vn-1] == 0); return vn; }