#include "fmpz_vec.h"
#include "fmpz_mod.h"
#include "n_poly.h"
#include "nmod_mpoly.h"
#include "mpoly.h"
#include "fmpz_mod_mpoly_factor.h"
static void fmpz_mod_mpolyn_interp_lift_sm_polyu1n(
fmpz_mod_mpolyn_t F,
fmpz_mod_polyun_t A,
const fmpz_mod_mpoly_ctx_t ctx)
{
slong N = mpoly_words_per_exp_sp(F->bits, ctx->minfo);
slong i, j, Fi;
slong off0, shift0, off1, shift1;
mpoly_gen_offset_shift_sp(&off0, &shift0, 0, F->bits, ctx->minfo);
mpoly_gen_offset_shift_sp(&off1, &shift1, 1, F->bits, ctx->minfo);
Fi = 0;
for (i = 0; i < A->length; i++)
{
fmpz * Aicoeffs = A->coeffs[i].coeffs;
ulong e0 = A->exps[i] << shift0;
for (j = A->coeffs[i].length - 1; j >= 0; j--)
{
if (fmpz_is_zero(Aicoeffs + j))
continue;
fmpz_mod_mpolyn_fit_length(F, Fi + 1, ctx);
mpoly_monomial_zero(F->exps + N*Fi, N);
(F->exps + N*Fi)[off0] = e0;
(F->exps + N*Fi)[off1] += (j << shift1);
fmpz_mod_poly_set_fmpz(F->coeffs + Fi, Aicoeffs + j, ctx->ffinfo);
Fi++;
}
}
F->length = Fi;
}
static int fmpz_mod_mpolyn_interp_crt_sm_polyu1n(
slong * lastdeg,
fmpz_mod_mpolyn_t F,
fmpz_mod_mpolyn_t T,
fmpz_mod_polyun_t A,
fmpz_mod_poly_t modulus,
fmpz_mod_poly_t alphapow,
const fmpz_mod_mpoly_ctx_t ctx)
{
int changed = 0;
slong N = mpoly_words_per_exp(F->bits, ctx->minfo);
slong off0, shift0, off1, shift1;
fmpz_mod_poly_struct * Acoeffs = A->coeffs;
ulong * Aexps = A->exps;
slong Fi, Ti, Ai, ai;
slong Alen = A->length;
slong Flen = F->length;
ulong * Fexps = F->exps;
fmpz_mod_poly_struct * Fcoeffs = F->coeffs;
ulong * Texps = T->exps;
fmpz_mod_poly_struct * Tcoeffs = T->coeffs;
fmpz_t v;
ulong Fexpi, mask;
fmpz_init(v);
mask = (-UWORD(1)) >> (FLINT_BITS - F->bits);
mpoly_gen_offset_shift_sp(&off0, &shift0, 0, F->bits, ctx->minfo);
mpoly_gen_offset_shift_sp(&off1, &shift1, 1, F->bits, ctx->minfo);
FLINT_ASSERT(T->bits == F->bits);
*lastdeg = -1;
Ti = Fi = 0;
Ai = 0;
ai = 0;
if (Ai < Alen)
ai = fmpz_mod_poly_degree(Acoeffs + Ai, ctx->ffinfo);
while (Fi < Flen || Ai < Alen)
{
if (Ti >= T->alloc)
{
slong extra = FLINT_MAX(Flen - Fi, Alen - Ai);
fmpz_mod_mpolyn_fit_length(T, Ti + extra + 1, ctx);
Tcoeffs = T->coeffs;
Texps = T->exps;
}
if (Fi < Flen)
Fexpi = pack_exp2(((Fexps + N*Fi)[off0]>>shift0)&mask,
((Fexps + N*Fi)[off1]>>shift1)&mask);
else
Fexpi = 0;
if (Fi < Flen && Ai < Alen && Fexpi == pack_exp2(Aexps[Ai], ai))
{
mpoly_monomial_set(Texps + N*Ti, Fexps + N*Fi, N);
fmpz_mod_poly_eval_pow(v, Fcoeffs + Fi, alphapow, ctx->ffinfo);
fmpz_mod_sub(v, Acoeffs[Ai].coeffs + ai, v, ctx->ffinfo);
changed |= !fmpz_is_zero(v);
fmpz_mod_poly_scalar_addmul_fmpz_mod(Tcoeffs + Ti,
Fcoeffs + Fi, modulus, v, ctx->ffinfo);
Fi++;
do {
ai--;
} while (ai >= 0 && fmpz_is_zero(Acoeffs[Ai].coeffs + ai));
if (ai < 0)
{
Ai++;
if (Ai < Alen)
ai = fmpz_mod_poly_degree(Acoeffs + Ai, ctx->ffinfo);
}
}
else if (Ai < Alen && (Fi >= Flen || Fexpi < pack_exp2(Aexps[Ai], ai)))
{
mpoly_monomial_zero(Texps + N*Ti, N);
(Texps + N*Ti)[off0] += (Ai << shift0);
(Texps + N*Ti)[off1] += (ai << shift1);
changed = 1;
fmpz_mod_poly_scalar_mul_fmpz(Tcoeffs + Ti, modulus,
Acoeffs[Ai].coeffs + ai, ctx->ffinfo);
do {
ai--;
} while (ai >= 0 && fmpz_is_zero(Acoeffs[Ai].coeffs + ai));
if (ai < 0)
{
Ai++;
if (Ai < Alen)
ai = fmpz_mod_poly_degree(Acoeffs + Ai, ctx->ffinfo);
}
}
else
{
FLINT_ASSERT(Fi < Flen && (Ai >= Alen || Fexpi > pack_exp2(Aexps[Ai], ai)));
mpoly_monomial_set(Texps + N*Ti, Fexps + N*Fi, N);
fmpz_mod_poly_eval_pow(v, Fcoeffs + Fi, alphapow, ctx->ffinfo);
fmpz_mod_neg(v, v, ctx->ffinfo);
changed |= !fmpz_is_zero(v);
fmpz_mod_poly_scalar_addmul_fmpz_mod(Tcoeffs + Ti,
Fcoeffs + Fi, modulus, v, ctx->ffinfo);
Fi++;
}
FLINT_ASSERT(!fmpz_mod_poly_is_zero(Tcoeffs + Ti, ctx->ffinfo));
*lastdeg = FLINT_MAX(*lastdeg, fmpz_mod_poly_degree(Tcoeffs + Ti, ctx->ffinfo));
Ti++;
}
T->length = Ti;
if (changed)
fmpz_mod_mpolyn_swap(T, F, ctx);
fmpz_clear(v);
return changed;
}
static ulong _fmpz_mod_mpoly_bidegree(
const fmpz_mod_mpoly_t A,
const fmpz_mod_mpoly_ctx_t ctx)
{
FLINT_ASSERT(A->length > 0);
return _mpoly_bidegree(A->exps, A->bits, ctx->minfo);
}
int fmpz_mod_polyun_zip_solve(
fmpz_mod_mpoly_t A,
fmpz_mod_polyun_t Z,
fmpz_mod_polyun_t H,
fmpz_mod_polyun_t M,
const fmpz_mod_mpoly_ctx_t ctx)
{
int success;
slong Ai, i, n;
fmpz * Acoeffs = A->coeffs;
fmpz_mod_poly_t t;
fmpz_mod_poly_init(t, ctx->ffinfo);
FLINT_ASSERT(Z->length == H->length);
FLINT_ASSERT(Z->length == M->length);
Ai = 0;
for (i = 0; i < H->length; i++)
{
n = H->coeffs[i].length;
FLINT_ASSERT(M->coeffs[i].length == n + 1);
FLINT_ASSERT(Z->coeffs[i].length >= n);
FLINT_ASSERT(Ai + n <= A->length);
fmpz_mod_poly_fit_length(t, n, ctx->ffinfo);
success = _fmpz_mod_zip_vand_solve(Acoeffs + Ai,
H->coeffs[i].coeffs, n,
Z->coeffs[i].coeffs, Z->coeffs[i].length,
M->coeffs[i].coeffs, t->coeffs, ctx->ffinfo);
if (success < 1)
{
fmpz_mod_poly_clear(t, ctx->ffinfo);
return success;
}
Ai += n;
FLINT_ASSERT(Ai <= A->length);
}
FLINT_ASSERT(Ai == A->length);
fmpz_mod_poly_clear(t, ctx->ffinfo);
return 1;
}
#define USE_G 1
#define USE_ABAR 2
#define USE_BBAR 4
static double interp_cost(
double degG,
double numABgamma,
double maxnumci,
double totnumci,
double degxAB,
double degyAB)
{
return degG*(degG*totnumci + numABgamma + 0.01*maxnumci*(
numABgamma + totnumci + (degxAB*degyAB)*(degxAB*degyAB)));
}
static int fmpz_mod_mpoly_gcd_get_use_new(
slong rGdeg,
slong Adeg,
slong Bdeg,
slong gammadeg,
slong degxAB,
slong degyAB,
slong numABgamma,
const fmpz_mod_polyun_t G,
const fmpz_mod_polyun_t Abar,
const fmpz_mod_polyun_t Bbar)
{
int use = 0;
slong i, lower = FLINT_MAX(gammadeg, rGdeg);
slong upper = gammadeg + FLINT_MIN(FLINT_MIN(Adeg, Bdeg), rGdeg);
if (lower <= upper)
{
slong Gdeg = ((ulong)upper + (ulong)lower)/2;
slong maxnumci, totnumci;
double Gcost, Abarcost, Bbarcost;
maxnumci = totnumci = 0;
for (i = 0; i < G->length; i++)
{
maxnumci = FLINT_MAX(maxnumci, G->coeffs[i].length);
totnumci += G->coeffs[i].length;
}
FLINT_ASSERT(Gdeg >= 0);
Gcost = interp_cost(Gdeg,
numABgamma, maxnumci, totnumci, degxAB, degyAB);
maxnumci = totnumci = 0;
for (i = 0; i < Abar->length; i++)
{
maxnumci = FLINT_MAX(maxnumci, Abar->coeffs[i].length);
totnumci += Abar->coeffs[i].length;
}
FLINT_ASSERT(gammadeg + Adeg - Gdeg >= 0);
Abarcost = interp_cost(gammadeg + Adeg - Gdeg,
numABgamma, maxnumci, totnumci, degxAB, degyAB);
maxnumci = totnumci = 0;
for (i = 0; i < Bbar->length; i++)
{
maxnumci = FLINT_MAX(maxnumci, Bbar->coeffs[i].length);
totnumci += Bbar->coeffs[i].length;
}
FLINT_ASSERT(gammadeg + Bdeg - Gdeg >= 0);
Bbarcost = interp_cost(gammadeg + Bdeg - Gdeg,
numABgamma, maxnumci, totnumci, degxAB, degyAB);
if (Gcost <= FLINT_MIN(Abarcost, Bbarcost)*1.125)
use |= USE_G;
if (Abarcost <= FLINT_MIN(Gcost, Bbarcost)*1.125)
use |= USE_ABAR;
if (Bbarcost <= FLINT_MIN(Gcost, Abarcost)*1.125)
use |= USE_BBAR;
}
if (use == 0)
use = USE_G | USE_ABAR | USE_BBAR;
return use;
}
static void fmpz_mod_poly_zip_eval_cur_inc_coeff(
fmpz_t eval,
fmpz_mod_poly_t cur,
const fmpz_mod_poly_t inc,
const fmpz_mod_mpoly_t A,
const fmpz_mod_mpoly_ctx_t ctx)
{
FLINT_ASSERT(A->length == cur->length);
FLINT_ASSERT(A->length == inc->length);
_fmpz_mod_zip_eval_step(eval, cur->coeffs, inc->coeffs, A->coeffs, A->length, ctx->ffinfo);
}
void fmpz_mod_mpoly_mock_eval_coeff(
fmpz_mod_polyun_t mock,
const fmpz_mod_mpoly_t A,
const fmpz_mod_polyun_t Aeh_inc,
const fmpz_mod_mpoly_ctx_t FLINT_UNUSED(ctx))
{
slong i, k;
if (mock->alloc < Aeh_inc->length)
{
mock->alloc = FLINT_MAX(Aeh_inc->length, mock->alloc + mock->alloc/2);
mock->coeffs = FLINT_ARRAY_REALLOC(mock->coeffs, mock->alloc,
fmpz_mod_poly_struct);
}
mock->length = Aeh_inc->length;
k = 0;
for (i = 0; i < Aeh_inc->length; i++)
{
slong l = Aeh_inc->coeffs[i].length;
mock->coeffs[i].coeffs = A->coeffs + k;
mock->coeffs[i].alloc = l;
mock->coeffs[i].length = l;
k += l;
}
FLINT_ASSERT(k == A->length);
}
static void fmpz_mod_mpoly_monomial_evals(
fmpz_mod_poly_t E,
const fmpz_mod_mpoly_t A,
fmpz_mod_poly_struct * beta_caches,
slong start,
slong stop,
const fmpz_mod_mpoly_ctx_t ctx)
{
mpoly_monomial_evals_fmpz_mod(E, A->exps, A->length, A->bits,
beta_caches, start, stop, ctx->minfo, ctx->ffinfo);
}
static void fmpz_mod_mpoly_monomial_evals2(
fmpz_mod_polyun_t E,
const fmpz_mod_mpoly_t A,
fmpz_mod_poly_struct * betas,
slong m,
const fmpz_mod_mpoly_ctx_t ctx,
n_poly_t tmark)
{
mpoly2_fill_marks(&tmark->coeffs, &tmark->length, &tmark->alloc,
A->exps, A->length, A->bits, ctx->minfo);
mpoly2_monomial_evals_fmpz_mod(E, A->exps, A->bits, tmark->coeffs,
tmark->length, betas, m, ctx->minfo, ctx->ffinfo);
}
static int fmpz_mod_polyun_add_zip_must_match(
fmpz_mod_polyun_t Z,
const fmpz_mod_polyun_t A,
slong cur_length)
{
slong i, Ai, ai;
slong Alen = A->length;
ulong * Zexps = Z->exps;
fmpz_mod_poly_struct * Zcoeffs = Z->coeffs;
ulong * Aexps = A->exps;
fmpz_mod_poly_struct * Acoeffs = A->coeffs;
Ai = 0;
ai = 0;
if (Ai < Alen)
ai = Acoeffs[Ai].length - 1;
for (i = 0; i < Z->length; i++)
{
if (Ai < Alen && Zexps[i] == pack_exp2(Aexps[Ai], ai))
{
fmpz_set(Zcoeffs[i].coeffs + cur_length,
Acoeffs[Ai].coeffs + ai);
Zcoeffs[i].length = cur_length + 1;
do {
ai--;
} while (ai >= 0 && fmpz_is_zero(Acoeffs[Ai].coeffs + ai));
if (ai < 0)
{
Ai++;
if (Ai < Alen)
ai = Acoeffs[Ai].length - 1;
}
}
else if (Ai >= Alen || Zexps[i] > pack_exp2(Aexps[Ai], ai))
{
fmpz_zero(Zcoeffs[i].coeffs + cur_length);
Zcoeffs[i].length = cur_length + 1;
}
else
{
return 0;
}
}
return Ai >= Alen;
}
void fmpz_mod_polyu2n_zip_eval_cur_inc_coeff(
fmpz_mod_polyun_t E,
fmpz_mod_polyun_t Acur,
const fmpz_mod_polyun_t Ainc,
const fmpz_mod_polyun_t Acoeff,
const fmpz_mod_ctx_t ctx)
{
slong i, Ei;
ulong e0, e1;
fmpz_t c;
FLINT_ASSERT(Acur->length > 0);
FLINT_ASSERT(Acur->length == Ainc->length);
FLINT_ASSERT(Acur->length == Acoeff->length);
fmpz_init(c);
e0 = extract_exp(Acur->exps[0], 1, 2);
e1 = extract_exp(Acur->exps[0], 0, 2);
fmpz_mod_polyun_fit_length(E, 4, ctx);
Ei = 0;
E->exps[Ei] = e1;
fmpz_mod_poly_zero(E->coeffs + Ei, ctx);
for (i = 0; i < Acur->length; i++)
{
slong this_len = Acur->coeffs[i].length;
FLINT_ASSERT(this_len == Ainc->coeffs[i].length);
FLINT_ASSERT(this_len == Acoeff->coeffs[i].length);
_fmpz_mod_zip_eval_step(c, Acur->coeffs[i].coeffs,
Ainc->coeffs[i].coeffs, Acoeff->coeffs[i].coeffs, this_len, ctx);
e0 = extract_exp(Acur->exps[i], 1, 2);
e1 = extract_exp(Acur->exps[i], 0, 2);
if (E->exps[Ei] != e0)
{
fmpz_mod_polyun_fit_length(E, Ei + 2, ctx);
Ei += !fmpz_mod_poly_is_zero(E->coeffs + Ei, ctx);
E->exps[Ei] = e0;
fmpz_mod_poly_zero(E->coeffs + Ei, ctx);
}
fmpz_mod_poly_set_coeff_fmpz(E->coeffs + Ei, e1, c, ctx);
}
Ei += !fmpz_mod_poly_is_zero(E->coeffs + Ei, ctx);
E->length = Ei;
FLINT_ASSERT(fmpz_mod_polyun_is_canonical(E, ctx));
fmpz_clear(c);
}
int fmpz_mod_mpolyl_gcd_zippel2_smprime(
fmpz_mod_mpoly_t rG, const slong * rGdegs,
fmpz_mod_mpoly_t rAbar,
fmpz_mod_mpoly_t rBbar,
const fmpz_mod_mpoly_t A, const slong * Adegs,
const fmpz_mod_mpoly_t B, const slong * Bdegs,
const fmpz_mod_mpoly_t gamma, const slong * gammadegs,
const fmpz_mod_mpoly_ctx_t ctx)
{
int success, use, alpha_tries_left;
slong i, m;
slong nvars = ctx->minfo->nvars;
flint_bitcnt_t bits = A->bits;
fmpz * alphas, * betas;
fmpz_mod_poly_struct * alpha_caches, * beta_caches;
flint_rand_t state;
n_poly_t tmark;
fmpz_mod_mpoly_t cont;
fmpz_mod_mpoly_t T, G, Abar, Bbar;
fmpz_mod_polyun_t HG, HAbar, HBbar, MG, MAbar, MBbar, ZG, ZAbar, ZBbar;
fmpz_mod_polyun_t Aev, Bev, Gev, Abarev, Bbarev;
fmpz_t gammaev;
fmpz_mod_mpolyn_t Tn, Gn, Abarn, Bbarn;
slong lastdeg;
slong cur_zip_image, req_zip_images, this_length;
fmpz_mod_polyun_t Aeh_coeff_mock, Beh_coeff_mock;
fmpz_mod_polyun_t Aeh_cur, Aeh_inc, Beh_cur, Beh_inc;
fmpz_mod_poly_t gammaeh_cur, gammaeh_inc;
fmpz_mod_poly_t modulus, alphapow;
fmpz_mod_mpoly_struct * Aevals, * Bevals;
fmpz_mod_mpoly_struct * gammaevals;
fmpz_mod_poly_polyun_stack_t St;
fmpz_t c, start_alpha;
ulong GdegboundXY, newdegXY, Abideg, Bbideg;
slong degxAB, degyAB;
FLINT_ASSERT(bits <= FLINT_BITS);
FLINT_ASSERT(bits == A->bits);
FLINT_ASSERT(bits == B->bits);
FLINT_ASSERT(bits == gamma->bits);
FLINT_ASSERT(A->length > 0);
FLINT_ASSERT(B->length > 0);
FLINT_ASSERT(gamma->length > 0);
fmpz_mod_mpoly_fit_length_reset_bits(rG, 1, bits, ctx);
fmpz_mod_mpoly_fit_length_reset_bits(rAbar, 1, bits, ctx);
fmpz_mod_mpoly_fit_length_reset_bits(rBbar, 1, bits, ctx);
fmpz_init(gammaev);
fmpz_init(c);
fmpz_init(start_alpha);
#if FLINT_WANT_ASSERT
{
slong * tmp_degs = FLINT_ARRAY_ALLOC(nvars, slong);
fmpz_mod_mpoly_degrees_si(tmp_degs, A, ctx);
for (i = 0; i < nvars; i++)
FLINT_ASSERT(tmp_degs[i] == Adegs[i]);
fmpz_mod_mpoly_degrees_si(tmp_degs, B, ctx);
for (i = 0; i < nvars; i++)
FLINT_ASSERT(tmp_degs[i] == Bdegs[i]);
fmpz_mod_mpoly_degrees_si(tmp_degs, gamma, ctx);
for (i = 0; i < nvars; i++)
FLINT_ASSERT(tmp_degs[i] == gammadegs[i]);
flint_free(tmp_degs);
}
#endif
FLINT_ASSERT(gammadegs[0] == 0);
FLINT_ASSERT(gammadegs[1] == 0);
n_poly_init(tmark);
fmpz_mod_polyun_init(HG, ctx->ffinfo);
fmpz_mod_polyun_init(HAbar, ctx->ffinfo);
fmpz_mod_polyun_init(HBbar, ctx->ffinfo);
fmpz_mod_polyun_init(MG, ctx->ffinfo);
fmpz_mod_polyun_init(MAbar, ctx->ffinfo);
fmpz_mod_polyun_init(MBbar, ctx->ffinfo);
fmpz_mod_polyun_init(ZG, ctx->ffinfo);
fmpz_mod_polyun_init(ZAbar, ctx->ffinfo);
fmpz_mod_polyun_init(ZBbar, ctx->ffinfo);
fmpz_mod_polyun_init(Aev, ctx->ffinfo);
fmpz_mod_polyun_init(Bev, ctx->ffinfo);
fmpz_mod_polyun_init(Gev, ctx->ffinfo);
fmpz_mod_polyun_init(Abarev, ctx->ffinfo);
fmpz_mod_polyun_init(Bbarev, ctx->ffinfo);
fmpz_mod_poly_init2(alphapow, 4, ctx->ffinfo);
fmpz_mod_mpoly_init3(cont, 1, bits, ctx);
fmpz_mod_mpoly_init3(T, 1, bits, ctx);
fmpz_mod_mpoly_init3(G, 1, bits, ctx);
fmpz_mod_mpoly_init3(Abar, 1, bits, ctx);
fmpz_mod_mpoly_init3(Bbar, 1, bits, ctx);
fmpz_mod_mpolyn_init(Tn, bits, ctx);
fmpz_mod_mpolyn_init(Gn, bits, ctx);
fmpz_mod_mpolyn_init(Abarn, bits, ctx);
fmpz_mod_mpolyn_init(Bbarn, bits, ctx);
fmpz_mod_polyun_init(Aeh_cur, ctx->ffinfo);
fmpz_mod_polyun_init(Aeh_inc, ctx->ffinfo);
fmpz_mod_polyun_init(Beh_cur, ctx->ffinfo);
fmpz_mod_polyun_init(Beh_inc, ctx->ffinfo);
fmpz_mod_poly_init(gammaeh_cur, ctx->ffinfo);
fmpz_mod_poly_init(gammaeh_inc, ctx->ffinfo);
fmpz_mod_poly_init(modulus, ctx->ffinfo);
fmpz_mod_poly_stack_init(St->poly_stack);
fmpz_mod_polyun_stack_init(St->polyun_stack);
Aeh_coeff_mock->exps = NULL;
Aeh_coeff_mock->coeffs = NULL;
Aeh_coeff_mock->length = 0;
Aeh_coeff_mock->alloc = 0;
Beh_coeff_mock->exps = NULL;
Beh_coeff_mock->coeffs = NULL;
Beh_coeff_mock->length = 0;
Beh_coeff_mock->alloc = 0;
betas = _fmpz_vec_init(nvars);
alphas = _fmpz_vec_init(nvars);
flint_rand_init(state);
beta_caches = FLINT_ARRAY_ALLOC(nvars, fmpz_mod_poly_struct);
alpha_caches = FLINT_ARRAY_ALLOC(nvars, fmpz_mod_poly_struct);
for (i = 0; i < nvars; i++)
{
fmpz_mod_poly_init(beta_caches + i, ctx->ffinfo);
fmpz_mod_poly_init(alpha_caches + i, ctx->ffinfo);
}
Aevals = FLINT_ARRAY_ALLOC(nvars + 1, fmpz_mod_mpoly_struct);
Bevals = FLINT_ARRAY_ALLOC(nvars + 1, fmpz_mod_mpoly_struct);
gammaevals = FLINT_ARRAY_ALLOC(nvars + 1, fmpz_mod_mpoly_struct);
for (i = 0; i < nvars; i++)
{
fmpz_mod_mpoly_init3(Aevals + i, 0, bits, ctx);
fmpz_mod_mpoly_init3(Bevals + i, 0, bits, ctx);
fmpz_mod_mpoly_init3(gammaevals + i, 0, bits, ctx);
}
Aevals[nvars] = *A;
Bevals[nvars] = *B;
gammaevals[nvars] = *gamma;
Abideg = _fmpz_mod_mpoly_bidegree(A, ctx);
Bbideg = _fmpz_mod_mpoly_bidegree(B, ctx);
degxAB = FLINT_MAX(Adegs[0], Bdegs[0]);
degyAB = FLINT_MAX(Adegs[1], Bdegs[1]);
GdegboundXY = pack_exp2(FLINT_MIN(Adegs[0], Bdegs[0]),
FLINT_MIN(Adegs[1], Bdegs[1]));
if (GdegboundXY == 0)
goto gcd_is_trivial;
alpha_tries_left = 20;
choose_alphas:
if (--alpha_tries_left < 0)
{
success = 0;
goto cleanup;
}
for (i = 2; i < nvars; i++)
fmpz_mod_rand_not_zero(alphas + i, state, ctx->ffinfo);
for (i = nvars - 1; i >= 2; i--)
{
fmpz_mod_mpoly_evaluate_one_fmpz(Aevals + i, Aevals + i + 1, i, alphas + i, ctx);
fmpz_mod_mpoly_evaluate_one_fmpz(Bevals + i, Bevals + i + 1, i, alphas + i, ctx);
fmpz_mod_mpoly_evaluate_one_fmpz(gammaevals + i, gammaevals + i + 1, i, alphas + i, ctx);
if (fmpz_mod_mpoly_is_zero(gammaevals + i, ctx))
goto choose_alphas;
if (Aevals[i].length < 1 || _fmpz_mod_mpoly_bidegree(Aevals + i, ctx) != Abideg)
goto choose_alphas;
if (Bevals[i].length < 1 || _fmpz_mod_mpoly_bidegree(Bevals + i, ctx) != Bbideg)
goto choose_alphas;
}
m = 2;
if (rGdegs == NULL)
use = USE_G | USE_ABAR | USE_BBAR;
else
use = mpoly_gcd_get_use_first(rGdegs[m], Adegs[m], Bdegs[m], gammadegs[m]);
fmpz_mod_mpoly_get_polyu1n(Aev, Aevals + m, 0, 1, ctx);
fmpz_mod_mpoly_get_polyu1n(Bev, Bevals + m, 0, 1, ctx);
success = fmpz_mod_polyu1n_gcd_brown_smprime(Gev, Abarev, Bbarev, Aev, Bev,
ctx->ffinfo, St->poly_stack, St->polyun_stack);
if (!success)
goto cleanup;
newdegXY = fmpz_mod_polyu1n_bidegree(Gev);
if (newdegXY > GdegboundXY)
goto choose_alphas;
if (newdegXY < GdegboundXY)
{
GdegboundXY = newdegXY;
if (GdegboundXY == 0)
goto gcd_is_trivial;
}
fmpz_mod_mpoly_get_fmpz(gammaev, gammaevals + m, ctx);
_fmpz_mod_poly_vec_mul_fmpz_mod(Gev->coeffs, Gev->length, gammaev, ctx->ffinfo);
fmpz_mod_mpolyn_interp_lift_sm_polyu1n(Gn, Gev, ctx);
fmpz_mod_mpolyn_interp_lift_sm_polyu1n(Abarn, Abarev, ctx);
fmpz_mod_mpolyn_interp_lift_sm_polyu1n(Bbarn, Bbarev, ctx);
fmpz_mod_poly_one(modulus, ctx->ffinfo);
fmpz_mod_neg(c, alphas + m, ctx->ffinfo);
fmpz_mod_poly_shift_left_scalar_addmul_fmpz_mod(modulus, 1, c, ctx->ffinfo);
fmpz_set(start_alpha, alphas + m);
while (1)
{
choose_alpha_2:
if (fmpz_cmp_ui(alphas + m, 2) < 0)
fmpz_set(alphas + m, fmpz_mod_ctx_modulus(ctx->ffinfo));
fmpz_sub_ui(alphas + m, alphas + m, 1);
if (fmpz_equal(alphas + m, start_alpha))
goto choose_alphas;
FLINT_ASSERT(alphapow->alloc >= 2);
fmpz_one(alphapow->coeffs + 0);
fmpz_set(alphapow->coeffs + 1, alphas + m);
alphapow->length = 2;
fmpz_mod_mpoly_evaluate_one_fmpz(Aevals + m, Aevals + m + 1, m, alphas + m, ctx);
fmpz_mod_mpoly_evaluate_one_fmpz(Bevals + m, Bevals + m + 1, m, alphas + m, ctx);
fmpz_mod_mpoly_evaluate_one_fmpz(gammaevals + m, gammaevals + m + 1, m, alphas + m, ctx);
if (fmpz_mod_mpoly_is_zero(gammaevals + m, ctx))
goto choose_alpha_2;
if (Aevals[m].length < 1 || _fmpz_mod_mpoly_bidegree(Aevals + m, ctx) != Abideg)
goto choose_alpha_2;
if (Bevals[m].length < 1 || _fmpz_mod_mpoly_bidegree(Bevals + m, ctx) != Bbideg)
goto choose_alpha_2;
fmpz_mod_mpoly_get_polyu1n(Aev, Aevals + m, 0, 1, ctx);
fmpz_mod_mpoly_get_polyu1n(Bev, Bevals + m, 0, 1, ctx);
success = fmpz_mod_polyu1n_gcd_brown_smprime(Gev, Abarev, Bbarev,
Aev, Bev, ctx->ffinfo, St->poly_stack, St->polyun_stack);
if (!success)
goto cleanup;
newdegXY = fmpz_mod_polyu1n_bidegree(Gev);
if (newdegXY > GdegboundXY)
goto choose_alpha_2;
if (newdegXY < GdegboundXY)
{
GdegboundXY = newdegXY;
if (GdegboundXY == 0)
goto gcd_is_trivial;
goto choose_alphas;
}
fmpz_mod_mpoly_get_fmpz(gammaev, gammaevals + m, ctx);
_fmpz_mod_poly_vec_mul_fmpz_mod(Gev->coeffs, Gev->length, gammaev, ctx->ffinfo);
fmpz_mod_poly_eval_pow(c, modulus, alphapow, ctx->ffinfo);
fmpz_mod_inv(c, c, ctx->ffinfo);
fmpz_mod_poly_scalar_mul_fmpz(modulus, modulus, c, ctx->ffinfo);
if ((use & USE_G) && !fmpz_mod_mpolyn_interp_crt_sm_polyu1n(
&lastdeg, Gn, Tn, Gev, modulus, alphapow, ctx))
{
if (m == nvars - 1)
{
fmpz_mod_mpoly_cvtfrom_mpolyn(rG, Gn, m, ctx);
success = fmpz_mod_mpolyl_content(cont, rG, 2, ctx);
if (!success)
goto cleanup;
fmpz_mod_mpoly_divides(rG, rG, cont, ctx);
fmpz_mod_mpoly_repack_bits_inplace(rG, bits, ctx);
if (fmpz_mod_mpoly_divides(rAbar, A, rG, ctx) &&
fmpz_mod_mpoly_divides(rBbar, B, rG, ctx))
{
fmpz_mod_mpoly_repack_bits_inplace(rAbar, bits, ctx);
fmpz_mod_mpoly_repack_bits_inplace(rBbar, bits, ctx);
break;
}
}
else
{
fmpz_mod_mpoly_cvtfrom_mpolyn(G, Gn, m, ctx);
fmpz_mod_mpoly_mul(T, Aevals + m + 1, gammaevals + m + 1, ctx);
if (fmpz_mod_mpoly_divides(Abar, T, G, ctx))
{
fmpz_mod_mpoly_repack_bits_inplace(Abar, bits, ctx);
fmpz_mod_mpoly_mul(T, Bevals + m + 1, gammaevals + m + 1, ctx);
if (fmpz_mod_mpoly_divides(Bbar, T, G, ctx))
{
fmpz_mod_mpoly_repack_bits_inplace(Bbar, bits, ctx);
break;
}
}
}
}
if ((use & USE_ABAR) && !fmpz_mod_mpolyn_interp_crt_sm_polyu1n(
&lastdeg, Abarn, Tn, Abarev, modulus, alphapow, ctx))
{
if (m == nvars - 1)
{
fmpz_mod_mpoly_cvtfrom_mpolyn(rAbar, Abarn, m, ctx);
success = fmpz_mod_mpolyl_content(cont, rAbar, 2, ctx);
if (!success)
goto cleanup;
fmpz_mod_mpoly_divides(rAbar, rAbar, cont, ctx);
fmpz_mod_mpoly_repack_bits_inplace(rAbar, bits, ctx);
if (fmpz_mod_mpoly_divides(rG, A, rAbar, ctx) &&
fmpz_mod_mpoly_divides(rBbar, B, rG, ctx))
{
fmpz_mod_mpoly_repack_bits_inplace(rG, bits, ctx);
fmpz_mod_mpoly_repack_bits_inplace(rBbar, bits, ctx);
break;
}
}
else
{
fmpz_mod_mpoly_cvtfrom_mpolyn(Abar, Abarn, m, ctx);
fmpz_mod_mpoly_mul(T, Aevals + m + 1, gammaevals + m + 1, ctx);
if (fmpz_mod_mpoly_divides(G, T, Abar, ctx))
{
fmpz_mod_mpoly_repack_bits_inplace(G, bits, ctx);
fmpz_mod_mpoly_mul(T, Bevals + m + 1, gammaevals + m + 1, ctx);
if (fmpz_mod_mpoly_divides(Bbar, T, G, ctx))
{
fmpz_mod_mpoly_repack_bits_inplace(Bbar, bits, ctx);
break;
}
}
}
}
if ((use & USE_BBAR) && !fmpz_mod_mpolyn_interp_crt_sm_polyu1n(
&lastdeg, Bbarn, Tn, Bbarev, modulus, alphapow, ctx))
{
if (m == nvars - 1)
{
fmpz_mod_mpoly_cvtfrom_mpolyn(rBbar, Bbarn, m, ctx);
success = fmpz_mod_mpolyl_content(cont, rBbar, 2, ctx);
if (!success)
goto cleanup;
fmpz_mod_mpoly_divides(rBbar, rBbar, cont, ctx);
fmpz_mod_mpoly_repack_bits_inplace(rBbar, bits, ctx);
if (fmpz_mod_mpoly_divides(rG, B, rBbar, ctx) &&
fmpz_mod_mpoly_divides(rAbar, A, rG, ctx))
{
fmpz_mod_mpoly_repack_bits_inplace(rG, bits, ctx);
fmpz_mod_mpoly_repack_bits_inplace(rAbar, bits, ctx);
break;
}
}
else
{
fmpz_mod_mpoly_cvtfrom_mpolyn(Bbar, Bbarn, m, ctx);
fmpz_mod_mpoly_mul(T, Bevals + m + 1, gammaevals + m + 1, ctx);
if (fmpz_mod_mpoly_divides(G, T, Bbar, ctx))
{
fmpz_mod_mpoly_repack_bits_inplace(G, bits, ctx);
fmpz_mod_mpoly_mul(T, Aevals + m + 1, gammaevals + m + 1, ctx);
if (fmpz_mod_mpoly_divides(Abar, T, G, ctx))
{
fmpz_mod_mpoly_repack_bits_inplace(Abar, bits, ctx);
break;
}
}
}
}
if (fmpz_mod_poly_degree(modulus, ctx->ffinfo) > gammadegs[m] + Adegs[m] &&
fmpz_mod_poly_degree(modulus, ctx->ffinfo) > gammadegs[m] + Bdegs[m])
{
goto choose_alphas;
}
fmpz_mod_neg(c, alphas + m, ctx->ffinfo);
fmpz_mod_poly_shift_left_scalar_addmul_fmpz_mod(modulus, 1, c, ctx->ffinfo);
}
for (m = 3; m < nvars; m++)
{
fmpz_mod_mpolyn_interp_lift_sm_mpoly(Gn, G, ctx);
fmpz_mod_mpolyn_interp_lift_sm_mpoly(Abarn, Abar, ctx);
fmpz_mod_mpolyn_interp_lift_sm_mpoly(Bbarn, Bbar, ctx);
if (rGdegs == NULL)
use = USE_G | USE_ABAR | USE_BBAR;
else
use = 0;
fmpz_mod_poly_one(modulus, ctx->ffinfo);
fmpz_mod_neg(c, alphas + m, ctx->ffinfo);
fmpz_mod_poly_shift_left_scalar_addmul_fmpz_mod(modulus, 1, c, ctx->ffinfo);
fmpz_set(start_alpha, alphas + m);
choose_betas:
for (i = 2; i < nvars; i++)
{
fmpz_mod_rand_not_zero(betas + i, state, ctx->ffinfo);
fmpz_mod_pow_cache_start(betas + i, beta_caches + i, ctx->ffinfo);
}
fmpz_mod_mpoly_monomial_evals2(HG, G, beta_caches + 2, m, ctx, tmark);
fmpz_mod_mpoly_monomial_evals2(HAbar, Abar, beta_caches + 2, m, ctx, tmark);
fmpz_mod_mpoly_monomial_evals2(HBbar, Bbar, beta_caches + 2, m, ctx, tmark);
if (use == 0)
{
this_length = gammaevals[m + 1].length + Aevals[m + 1].length +
Bevals[m + 1].length;
use = fmpz_mod_mpoly_gcd_get_use_new(rGdegs[m], Adegs[m], Bdegs[m],
gammadegs[m], degxAB, degyAB, this_length, HG, HAbar, HBbar);
}
req_zip_images = 1;
if (use & USE_G)
{
this_length = fmpz_mod_polyun_product_roots(MG, HG, ctx->ffinfo);
req_zip_images = FLINT_MAX(req_zip_images, this_length);
}
if (use & USE_ABAR)
{
this_length = fmpz_mod_polyun_product_roots(MAbar, HAbar, ctx->ffinfo);
req_zip_images = FLINT_MAX(req_zip_images, this_length);
}
if (use & USE_BBAR)
{
this_length = fmpz_mod_polyun_product_roots(MBbar, HBbar, ctx->ffinfo);
req_zip_images = FLINT_MAX(req_zip_images, this_length);
}
while (1)
{
choose_alpha_m:
if (fmpz_cmp_ui(alphas + m, 2) < 0)
fmpz_set(alphas + m, fmpz_mod_ctx_modulus(ctx->ffinfo));
fmpz_sub_ui(alphas + m, alphas + m, 1);
if (fmpz_equal(alphas + m, start_alpha))
goto choose_alphas;
FLINT_ASSERT(alphapow->alloc >= 2);
fmpz_one(alphapow->coeffs + 0);
fmpz_set(alphapow->coeffs + 1, alphas + m);
alphapow->length = 2;
fmpz_mod_mpoly_evaluate_one_fmpz(Aevals + m, Aevals + m + 1, m, alphas + m, ctx);
fmpz_mod_mpoly_evaluate_one_fmpz(Bevals + m, Bevals + m + 1, m, alphas + m, ctx);
fmpz_mod_mpoly_evaluate_one_fmpz(gammaevals + m, gammaevals + m + 1, m, alphas + m, ctx);
if (fmpz_mod_mpoly_is_zero(gammaevals + m, ctx))
goto choose_alpha_m;
if (Aevals[m].length < 1 || _fmpz_mod_mpoly_bidegree(Aevals + m, ctx) != Abideg)
goto choose_alpha_m;
if (Bevals[m].length < 1 || _fmpz_mod_mpoly_bidegree(Bevals + m, ctx) != Bbideg)
goto choose_alpha_m;
fmpz_mod_mpoly_monomial_evals2(Aeh_inc, Aevals + m, beta_caches + 2, m, ctx, tmark);
fmpz_mod_mpoly_monomial_evals2(Beh_inc, Bevals + m, beta_caches + 2, m, ctx, tmark);
fmpz_mod_mpoly_monomial_evals(gammaeh_inc, gammaevals + m, beta_caches + 2, 2, m, ctx);
fmpz_mod_polyun_set(Aeh_cur, Aeh_inc, ctx->ffinfo);
fmpz_mod_polyun_set(Beh_cur, Beh_inc, ctx->ffinfo);
fmpz_mod_poly_set(gammaeh_cur, gammaeh_inc, ctx->ffinfo);
fmpz_mod_mpoly_mock_eval_coeff(Aeh_coeff_mock, Aevals + m, Aeh_inc, ctx);
fmpz_mod_mpoly_mock_eval_coeff(Beh_coeff_mock, Bevals + m, Beh_inc, ctx);
fmpz_mod_polyun_zip_start(ZG, HG, req_zip_images, ctx->ffinfo);
fmpz_mod_polyun_zip_start(ZAbar, HAbar, req_zip_images, ctx->ffinfo);
fmpz_mod_polyun_zip_start(ZBbar, HBbar, req_zip_images, ctx->ffinfo);
for (cur_zip_image = 0; cur_zip_image < req_zip_images; cur_zip_image++)
{
fmpz_mod_polyu2n_zip_eval_cur_inc_coeff(Aev, Aeh_cur, Aeh_inc, Aeh_coeff_mock, ctx->ffinfo);
fmpz_mod_polyu2n_zip_eval_cur_inc_coeff(Bev, Beh_cur, Beh_inc, Beh_coeff_mock, ctx->ffinfo);
fmpz_mod_poly_zip_eval_cur_inc_coeff(gammaev, gammaeh_cur, gammaeh_inc, gammaevals + m, ctx);
if (fmpz_is_zero(gammaev))
goto choose_betas;
if (Aev->length < 1 || fmpz_mod_polyu1n_bidegree(Aev) != Abideg)
goto choose_betas;
if (Bev->length < 1 || fmpz_mod_polyu1n_bidegree(Bev) != Bbideg)
goto choose_betas;
success = fmpz_mod_polyu1n_gcd_brown_smprime(Gev, Abarev, Bbarev,
Aev, Bev, ctx->ffinfo, St->poly_stack, St->polyun_stack);
if (!success)
goto cleanup;
newdegXY = fmpz_mod_polyu1n_bidegree(Gev);
if (newdegXY > GdegboundXY)
goto choose_betas;
if (newdegXY < GdegboundXY)
{
GdegboundXY = newdegXY;
if (GdegboundXY == 0)
goto gcd_is_trivial;
goto choose_alphas;
}
_fmpz_mod_poly_vec_mul_fmpz_mod(Gev->coeffs, Gev->length, gammaev, ctx->ffinfo);
if ((use & USE_G) && !fmpz_mod_polyun_add_zip_must_match(ZG, Gev, cur_zip_image))
goto choose_alphas;
if ((use & USE_ABAR) && !fmpz_mod_polyun_add_zip_must_match(ZAbar, Abarev, cur_zip_image))
goto choose_alphas;
if ((use & USE_BBAR) && !fmpz_mod_polyun_add_zip_must_match(ZBbar, Bbarev, cur_zip_image))
goto choose_alphas;
}
if ((use & USE_G) && fmpz_mod_polyun_zip_solve(G, ZG, HG, MG, ctx) < 1)
goto choose_alphas;
if ((use & USE_ABAR) && fmpz_mod_polyun_zip_solve(Abar, ZAbar, HAbar, MAbar, ctx) < 1)
goto choose_alphas;
if ((use & USE_BBAR) && fmpz_mod_polyun_zip_solve(Bbar, ZBbar, HBbar, MBbar, ctx) < 1)
goto choose_alphas;
FLINT_ASSERT(fmpz_mod_poly_degree(modulus, ctx->ffinfo) > 0);
fmpz_mod_poly_eval_pow(c, modulus, alphapow, ctx->ffinfo);
fmpz_mod_inv(c, c, ctx->ffinfo);
fmpz_mod_poly_scalar_mul_fmpz(modulus, modulus, c, ctx->ffinfo);
if ((use & USE_G) && !fmpz_mod_mpolyn_interp_mcrt_sm_mpoly(
&lastdeg, Gn, G, modulus, alphapow, ctx))
{
fmpz_mod_mpoly_cvtfrom_mpolyn(rG, Gn, m, ctx);
if (m == nvars - 1)
{
success = fmpz_mod_mpolyl_content(cont, rG, 2, ctx);
if (!success)
goto cleanup;
fmpz_mod_mpoly_divides(rG, rG, cont, ctx);
fmpz_mod_mpoly_repack_bits_inplace(rG, bits, ctx);
if (fmpz_mod_mpoly_divides(rAbar, A, rG, ctx) &&
fmpz_mod_mpoly_divides(rBbar, B, rG, ctx))
{
fmpz_mod_mpoly_repack_bits_inplace(rAbar, bits, ctx);
fmpz_mod_mpoly_repack_bits_inplace(rBbar, bits, ctx);
break;
}
}
else
{
fmpz_mod_mpoly_mul(T, Aevals + m + 1, gammaevals + m + 1, ctx);
if (fmpz_mod_mpoly_divides(rAbar, T, rG, ctx))
{
fmpz_mod_mpoly_mul(T, Bevals + m + 1, gammaevals + m + 1, ctx);
if (fmpz_mod_mpoly_divides(rBbar, T, rG, ctx))
{
fmpz_mod_mpoly_repack_bits_inplace(rAbar, bits, ctx);
fmpz_mod_mpoly_repack_bits_inplace(rBbar, bits, ctx);
fmpz_mod_mpoly_swap(G, rG, ctx);
fmpz_mod_mpoly_swap(Abar, rAbar, ctx);
fmpz_mod_mpoly_swap(Bbar, rBbar, ctx);
break;
}
}
}
}
if ((use & USE_ABAR) && !fmpz_mod_mpolyn_interp_mcrt_sm_mpoly(
&lastdeg, Abarn, Abar, modulus, alphapow, ctx))
{
fmpz_mod_mpoly_cvtfrom_mpolyn(rAbar, Abarn, m, ctx);
if (m == nvars - 1)
{
success = fmpz_mod_mpolyl_content(cont, rAbar, 2, ctx);
if (!success)
goto cleanup;
fmpz_mod_mpoly_divides(rAbar, rAbar, cont, ctx);
fmpz_mod_mpoly_repack_bits_inplace(rAbar, bits, ctx);
if (fmpz_mod_mpoly_divides(rG, A, rAbar, ctx) &&
fmpz_mod_mpoly_divides(rBbar, B, rG, ctx))
{
fmpz_mod_mpoly_repack_bits_inplace(rG, bits, ctx);
fmpz_mod_mpoly_repack_bits_inplace(rBbar, bits, ctx);
break;
}
}
else
{
fmpz_mod_mpoly_mul(T, Aevals + m + 1, gammaevals + m + 1, ctx);
if (fmpz_mod_mpoly_divides(rG, T, rAbar, ctx))
{
fmpz_mod_mpoly_mul(T, Bevals + m + 1, gammaevals + m + 1, ctx);
if (fmpz_mod_mpoly_divides(rBbar, T, rG, ctx))
{
fmpz_mod_mpoly_repack_bits_inplace(rG, bits, ctx);
fmpz_mod_mpoly_repack_bits_inplace(rBbar, bits, ctx);
fmpz_mod_mpoly_swap(G, rG, ctx);
fmpz_mod_mpoly_swap(Abar, rAbar, ctx);
fmpz_mod_mpoly_swap(Bbar, rBbar, ctx);
break;
}
}
}
}
if ((use & USE_BBAR) && !fmpz_mod_mpolyn_interp_mcrt_sm_mpoly(
&lastdeg, Bbarn, Bbar, modulus, alphapow, ctx))
{
fmpz_mod_mpoly_cvtfrom_mpolyn(rBbar, Bbarn, m, ctx);
if (m == nvars - 1)
{
success = fmpz_mod_mpolyl_content(cont, rBbar, 2, ctx);
if (!success)
goto cleanup;
fmpz_mod_mpoly_divides(rBbar, rBbar, cont, ctx);
fmpz_mod_mpoly_repack_bits_inplace(rBbar, bits, ctx);
if (fmpz_mod_mpoly_divides(rG, B, rBbar, ctx) &&
fmpz_mod_mpoly_divides(rAbar, A, rG, ctx))
{
fmpz_mod_mpoly_repack_bits_inplace(rG, bits, ctx);
fmpz_mod_mpoly_repack_bits_inplace(rAbar, bits, ctx);
break;
}
}
else
{
fmpz_mod_mpoly_mul(T, Bevals + m + 1, gammaevals + m + 1, ctx);
if (fmpz_mod_mpoly_divides(rG, T, rBbar, ctx))
{
fmpz_mod_mpoly_mul(T, Aevals + m + 1, gammaevals + m + 1, ctx);
if (fmpz_mod_mpoly_divides(rAbar, T, rG, ctx))
{
fmpz_mod_mpoly_repack_bits_inplace(rG, bits, ctx);
fmpz_mod_mpoly_repack_bits_inplace(rAbar, bits, ctx);
fmpz_mod_mpoly_swap(G, rG, ctx);
fmpz_mod_mpoly_swap(Abar, rAbar, ctx);
fmpz_mod_mpoly_swap(Bbar, rBbar, ctx);
break;
}
}
}
}
if (_fmpz_mod_poly_degree(modulus) > gammadegs[m] + Adegs[m] &&
_fmpz_mod_poly_degree(modulus) > gammadegs[m] + Bdegs[m])
{
goto choose_alphas;
}
fmpz_mod_neg(c, alphas + m, ctx->ffinfo);
fmpz_mod_poly_shift_left_scalar_addmul_fmpz_mod(modulus, 1, c, ctx->ffinfo);
}
}
success = 1;
cleanup:
n_poly_clear(tmark);
fmpz_mod_polyun_clear(HG, ctx->ffinfo);
fmpz_mod_polyun_clear(HAbar, ctx->ffinfo);
fmpz_mod_polyun_clear(HBbar, ctx->ffinfo);
fmpz_mod_polyun_clear(MG, ctx->ffinfo);
fmpz_mod_polyun_clear(MAbar, ctx->ffinfo);
fmpz_mod_polyun_clear(MBbar, ctx->ffinfo);
fmpz_mod_polyun_clear(ZG, ctx->ffinfo);
fmpz_mod_polyun_clear(ZAbar, ctx->ffinfo);
fmpz_mod_polyun_clear(ZBbar, ctx->ffinfo);
fmpz_mod_polyun_clear(Aev, ctx->ffinfo);
fmpz_mod_polyun_clear(Bev, ctx->ffinfo);
fmpz_mod_polyun_clear(Gev, ctx->ffinfo);
fmpz_mod_polyun_clear(Abarev, ctx->ffinfo);
fmpz_mod_polyun_clear(Bbarev, ctx->ffinfo);
fmpz_mod_poly_clear(alphapow, ctx->ffinfo);
fmpz_mod_mpoly_clear(cont, ctx);
fmpz_mod_mpoly_clear(T, ctx);
fmpz_mod_mpoly_clear(G, ctx);
fmpz_mod_mpoly_clear(Abar, ctx);
fmpz_mod_mpoly_clear(Bbar, ctx);
fmpz_mod_mpolyn_clear(Tn, ctx);
fmpz_mod_mpolyn_clear(Gn, ctx);
fmpz_mod_mpolyn_clear(Abarn, ctx);
fmpz_mod_mpolyn_clear(Bbarn, ctx);
fmpz_mod_polyun_clear(Aeh_cur, ctx->ffinfo);
fmpz_mod_polyun_clear(Aeh_inc, ctx->ffinfo);
fmpz_mod_polyun_clear(Beh_cur, ctx->ffinfo);
fmpz_mod_polyun_clear(Beh_inc, ctx->ffinfo);
fmpz_mod_poly_clear(gammaeh_cur, ctx->ffinfo);
fmpz_mod_poly_clear(gammaeh_inc, ctx->ffinfo);
fmpz_mod_poly_clear(modulus, ctx->ffinfo);
fmpz_mod_poly_stack_clear(St->poly_stack);
fmpz_mod_polyun_stack_clear(St->polyun_stack);
flint_free(Aeh_coeff_mock->coeffs);
flint_free(Beh_coeff_mock->coeffs);
for (i = 0; i < nvars; i++)
{
fmpz_mod_poly_clear(beta_caches + i, ctx->ffinfo);
fmpz_mod_poly_clear(alpha_caches + i, ctx->ffinfo);
}
flint_free(beta_caches);
flint_free(alpha_caches);
_fmpz_vec_clear(betas, nvars);
_fmpz_vec_clear(alphas, nvars);
flint_rand_clear(state);
for (i = 0; i < nvars; i++)
{
fmpz_mod_mpoly_clear(Aevals + i, ctx);
fmpz_mod_mpoly_clear(Bevals + i, ctx);
fmpz_mod_mpoly_clear(gammaevals + i, ctx);
}
flint_free(Aevals);
flint_free(Bevals);
flint_free(gammaevals);
fmpz_clear(gammaev);
fmpz_clear(c);
fmpz_clear(start_alpha);
FLINT_ASSERT(!success || rG->bits == bits);
FLINT_ASSERT(!success || rAbar->bits == bits);
FLINT_ASSERT(!success || rBbar->bits == bits);
FLINT_ASSERT(success || fmpz_abs_fits_ui(fmpz_mod_mpoly_ctx_modulus(ctx)));
return success;
gcd_is_trivial:
fmpz_mod_mpoly_one(rG, ctx);
fmpz_mod_mpoly_set(rAbar, A, ctx);
fmpz_mod_mpoly_set(rBbar, B, ctx);
success = 1;
goto cleanup;
}