#include "mpoly.h"
#include "fmpz_mod_mpoly_factor.h"
int fmpz_mod_polyun_is_canonical(
const fmpz_mod_polyun_t A,
const fmpz_mod_ctx_t ctx)
{
slong i;
if (A->length < 0)
return 0;
for (i = 0; i < A->length; i++)
{
if (!fmpz_mod_poly_is_canonical(A->coeffs + i, ctx) ||
fmpz_mod_poly_is_zero(A->coeffs + i, ctx))
{
return 0;
}
if (i > 0 && A->exps[i] >= A->exps[i - 1])
return 0;
}
return 1;
}
void fmpz_mod_polyun_clear(
fmpz_mod_polyun_t A,
const fmpz_mod_ctx_t ctx)
{
slong i;
for (i = 0; i < A->alloc; i++)
fmpz_mod_poly_clear(A->coeffs + i, ctx);
flint_free(A->coeffs);
flint_free(A->exps);
}
void fmpz_mod_polyun_realloc(
fmpz_mod_polyun_t A,
slong len,
const fmpz_mod_ctx_t ctx)
{
slong i, old_alloc = A->alloc;
slong new_alloc = FLINT_MAX(len, old_alloc + 1 + old_alloc/2);
A->exps = FLINT_ARRAY_REALLOC(A->exps, new_alloc, ulong);
A->coeffs = FLINT_ARRAY_REALLOC(A->coeffs, new_alloc, fmpz_mod_poly_struct);
for (i = old_alloc; i < new_alloc; i++)
fmpz_mod_poly_init(A->coeffs + i, ctx);
A->alloc = new_alloc;
}
int fmpz_mod_polyun_equal(
fmpz_mod_polyun_t A,
const fmpz_mod_polyun_t B,
const fmpz_mod_ctx_t ctx)
{
slong i;
if (A->length != B->length)
return 0;
for (i = 0; i < A->length; i++)
{
if (A->exps[i] != B->exps[i])
return 0;
if (!fmpz_mod_poly_equal(A->coeffs + i, B->coeffs + i, ctx))
return 0;
}
return 1;
}
void fmpz_mod_polyun_set(
fmpz_mod_polyun_t A,
const fmpz_mod_polyun_t B,
const fmpz_mod_ctx_t ctx)
{
slong i;
fmpz_mod_polyun_fit_length(A, B->length, ctx);
for (i = 0; i < B->length; i++)
{
A->exps[i] = B->exps[i];
fmpz_mod_poly_set(A->coeffs + i, B->coeffs + i, ctx);
}
A->length = B->length;
}
void fmpz_mod_polyun_one(fmpz_mod_polyun_t A, const fmpz_mod_ctx_t ctx)
{
fmpz_mod_polyun_fit_length(A, 1, ctx);
fmpz_mod_poly_one(A->coeffs + 0, ctx);
A->exps[0] = 0;
A->length = 1;
}
void fmpz_mod_mpoly_get_polyu1n(
fmpz_mod_polyun_t A,
const fmpz_mod_mpoly_t B,
slong varx,
slong vary,
const fmpz_mod_mpoly_ctx_t ctx)
{
slong j, Ai;
ulong Bexpx, Bexpy;
slong Boffx, Bshiftx, Boffy, Bshifty;
ulong mask = (-UWORD(1)) >> (FLINT_BITS - B->bits);
slong NB = mpoly_words_per_exp_sp(B->bits, ctx->minfo);
mpoly_gen_offset_shift_sp(&Boffx, &Bshiftx, varx, B->bits, ctx->minfo);
mpoly_gen_offset_shift_sp(&Boffy, &Bshifty, vary, B->bits, ctx->minfo);
Ai = -1;
for (j = 0; j < B->length; j++)
{
Bexpx = ((B->exps + NB*j)[Boffx] >> Bshiftx) & mask;
Bexpy = ((B->exps + NB*j)[Boffy] >> Bshifty) & mask;
if (Ai < 0 || A->exps[Ai] != Bexpx)
{
Ai++;
fmpz_mod_polyun_fit_length(A, Ai + 1, ctx->ffinfo);
A->exps[Ai] = Bexpx;
fmpz_mod_poly_zero(A->coeffs + Ai, ctx->ffinfo);
}
fmpz_mod_poly_set_coeff_fmpz(A->coeffs + Ai, Bexpy, B->coeffs + j, ctx->ffinfo);
if (fmpz_mod_poly_is_zero(A->coeffs + Ai, ctx->ffinfo))
Ai--;
}
A->length = Ai + 1;
FLINT_ASSERT(fmpz_mod_polyun_is_canonical(A, ctx->ffinfo));
}
void fmpz_mod_mpoly_set_polyu1n(
fmpz_mod_mpoly_t B,
const fmpz_mod_polyun_t A,
slong varx,
slong vary,
const fmpz_mod_mpoly_ctx_t ctx)
{
slong i, j;
slong Boffx, Bshiftx, Boffy, Bshifty;
slong N = mpoly_words_per_exp_sp(B->bits, ctx->minfo);
mpoly_gen_offset_shift_sp(&Boffx, &Bshiftx, varx, B->bits, ctx->minfo);
mpoly_gen_offset_shift_sp(&Boffy, &Bshifty, vary, B->bits, ctx->minfo);
B->length = 0;
for (i = 0; i < A->length; i++)
{
for (j = A->coeffs[i].length - 1; j >= 0; j--)
{
if (fmpz_is_zero(A->coeffs[i].coeffs + j))
continue;
fmpz_mod_mpoly_fit_length(B, B->length + 1, ctx);
mpoly_monomial_zero(B->exps + N*B->length, N);
(B->exps + N*B->length)[Boffx] += A->exps[i] << Bshiftx;
(B->exps + N*B->length)[Boffy] += j << Bshifty;
fmpz_set(B->coeffs + B->length, A->coeffs[i].coeffs + j);
B->length++;
}
}
FLINT_ASSERT(fmpz_mod_mpoly_is_canonical(B, ctx));
}