#include "fmpz.h"
#include "fmpz_poly.h"
#include "mpoly.h"
#include "fmpz_mpoly.h"
void fmpz_mpoly_to_fmpz_poly(fmpz_poly_t poly1, slong * poly1_shift,
const fmpz_mpoly_t poly2, slong var, const fmpz_mpoly_ctx_t ctx)
{
slong i, shift, off, bits, N;
ulong k;
slong _shift = 0, len = poly2->length;
fmpz * coeff = poly2->coeffs;
ulong * exp = poly2->exps;
if (poly2->bits > FLINT_BITS)
flint_throw(FLINT_EXPOF, "Bits too high in fmpz_mpoly_to_fmpz_poly");
bits = poly2->bits;
N = mpoly_words_per_exp(bits, ctx->minfo);
mpoly_gen_offset_shift_sp(&off, &shift, var, bits, ctx->minfo);
fmpz_poly_zero(poly1);
if (len > 0)
{
ulong mask = (-UWORD(1)) >> (FLINT_BITS - bits);
_shift = (exp[N*(len - 1)] >> shift) & mask;
for (i = 0; i < len; i++)
{
k = (exp[N*i + off] >> shift) & mask;
k -= _shift;
FLINT_ASSERT(((slong)k) >= 0);
fmpz_poly_set_coeff_fmpz(poly1, k, coeff + i);
}
}
*poly1_shift = _shift;
}
void fmpz_mpoly_from_fmpz_poly(fmpz_mpoly_t poly1, const fmpz_poly_t poly2,
slong shift2, slong var, const fmpz_mpoly_ctx_t ctx)
{
flint_bitcnt_t bits;
slong N;
slong k;
slong p_len;
fmpz * p_coeff;
ulong * p_exp;
slong p_alloc;
ulong * one;
TMP_INIT;
TMP_START;
bits = 1 + FLINT_BIT_COUNT(FLINT_MAX(WORD(1),
shift2 + fmpz_poly_degree(poly2)));
if (bits > FLINT_BITS)
flint_throw(FLINT_EXPOF, "Exponent overflow in fmpz_mpoly_from_fmpz_poly");
bits = mpoly_fix_bits(bits, ctx->minfo);
N = mpoly_words_per_exp_sp(bits, ctx->minfo);
one = (ulong*) TMP_ALLOC(N*sizeof(ulong));
mpoly_gen_monomial_sp(one, var,bits, ctx->minfo);
fmpz_mpoly_fit_bits(poly1, bits, ctx);
poly1->bits = bits;
p_coeff = poly1->coeffs;
p_exp = poly1->exps;
p_alloc = poly1->alloc;
p_len = 0;
for (k = fmpz_poly_degree(poly2); k >= 0; k--)
{
_fmpz_mpoly_fit_length(&p_coeff, &p_exp, &p_alloc, p_len + 1, N);
mpoly_monomial_mul_ui(p_exp + N*p_len, one, N, k + shift2);
fmpz_poly_get_coeff_fmpz(p_coeff + p_len, poly2, k);
p_len += !fmpz_is_zero(p_coeff + p_len);
}
poly1->coeffs = p_coeff;
poly1->exps = p_exp;
poly1->alloc = p_alloc;
_fmpz_mpoly_set_length(poly1, p_len, ctx);
TMP_END;
}
void _fmpz_mpoly_to_fmpz_poly_deflate(
fmpz_poly_t A,
const fmpz_mpoly_t B,
slong var,
const ulong * Bshift,
const ulong * Bstride,
const fmpz_mpoly_ctx_t ctx)
{
ulong mask;
slong i, shift, off, N;
slong len = B->length;
fmpz * coeff = B->coeffs;
ulong * exp = B->exps;
ulong var_shift, var_stride;
flint_bitcnt_t bits = B->bits;
FLINT_ASSERT(len > 0);
FLINT_ASSERT(bits <= FLINT_BITS);
N = mpoly_words_per_exp(bits, ctx->minfo);
mpoly_gen_offset_shift_sp(&off, &shift, var, bits, ctx->minfo);
fmpz_poly_zero(A);
mask = (-UWORD(1)) >> (FLINT_BITS - bits);
var_shift = Bshift[var];
var_stride = Bstride[var];
for (i = 0; i < len; i++)
{
ulong k = (exp[N*i + off] >> shift) & mask;
FLINT_ASSERT(k >= var_shift);
k -= var_shift;
if (k != 0)
{
k /= var_stride;
}
fmpz_poly_set_coeff_fmpz(A, k, coeff + i);
}
#if FLINT_WANT_ASSERT
for (i = 0; i < len; i++)
{
slong v;
for (v = 0; v < ctx->minfo->nvars; v++)
{
ulong k;
mpoly_gen_offset_shift_sp(&off, &shift, v, bits, ctx->minfo);
k = (exp[N*i + off] >> shift) & mask;
FLINT_ASSERT( (v == var && k >= Bshift[v])
|| (v != var && k == Bshift[v]));
}
}
#endif
}
void _fmpz_mpoly_from_fmpz_poly_inflate(
fmpz_mpoly_t A,
flint_bitcnt_t Abits,
const fmpz_poly_t B,
slong var,
const ulong * Ashift,
const ulong * Astride,
const fmpz_mpoly_ctx_t ctx)
{
slong N;
slong k;
slong Alen;
fmpz * Acoeff;
ulong * Aexp;
slong Aalloc;
ulong * shiftexp;
ulong * strideexp;
slong Bdeg = fmpz_poly_degree(B);
TMP_INIT;
TMP_START;
FLINT_ASSERT(Abits <= FLINT_BITS);
FLINT_ASSERT(!fmpz_poly_is_zero(B));
FLINT_ASSERT(1 + FLINT_BIT_COUNT(Ashift[var] + Bdeg*Astride[var]) <= Abits);
N = mpoly_words_per_exp(Abits, ctx->minfo);
strideexp = (ulong*) TMP_ALLOC(N*sizeof(ulong));
shiftexp = (ulong*) TMP_ALLOC(N*sizeof(ulong));
mpoly_set_monomial_ui(shiftexp, Ashift, Abits, ctx->minfo);
mpoly_gen_monomial_sp(strideexp, var, Abits, ctx->minfo);
mpoly_monomial_mul_ui(strideexp, strideexp, N, Astride[var]);
fmpz_mpoly_fit_bits(A, Abits, ctx);
A->bits = Abits;
Acoeff = A->coeffs;
Aexp = A->exps;
Aalloc = A->alloc;
Alen = 0;
for (k = Bdeg; k >= 0; k--)
{
_fmpz_mpoly_fit_length(&Acoeff, &Aexp, &Aalloc, Alen + 1, N);
fmpz_poly_get_coeff_fmpz(Acoeff + Alen, B, k);
if (!fmpz_is_zero(Acoeff + Alen))
{
mpoly_monomial_madd(Aexp + N*Alen, shiftexp, k, strideexp, N);
Alen++;
}
}
A->coeffs = Acoeff;
A->exps = Aexp;
A->alloc = Aalloc;
_fmpz_mpoly_set_length(A, Alen, ctx);
TMP_END;
}