Extending the mpn interface

Niels Möller nisse at lysator.liu.se
Wed Jan 30 22:19:40 CET 2013


Emmanuel Thomé <emmanuel.thome at gmail.com> writes:

> I've too been traveling with MPZ_SET_MPN, MPN_SET_MPZ, MPN_NORMALIZE
> macros/functions and so on, for quite some time now.

Here's a sketch (totally untested, not even compiled), supporting the
operations I have seen a need for. As usual, good naming is the
difficult part ;-)

I think it makes some sense to use an _mpz prefix on the functions,
following _mpz_realloc rather than mpz_size.

Regards,
/Niels

/* Some functions for interfacing between mpz and mpn code. Signs of
   the mpz numbers are generally ignored. */

/* We already have mpz_size (which might be better named _mpz_size).
   And _mpz_realloc, which isn't quite what we need, but which could
   be used to implement this interface without relying on the
   MPZ_*ALLOC macros. */

/* This could be rewritten to access _mp_size and _mp_d (but not
   _mp_alloc) directly, and use _mpz_realloc for increasing allocation
   size when needed. That should be fairly portable between GMP
   releases, I think. */

/* Read access to mpz numbers. */

/* Return limb pointer, for read-only operations. Use mpz_size to get
   the number of limbs. */
mp_srcptr 
_mpz_read_limbs (const mpz_t x)
{
  return PTR (x);
}

/* Get a pointer to an n limb area, for read-only operation. n must be
   greater or equal to the current size, and the mpz is zero-padded if
   needed. */
mp_srcptr
_mpz_read_limbs_n (mpz_t x, mp_size_t n)
{
  mp_size_t xn = ABSSIZ (x);
  mp_ptr xp;

  ASSERT (xn <= n);

  xp = MPZ_REALLOC (x, n);
  if (xn < n)
    mpn_zero (xp + xn, n - xn);

  return xp;
}

/* Write access to mpz numbers. */

/* Get a limb pointer for writing, previous contents may be
   destroyed. */
mpz_ptr
_mpz_write_limbs (mpz_t x, mp_size_t n)
{
  ASSERT (n > 0);
  return MPZ_NEWALLOC (x, n);
}

/* Get a limb pointer for writing, previous contents is intact. */
mpz_ptr
_mpz_modify_limbs (mpz_t x, mp_size_t n)
{
  ASSERT (n > 0);  
  return MPZ_REALLOC (x, n);
}

void
_mpz_done_limbs (mpz_t x, mp_size_t n)
{
  ASSERT (n >= 0);
  MPN_NORMALIZE (PTR (x), n);
  SIZ (x) = n;
}

/* Using an mpn number as an mpz. Can be used for read-only access
   only. x must not be cleared or reallocated. I'd like to mark the
   date as const in some way, but that won't quite work. */
void
_mpz_init_mpn (mpz_t x, mp_ptr *xp, mp_size_t xs)
{
  mp_size_t xn = ABS (xs);
  MPN_NORMALIZE (x, xn);

  x->_mp_size = xs < 0 ? -xn : xn;
  x->_mp_alloc = 0;
  x->_mp_d = xp;
}

-- 
Niels Möller. PGP-encrypted email is preferred. Keyid C0B98E26.
Internet email is subject to wholesale government surveillance.


More information about the gmp-devel mailing list