mini-gmp

Zimmermann Paul Paul.Zimmermann at inria.fr
Sat Jan 18 18:52:12 UTC 2014


       Niels,

> > The most wanted are the mpn division functions, I wonder why those functions
> > are not exported.
> 
> I think the main reason is that the interface of the internal division
> functions in mini-gmp, in particular mpn_div_qr, is quite different from
> the older interface used in gmp. And gmp is slowly moving towards an
> interface more like the one in mini-gmp. So when the real gmp gets a
> public function mpn_div_qr, mini-gmp's version should also be exported,
> and we should make sure that it's compatible.
> 
> Precisely which division functions are you missing? mpn_tdiv_qr? It
> would make some sense to add an mpn_tdiv_qr to mini-gmp, as a small
> wrapper around mpn_div_qr.

I know the division interface will change for GMP 6 :-)

Here are the division functions I had to re-implement on top of mini-gmp
(I know mpn_divrem is obsolete, but its interface is better suited for MPFR):

#ifdef WANT_mpn_divrem_1
mp_limb_t
mpn_divrem_1 (mp_limb_t *qp, mp_size_t qxn, mp_limb_t *np, mp_size_t nn,
              mp_limb_t d0)
{
  mpz_t q, r, n, d;
  mp_limb_t ret, dd[1];

  d->_mp_d = dd;
  d->_mp_d[0] = d0;
  d->_mp_size = 1;
  mpz_init (q);
  mpz_init (r);
  if (qxn == 0)
    {
      n->_mp_d = np;
      n->_mp_size = nn;
    }
  else
    {
      mpz_init2 (n, (nn + qxn) * GMP_NUMB_BITS);
      mpn_copyi (n->_mp_d + qxn, np, nn);
      mpn_zero (n->_mp_d, qxn);
      n->_mp_size = nn + qxn;
    }
  mpz_tdiv_qr (q, r, n, d);
  if (q->_mp_size > 0)
    mpn_copyi (qp, q->_mp_d, q->_mp_size);
  if (q->_mp_size < nn + qxn)
    mpn_zero (qp + q->_mp_size, nn + qxn - q->_mp_size);
  ret = (r->_mp_size == 1) ? r->_mp_d[0] : 0;
  mpz_clear (q);
  mpz_clear (r);
  if (qxn != 0)
    mpz_clear (n);
  return ret;
}
#endif

#ifdef WANT_mpn_divrem
mp_limb_t
mpn_divrem (mp_limb_t *qp, mp_size_t qn, mp_limb_t *np,
            mp_size_t nn, const mp_limb_t *dp, mp_size_t dn)
{
  mpz_t q, r, n, d;
  mp_limb_t ret;

  MPFR_ASSERTN(qn == 0);
  qn = nn - dn;
  n->_mp_d = np;
  n->_mp_size = nn;
  d->_mp_d = (mp_limb_t*) dp;
  d->_mp_size = dn;
  mpz_init (q);
  mpz_init (r);
  mpz_tdiv_qr (q, r, n, d);
  MPFR_ASSERTN(q->_mp_size == qn || q->_mp_size == qn + 1);
  mpn_copyi (qp, q->_mp_d, qn);
  ret = (q->_mp_size == qn) ? 0 : q->_mp_d[qn];
  if (r->_mp_size > 0)
    mpn_copyi (np, r->_mp_d, r->_mp_size);
  if (r->_mp_size < dn)
    mpn_zero (np + r->_mp_size, dn - r->_mp_size);
  mpz_clear (q);
  mpz_clear (r);
  return ret;
}
#endif

#ifdef WANT_mpn_tdiv_qr
void
mpn_tdiv_qr (mp_limb_t *QP, mp_limb_t *RP, mp_size_t QXN,
             const mp_limb_t *NP, mp_size_t NN,
             const mp_limb_t *DP, mp_size_t DN)
{
  mpz_t q, r, n, d;

  MPFR_ASSERTN(QXN == 0);
  n->_mp_d = (mp_limb_t*) NP;
  n->_mp_size = NN;
  d->_mp_d = (mp_limb_t*) DP;
  d->_mp_size = DN;
  mpz_init (q);
  mpz_init (r);
  mpz_tdiv_qr (q, r, n, d);
  MPFR_ASSERTN(q->_mp_size > 0);
  mpn_copyi (QP, q->_mp_d, q->_mp_size);
  if (q->_mp_size < NN - DN + 1)
    mpn_zero (QP + q->_mp_size, NN - DN + 1 - q->_mp_size);
  if (r->_mp_size > 0)
    mpn_copyi (RP, r->_mp_d, r->_mp_size);
  if (r->_mp_size < DN)
    mpn_zero (RP + r->_mp_size, DN - r->_mp_size);
  mpz_clear (q);
  mpz_clear (r);
}
#endif

Paul


More information about the gmp-devel mailing list