#include "mpoly.h"
#include "fmpz_mod_mpoly_factor.h"
void fmpz_mod_mpoly_to_mpolyl_perm_deflate(
fmpz_mod_mpoly_t A,
const fmpz_mod_mpoly_ctx_t lctx,
const fmpz_mod_mpoly_t B,
const fmpz_mod_mpoly_ctx_t ctx,
const slong * perm,
const ulong * shift,
const ulong * stride)
{
slong j, k, l;
slong m = lctx->minfo->nvars;
slong n = ctx->minfo->nvars;
slong NA, NB;
ulong * lexps;
ulong * Bexps;
TMP_INIT;
FLINT_ASSERT(A->bits <= FLINT_BITS);
FLINT_ASSERT(B->bits <= FLINT_BITS);
FLINT_ASSERT(m <= n);
TMP_START;
fmpz_mod_mpoly_fit_length(A, B->length, ctx);
A->length = B->length;
lexps = (ulong *) TMP_ALLOC(m*sizeof(ulong));
Bexps = (ulong *) TMP_ALLOC(n*sizeof(ulong));
NA = mpoly_words_per_exp(A->bits, lctx->minfo);
NB = mpoly_words_per_exp(B->bits, ctx->minfo);
for (j = 0; j < B->length; j++)
{
fmpz_set(A->coeffs + j, B->coeffs + j);
mpoly_get_monomial_ui(Bexps, B->exps + NB*j, B->bits, ctx->minfo);
for (k = 0; k < m; k++)
{
l = perm[k];
if (stride[l] == 1)
{
lexps[k] = (Bexps[l] - shift[l]);
}
else
{
FLINT_ASSERT(stride[l] != 0);
FLINT_ASSERT(((Bexps[l] - shift[l]) % stride[l]) == 0);
lexps[k] = (Bexps[l] - shift[l]) / stride[l];
}
}
mpoly_set_monomial_ui(A->exps + NA*j, lexps, A->bits, lctx->minfo);
}
TMP_END;
fmpz_mod_mpoly_sort_terms(A, lctx);
FLINT_ASSERT(fmpz_mod_mpoly_is_canonical(A, lctx));
}
void fmpz_mod_mpoly_from_mpolyl_perm_inflate(
fmpz_mod_mpoly_t A,
flint_bitcnt_t Abits,
const fmpz_mod_mpoly_ctx_t ctx,
const fmpz_mod_mpoly_t B,
const fmpz_mod_mpoly_ctx_t lctx,
const slong * perm,
const ulong * shift,
const ulong * stride)
{
slong n = ctx->minfo->nvars;
slong m = lctx->minfo->nvars;
slong i, k, l;
slong NA, NB;
ulong * Bexps;
ulong * Aexps;
TMP_INIT;
FLINT_ASSERT(B->length > 0);
FLINT_ASSERT(Abits <= FLINT_BITS);
FLINT_ASSERT(B->bits <= FLINT_BITS);
FLINT_ASSERT(m <= n);
TMP_START;
Bexps = (ulong *) TMP_ALLOC(m*sizeof(ulong));
Aexps = (ulong *) TMP_ALLOC(n*sizeof(ulong));
NA = mpoly_words_per_exp(Abits, ctx->minfo);
NB = mpoly_words_per_exp(B->bits, lctx->minfo);
fmpz_mod_mpoly_fit_length_reset_bits(A, B->length, Abits, ctx);
A->length = B->length;
for (i = 0; i < B->length; i++)
{
fmpz_set(A->coeffs + i, B->coeffs + i);
mpoly_get_monomial_ui(Bexps, B->exps + NB*i, B->bits, lctx->minfo);
for (l = 0; l < n; l++)
{
Aexps[l] = shift[l];
}
for (k = 0; k < m; k++)
{
l = perm[k];
Aexps[l] += stride[l]*Bexps[k];
}
mpoly_set_monomial_ui(A->exps + NA*i, Aexps, Abits, ctx->minfo);
}
TMP_END;
fmpz_mod_mpoly_sort_terms(A, ctx);
FLINT_ASSERT(fmpz_mod_mpoly_is_canonical(A, ctx));
}