Beispiel #1
0
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;
}
Beispiel #2
0
/* 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;
}