#include <string.h>
#include "mpoly.h"
#include "fmpz_mpoly.h"
#include "gr_mpoly.h"
static int
_same_vars(char ** v1, char ** v2, slong n)
{
slong i;
if (v1 == NULL && v2 == NULL)
return 1;
if (v1 == NULL || v2 == NULL)
return 0;
for (i = 0; i < n; i++)
if (strcmp(v1[i], v2[i]))
return 0;
return 1;
}
static int
_gr_mpoly_set_gr_mpoly_other(gr_mpoly_t res, const gr_mpoly_t A, gr_mpoly_ctx_t A_ctx, gr_mpoly_ctx_t ctx)
{
mpoly_ctx_struct * mctx = GR_MPOLY_MCTX(ctx);
gr_ctx_struct * cctx = GR_MPOLY_CCTX(ctx);
mpoly_ctx_struct * A_mctx = GR_MPOLY_MCTX(A_ctx);
gr_ctx_struct * A_cctx = GR_MPOLY_CCTX(A_ctx);
slong A_nvars, nvars;
slong len;
len = A->length;
nvars = GR_MPOLY_NVARS(ctx);
A_nvars = GR_MPOLY_NVARS(A_ctx);
if (A->length == 0)
{
if (A_cctx == cctx)
{
return gr_mpoly_zero(res, ctx);
}
else
{
int status = GR_SUCCESS;
gr_ptr c, d;
GR_TMP_INIT(c, A_cctx);
GR_TMP_INIT(d, cctx);
status |= gr_mpoly_zero(res, ctx);
status |= gr_set_other(d, c, A_cctx, cctx);
GR_TMP_CLEAR(c, A_cctx);
GR_TMP_CLEAR(d, cctx);
return status;
}
}
if (nvars == A_nvars
&& mctx->ord == A_mctx->ord
&& _same_vars(GR_MPOLY_VARS(A_ctx), GR_MPOLY_VARS(ctx), nvars))
{
int status = GR_SUCCESS;
slong i, N, sz = cctx->sizeof_elem, A_sz = A_cctx->sizeof_elem;
N = mpoly_words_per_exp(A->bits, mctx);
gr_mpoly_fit_length_reset_bits(res, len, A->bits, ctx);
for (i = 0; status == GR_SUCCESS && i < len; i++)
{
status |= gr_set_other(GR_ENTRY(res->coeffs, i, sz), GR_ENTRY(A->coeffs, i, A_sz), A_cctx, cctx);
}
if (status == GR_SUCCESS)
{
mpoly_copy_monomials(res->exps, A->exps, len, N);
_gr_mpoly_set_length(res, len, ctx);
_gr_mpoly_normalise(res, ctx);
}
else
{
_gr_mpoly_set_length(res, 0, ctx);
}
return status;
}
{
int * used_mask;
slong len, num_used;
slong * used;
slong * translation;
int status = GR_SUCCESS;
slong i, j, N, sz = cctx->sizeof_elem, A_sz = A_cctx->sizeof_elem;
slong num_translated;
len = A->length;
if (GR_MPOLY_VARS(ctx) != NULL && GR_MPOLY_VARS(A_ctx) != NULL)
{
used_mask = flint_calloc(A_nvars, sizeof(int));
used = flint_malloc(sizeof(slong) * A_nvars);
translation = flint_malloc(sizeof(slong) * A_nvars);
mpoly_used_vars_or(used_mask, A->exps, len, A->bits, A_mctx);
num_used = 0;
for (i = 0; i < A_nvars; i++)
{
if (used_mask[i] != 0)
{
used[num_used] = i;
num_used++;
}
}
if (num_used <= nvars)
{
num_translated = 0;
for (i = 0; i < num_used; i++)
{
for (j = 0; j < nvars; j++)
{
if (!strcmp(GR_MPOLY_VARS(A_ctx)[used[i]], GR_MPOLY_VARS(ctx)[j]))
{
translation[num_translated] = j;
num_translated++;
break;
}
}
}
if (num_translated != num_used)
{
status = GR_UNABLE;
}
else if (A->bits <= FLINT_BITS)
{
ulong * A_exps;
ulong * exps;
A_exps = flint_malloc(sizeof(ulong) * A_nvars);
exps = flint_calloc(nvars, sizeof(ulong));
N = mpoly_words_per_exp(A->bits, A_mctx);
gr_mpoly_fit_length_reset_bits(res, len, A->bits, ctx);
for (i = 0; status == GR_SUCCESS && i < len; i++)
{
status |= gr_set_other(GR_ENTRY(res->coeffs, i, sz), GR_ENTRY(A->coeffs, i, A_sz), A_cctx, cctx);
mpoly_get_monomial_ui(A_exps, A->exps + i * N, A->bits, A_mctx);
for (j = 0; j < num_used; j++)
exps[translation[j]] = A_exps[used[j]];
_gr_mpoly_push_exp_ui(res, exps, ctx);
}
_gr_mpoly_set_length(res, len, ctx);
gr_mpoly_sort_terms(res, ctx);
_gr_mpoly_normalise(res, ctx);
flint_free(A_exps);
flint_free(exps);
}
else
{
status = GR_UNABLE;
}
}
flint_free(translation);
flint_free(used_mask);
flint_free(used);
}
else
{
status = GR_UNABLE;
}
return status;
}
return GR_UNABLE;
}
typedef struct
{
fmpz_mpoly_ctx_t mctx;
char ** vars;
}
_gr_fmpz_mpoly_ctx_t;
#define _FMPZ_MPOLY_CTX(ring_ctx) ((_gr_fmpz_mpoly_ctx_t *)(GR_CTX_DATA_AS_PTR(ring_ctx)))
#define _FMPZ_MPOLY_MCTX(ring_ctx) (_FMPZ_MPOLY_CTX(ring_ctx)->mctx)
static int
_gr_mpoly_set_fmpz_mpoly(gr_mpoly_t res, const fmpz_mpoly_t A, gr_ctx_t A_ctx, gr_mpoly_ctx_t ctx)
{
int status;
gr_ctx_t ZZ;
gr_mpoly_ctx_t A_ctx1;
gr_mpoly_t t;
gr_ctx_init_fmpz(ZZ);
*A_ctx1 = *ctx;
GR_MPOLY_MCTX(A_ctx1) = _FMPZ_MPOLY_MCTX(A_ctx)->minfo;
GR_MPOLY_CCTX(A_ctx1) = ZZ;
GR_MPOLY_VARS(A_ctx1) = _FMPZ_MPOLY_CTX(A_ctx)->vars;
t->coeffs = A->coeffs;
t->exps = A->exps;
t->length = A->length;
t->bits = A->bits;
t->coeffs_alloc = 0;
t->exps_alloc = 0;
status = _gr_mpoly_set_gr_mpoly_other(res, t, A_ctx1, ctx);
return status;
}
int gr_mpoly_set_other(gr_mpoly_t res, gr_srcptr A, gr_ctx_t A_ctx, gr_mpoly_ctx_t ctx)
{
gr_ctx_struct * cctx = GR_MPOLY_CCTX(ctx);
if (A_ctx == ctx)
{
return gr_mpoly_set(res, A, ctx);
}
else if (A_ctx == cctx)
{
return gr_mpoly_set_scalar(res, A, ctx);
}
else if (A_ctx->which_ring == GR_CTX_GR_MPOLY)
{
return _gr_mpoly_set_gr_mpoly_other(res, A, A_ctx, ctx);
}
else if (A_ctx->which_ring == GR_CTX_FMPZ_MPOLY)
{
return _gr_mpoly_set_fmpz_mpoly(res, A, A_ctx, ctx);
}
else
{
int status;
gr_ptr t;
GR_TMP_INIT(t, cctx);
status = gr_set_other(t, A, A_ctx, cctx);
if (status == GR_SUCCESS)
{
status = gr_mpoly_set_scalar(res, t, ctx);
}
else
{
status = GR_UNABLE;
}
GR_TMP_CLEAR(t, cctx);
return status;
}
}