#if HAVE_CONFIG_H
# include "config.h"
#endif
#include <assert.h>
#include <stdlib.h>
#include "gmp-glue.h"
#if !GMP_HAVE_mpz_limbs_read
#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)
#define MPZ_REALLOC(x, n) \
(ABSIZ(x) >= (n) ? PTR(x) : (_mpz_realloc ((x),(n)), PTR (x)))
#define MPZ_NEWALLOC MPZ_REALLOC
const mp_limb_t *
mpz_limbs_read (mpz_srcptr x)
{
return PTR (x);
}
mp_limb_t *
mpz_limbs_write (mpz_ptr x, mp_size_t n)
{
assert (n > 0);
return MPZ_NEWALLOC (x, n);
}
mp_limb_t *
mpz_limbs_modify (mpz_ptr x, mp_size_t n)
{
assert (n > 0);
return MPZ_REALLOC (x, n);
}
void
mpz_limbs_finish (mpz_ptr x, mp_size_t n)
{
assert (n >= 0);
MPN_NORMALIZE (PTR(x), n);
SIZ (x) = n;
}
mpz_srcptr
mpz_roinit_n (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;
}
#endif
void
cnd_swap (mp_limb_t cnd, mp_limb_t *ap, mp_limb_t *bp, mp_size_t n)
{
mp_limb_t mask = - (mp_limb_t) (cnd != 0);
mp_size_t i;
for (i = 0; i < n; i++)
{
mp_limb_t a, b, t;
a = ap[i];
b = bp[i];
t = (a ^ b) & mask;
ap[i] = a ^ t;
bp[i] = b ^ t;
}
}
int
mpz_limbs_cmp (mpz_srcptr a, const mp_limb_t *bp, mp_size_t bn)
{
mp_size_t an = mpz_size (a);
assert (mpz_sgn (a) >= 0);
assert (bn >= 0);
if (an < bn)
return -1;
if (an > bn)
return 1;
if (an == 0)
return 0;
return mpn_cmp (mpz_limbs_read(a), bp, an);
}
const mp_limb_t *
mpz_limbs_read_n (mpz_ptr x, mp_size_t n)
{
mp_size_t xn = mpz_size (x);
mp_ptr xp;
assert (xn <= n);
xp = mpz_limbs_modify (x, n);
if (xn < n)
mpn_zero (xp + xn, n - xn);
return xp;
}
void
mpz_limbs_copy (mp_limb_t *xp, mpz_srcptr x, mp_size_t n)
{
mp_size_t xn = mpz_size (x);
assert (xn <= n);
mpn_copyi (xp, mpz_limbs_read (x), xn);
if (xn < n)
mpn_zero (xp + xn, n - xn);
}
void
mpz_set_n (mpz_t r, const mp_limb_t *xp, mp_size_t xn)
{
mpn_copyi (mpz_limbs_write (r, xn), xp, xn);
mpz_limbs_finish (r, xn);
}
void
mpn_set_base256 (mp_limb_t *rp, mp_size_t rn,
const uint8_t *xp, size_t xn)
{
size_t xi;
mp_limb_t out;
unsigned bits;
for (xi = xn, out = bits = 0; xi > 0 && rn > 0; )
{
mp_limb_t in = xp[--xi];
out |= (in << bits) & GMP_NUMB_MASK;
bits += 8;
if (bits >= GMP_NUMB_BITS)
{
*rp++ = out;
rn--;
bits -= GMP_NUMB_BITS;
out = in >> (8 - bits);
}
}
if (rn > 0)
{
*rp++ = out;
if (--rn > 0)
mpn_zero (rp, rn);
}
}
void
mpn_set_base256_le (mp_limb_t *rp, mp_size_t rn,
const uint8_t *xp, size_t xn)
{
size_t xi;
mp_limb_t out;
unsigned bits;
for (xi = 0, out = bits = 0; xi < xn && rn > 0; )
{
mp_limb_t in = xp[xi++];
out |= (in << bits) & GMP_NUMB_MASK;
bits += 8;
if (bits >= GMP_NUMB_BITS)
{
*rp++ = out;
rn--;
bits -= GMP_NUMB_BITS;
out = in >> (8 - bits);
}
}
if (rn > 0)
{
*rp++ = out;
if (--rn > 0)
mpn_zero (rp, rn);
}
}
void
mpn_get_base256 (uint8_t *rp, size_t rn,
const mp_limb_t *xp, mp_size_t xn)
{
unsigned bits;
mp_limb_t in;
for (bits = in = 0; xn > 0 && rn > 0; )
{
if (bits >= 8)
{
rp[--rn] = in;
in >>= 8;
bits -= 8;
}
else
{
uint8_t old = in;
in = *xp++;
xn--;
rp[--rn] = old | (in << bits);
in >>= (8 - bits);
bits += GMP_NUMB_BITS - 8;
}
}
while (rn > 0)
{
rp[--rn] = in;
in >>= 8;
}
}
void
mpn_get_base256_le (uint8_t *rp, size_t rn,
const mp_limb_t *xp, mp_size_t xn)
{
unsigned bits;
mp_limb_t in;
for (bits = in = 0; xn > 0 && rn > 0; )
{
if (bits >= 8)
{
*rp++ = in;
rn--;
in >>= 8;
bits -= 8;
}
else
{
uint8_t old = in;
in = *xp++;
xn--;
*rp++ = old | (in << bits);
rn--;
in >>= (8 - bits);
bits += GMP_NUMB_BITS - 8;
}
}
while (rn > 0)
{
*rp++ = in;
rn--;
in >>= 8;
}
}
mp_limb_t *
gmp_alloc_limbs (mp_size_t n)
{
void *(*alloc_func)(size_t);
assert (n > 0);
mp_get_memory_functions (&alloc_func, NULL, NULL);
return (mp_limb_t *) alloc_func ( (size_t) n * sizeof(mp_limb_t));
}
void
gmp_free_limbs (mp_limb_t *p, mp_size_t n)
{
void (*free_func)(void *, size_t);
assert (n > 0);
assert (p != 0);
mp_get_memory_functions (NULL, NULL, &free_func);
free_func (p, (size_t) n * sizeof(mp_limb_t));
}
void *
gmp_alloc(size_t n)
{
void *(*alloc_func)(size_t);
assert (n > 0);
mp_get_memory_functions(&alloc_func, NULL, NULL);
return alloc_func (n);
}
void
gmp_free(void *p, size_t n)
{
void (*free_func)(void *, size_t);
assert (n > 0);
assert (p != 0);
mp_get_memory_functions (NULL, NULL, &free_func);
free_func (p, (size_t) n);
}