Extending the mpn interface

Niels Möller nisse at lysator.liu.se
Mon Feb 4 11:40:29 CET 2013


nisse at lysator.liu.se (Niels Möller) writes:

> 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 ;-)

Here's a new iteration, which has actually had some testing. I think
I'll be using these functions for now. I really think something similar
should be added to GMP.

Regards,
/Niels

-------------- next part --------------
/* gmp-glue.h */

/* nettle, low-level cryptographics library
 *
 * Copyright (C) 2013 Niels Möller
 *  
 * The nettle library is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation; either version 2.1 of the License, or (at your
 * option) any later version.
 * 
 * The nettle library is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
 * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
 * License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public License
 * along with the nettle library; see the file COPYING.LIB.  If not, write to
 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 * MA 02111-1301, USA.
 */

#ifndef NETTLE_GMP_GLUE_H_INCLUDED
#define NETTLE_GMP_GLUE_H_INCLUDED

#include <gmp.h>

/* Name mangling. */
#define _mpz_cmp_limbs _nettle_mpz_cmp_limbs
#define _mpz_read_limbs _nettle_mpz_read_limbs
#define _mpz_read_limbs_n _nettle_mpz_read_limbs_n
#define _mpz_copy_limbs _nettle_mpz_copy_limbs
#define _mpz_write_limbs _nettle_mpz_write_limbs
#define _mpz_modify_limbs _nettle_mpz_modify_limbs
#define _mpz_done_limbs _nettle_mpz_done_limbs
#define _mpz_init_mpn _nettle_mpz_init_mpn

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

int
_mpz_cmp_limbs (mpz_srcptr a, const mp_limb_t *bp, mp_size_t bn);

/* Read access to mpz numbers. */

/* Return limb pointer, for read-only operations. Use mpz_size to get
   the number of limbs. */
const mp_limb_t *
_mpz_read_limbs (const mpz_srcptr 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. */
const mp_limb_t *
_mpz_read_limbs_n (mpz_ptr x, mp_size_t n);

/* Copy limbs, with zero-padding */
void
_mpz_copy_limbs (mp_limb_t *xp, mpz_srcptr x, mp_size_t n);

/* Write access to mpz numbers. */

/* Get a limb pointer for writing, previous contents may be
   destroyed. */
mp_limb_t *
_mpz_write_limbs (mpz_ptr x, mp_size_t n);

/* Get a limb pointer for writing, previous contents is intact. */
mp_limb_t *
_mpz_modify_limbs (mpz_ptr x, mp_size_t n);

/* Update size. */
void
_mpz_done_limbs (mpz_ptr x, mp_size_t n);


/* Using an mpn number as an mpz. Can be used for read-only access
   only. x must not be cleared or reallocated. */
mpz_srcptr
_mpz_init_mpn (mpz_ptr x, const mp_limb_t *xp, mp_size_t xs);

#endif /* NETTLE_GMP_GLUE_H_INCLUDED */
-------------- next part --------------
/* gmp-glue.c */

/* nettle, low-level cryptographics library
 *
 * Copyright (C) 2013 Niels Möller
 *  
 * The nettle library is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation; either version 2.1 of the License, or (at your
 * option) any later version.
 * 
 * The nettle library is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
 * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
 * License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public License
 * along with the nettle library; see the file COPYING.LIB.  If not, write to
 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 * MA 02111-1301, USA.
 */

#include <assert.h>

#include "gmp-glue.h"

/* This implementation tries to make a minimal use of GMP internals.
   We access and _mp_size and _mp_d, but not _mp_alloc. */

/* Use macros compatible with gmp-impl.h. */
#define ABS(x) ((x) >= 0 ? (x) : -(x))
#define PTR(x) ((x)->_mp_d)
#define SIZ(x) ((x)->_mp_size)
#define ABSIZ(x) ABS (SIZ (x))

#define MPN_NORMALIZE(xp, xn) do {		\
    while ( (xn) > 0 && (xp)[xn-1] == 0)	\
      (xn)--;					\
  }  while (0)

/* NOTE: Makes an unnecessary realloc if allocation is already large
   enough, but looking at _mp_alloc may break in future GMP
   versions. */
#define MPZ_REALLOC(x, n) \
  (ABSIZ(x) >= (n) ? PTR(x) : (_mpz_realloc ((x),(n)), PTR (x)))

#define MPZ_NEWALLOC MPZ_REALLOC

int
_mpz_cmp_limbs (mpz_srcptr a, const mp_limb_t *bp, mp_size_t bn)
{
  mp_size_t an = SIZ (a);
  if (an < bn)
    return -1;
  if (an > bn)
    return 1;
  if (an == 0)
    return 0;

  return mpn_cmp (PTR(a), bp, an);
}


/* Read access to mpz numbers. */

/* Return limb pointer, for read-only operations. Use mpz_size to get
   the number of limbs. */
const mp_limb_t *
_mpz_read_limbs (mpz_srcptr 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. */
const mp_limb_t *
_mpz_read_limbs_n (mpz_ptr x, mp_size_t n)
{
  mp_size_t xn = ABSIZ (x);

  assert (xn <= n);

  if (xn < n)
    {
      /* Makes an unnecessary realloc if allocation is already large
	 enough. */
      mpz_realloc (x, n);
      mpn_zero (PTR(x) + xn, n - xn);
    }

  return PTR(x);
}

void
_mpz_copy_limbs (mp_limb_t *xp, mpz_srcptr x, mp_size_t n)
{
  mp_size_t xn = ABSIZ (x);

  assert (xn <= n);
  mpn_copyi (xp, PTR(x), xn);
  if (xn < n)
    mpn_zero (xp + xn, n - xn);
}

/* Write access to mpz numbers. */

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

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

void
_mpz_done_limbs (mpz_ptr x, mp_size_t n)
{
  assert (n >= 0);
  MPN_NORMALIZE (PTR(x), n);

  SIZ (x) = n;
}

/* Needs some ugly casts. */
mpz_srcptr
_mpz_init_mpn (mpz_ptr x, const mp_limb_t *xp, mp_size_t xs)
{
  mp_size_t xn = ABS (xs);
  
  MPN_NORMALIZE (xp, xn);

  x->_mp_size = xs < 0 ? -xn : xn;
  x->_mp_alloc = 0;
  x->_mp_d = (mp_limb_t *) xp;
  return x;
}
-------------- next part --------------

-- 
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