#include "mpn_extras.h"
#include "fmpz.h"
#include "fmpz_poly.h"
int
_fmpz_poly_bit_unpack(fmpz * poly, slong nlo, slong nhi,
nn_srcptr arr, flint_bitcnt_t bit_size, int negate)
{
flint_bitcnt_t bits = 0;
slong limbs = 0;
flint_bitcnt_t b = bit_size % FLINT_BITS;
slong l = bit_size / FLINT_BITS;
int borrow = 0;
slong i;
if (nlo != 0)
{
borrow = (arr[(nlo * bit_size - 1) / FLINT_BITS] >>
((nlo * bit_size - 1) % FLINT_BITS)) & 1;
limbs = (nlo * bit_size) / FLINT_BITS;
bits = (nlo * bit_size) % FLINT_BITS;
}
for (i = nlo; i < nhi; i++)
{
borrow =
fmpz_bit_unpack(poly + i - nlo, arr + limbs, bits, bit_size, negate,
borrow);
limbs += l;
bits += b;
if (bits >= FLINT_BITS)
{
bits -= FLINT_BITS;
limbs++;
}
}
return borrow;
}
void
_fmpz_poly_bit_unpack_unsigned(fmpz * poly, slong nlo, slong nhi,
nn_srcptr arr, flint_bitcnt_t bit_size)
{
flint_bitcnt_t bits = 0;
slong limbs = 0;
flint_bitcnt_t b = bit_size % FLINT_BITS;
slong l = bit_size / FLINT_BITS;
slong i;
if (nlo != 0)
{
limbs = (nlo * bit_size) / FLINT_BITS;
bits = (nlo * bit_size) % FLINT_BITS;
}
for (i = nlo; i < nhi; i++)
{
fmpz_bit_unpack_unsigned(poly + i - nlo, arr + limbs, bits, bit_size);
limbs += l;
bits += b;
if (bits >= FLINT_BITS)
{
bits -= FLINT_BITS;
limbs++;
}
}
}
void
fmpz_poly_bit_unpack_unsigned(fmpz_poly_t poly, const fmpz_t f,
flint_bitcnt_t bit_size)
{
slong len;
mpz_t tmp;
if (fmpz_sgn(f) < 0)
{
flint_throw(FLINT_ERROR, "Exception (fmpz_poly_bit_unpack_unsigned). Expected an unsigned value.\n");
}
if (bit_size == 0 || fmpz_is_zero(f))
{
fmpz_poly_zero(poly);
return;
}
len = (fmpz_bits(f) + bit_size - 1) / bit_size;
mpz_init2(tmp, bit_size*len);
flint_mpn_zero(tmp->_mp_d, tmp->_mp_alloc);
fmpz_get_mpz(tmp, f);
fmpz_poly_fit_length(poly, len);
_fmpz_poly_bit_unpack_unsigned(poly->coeffs, 0, len, tmp->_mp_d, bit_size);
_fmpz_poly_set_length(poly, len);
_fmpz_poly_normalise(poly);
mpz_clear(tmp);
}
void
fmpz_poly_bit_unpack(fmpz_poly_t poly, const fmpz_t f, flint_bitcnt_t bit_size)
{
slong len;
mpz_t tmp;
int negate, borrow;
if (bit_size == 0 || fmpz_is_zero(f))
{
fmpz_poly_zero(poly);
return;
}
len = (fmpz_bits(f) + bit_size - 1) / bit_size;
negate = (fmpz_sgn(f) < 0) ? -1 : 0;
mpz_init2(tmp, bit_size*len);
flint_mpn_zero(tmp->_mp_d, tmp->_mp_alloc);
fmpz_get_mpz(tmp, f);
fmpz_poly_fit_length(poly, len + 1);
borrow = _fmpz_poly_bit_unpack(poly->coeffs, 0, len,
tmp->_mp_d, bit_size, negate);
if (borrow)
{
fmpz_set_si(poly->coeffs + len, negate ? WORD(-1) : WORD(1));
_fmpz_poly_set_length(poly, len + 1);
}
else
{
_fmpz_poly_set_length(poly, len);
_fmpz_poly_normalise(poly);
}
mpz_clear(tmp);
}