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