#include "fmpz_mod.h"
#include "mpoly.h"
#include "fmpz_mod_mpoly_factor.h"
static void _fmpz_mod_poly_gcd_cofactors(
fmpz_mod_poly_t G,
fmpz_mod_poly_t Abar,
fmpz_mod_poly_t Bbar,
const fmpz_mod_poly_t A,
const fmpz_mod_poly_t B,
const fmpz_mod_ctx_t ctx,
fmpz_mod_poly_t t)
{
fmpz_mod_poly_gcd(G, A, B, ctx);
fmpz_mod_poly_divrem(Abar, t, A, G, ctx);
fmpz_mod_poly_divrem(Bbar, t, B, G, ctx);
}
int fmpz_mod_polyu1n_gcd_brown_smprime(
fmpz_mod_polyun_t G,
fmpz_mod_polyun_t Abar,
fmpz_mod_polyun_t Bbar,
fmpz_mod_polyun_t A,
fmpz_mod_polyun_t B,
const fmpz_mod_ctx_t ctx,
fmpz_mod_poly_stack_t St_poly,
fmpz_mod_polyun_stack_t St_polyun)
{
int success;
slong bound;
fmpz_t alpha, temp, gammaevalp, gammaevalm;
fmpz_mod_poly_struct * Aevalp, * Bevalp, * Gevalp, * Abarevalp, * Bbarevalp;
fmpz_mod_poly_struct * Aevalm, * Bevalm, * Gevalm, * Abarevalm, * Bbarevalm;
fmpz_mod_polyun_struct * T;
slong deggamma, ldegG, ldegAbar, ldegBbar, ldegA, ldegB;
fmpz_mod_poly_struct * cA, * cB, * cG, * cAbar, * cBbar, * gamma;
fmpz_mod_poly_struct * modulus, * alphapow, * r;
int gstab, astab, bstab, use_stab;
#if FLINT_WANT_ASSERT
fmpz_mod_poly_t leadA, leadB;
#endif
fmpz_init(alpha);
fmpz_init(temp);
fmpz_init(gammaevalp);
fmpz_init(gammaevalm);
#if FLINT_WANT_ASSERT
fmpz_mod_poly_init(leadA, ctx);
fmpz_mod_poly_init(leadB, ctx);
fmpz_mod_poly_set(leadA, A->coeffs + 0, ctx);
fmpz_mod_poly_set(leadB, B->coeffs + 0, ctx);
#endif
fmpz_mod_poly_stack_fit_request(St_poly, 19);
cA = fmpz_mod_poly_stack_take_top(St_poly);
cB = fmpz_mod_poly_stack_take_top(St_poly);
cG = fmpz_mod_poly_stack_take_top(St_poly);
cAbar = fmpz_mod_poly_stack_take_top(St_poly);
cBbar = fmpz_mod_poly_stack_take_top(St_poly);
gamma = fmpz_mod_poly_stack_take_top(St_poly);
Aevalp = fmpz_mod_poly_stack_take_top(St_poly);
Bevalp = fmpz_mod_poly_stack_take_top(St_poly);
Gevalp = fmpz_mod_poly_stack_take_top(St_poly);
Abarevalp = fmpz_mod_poly_stack_take_top(St_poly);
Bbarevalp = fmpz_mod_poly_stack_take_top(St_poly);
Aevalm = fmpz_mod_poly_stack_take_top(St_poly);
Bevalm = fmpz_mod_poly_stack_take_top(St_poly);
Gevalm = fmpz_mod_poly_stack_take_top(St_poly);
Abarevalm = fmpz_mod_poly_stack_take_top(St_poly);
Bbarevalm = fmpz_mod_poly_stack_take_top(St_poly);
r = fmpz_mod_poly_stack_take_top(St_poly);
alphapow = fmpz_mod_poly_stack_take_top(St_poly);
modulus = fmpz_mod_poly_stack_take_top(St_poly);
fmpz_mod_polyun_stack_fit_request(St_polyun, 1);
T = fmpz_mod_polyun_stack_take_top(St_polyun);
_fmpz_mod_poly_vec_remove_content(cA, A->coeffs, A->length, ctx);
_fmpz_mod_poly_vec_remove_content(cB, B->coeffs, B->length, ctx);
_fmpz_mod_poly_gcd_cofactors(cG, cAbar, cBbar, cA, cB, ctx, r);
fmpz_mod_poly_gcd(gamma, A->coeffs + 0, B->coeffs + 0, ctx);
ldegA = _fmpz_mod_poly_vec_max_degree(A->coeffs, A->length, ctx);
ldegB = _fmpz_mod_poly_vec_max_degree(B->coeffs, B->length, ctx);
deggamma = fmpz_mod_poly_degree(gamma, ctx);
bound = 1 + deggamma + FLINT_MAX(ldegA, ldegB);
fmpz_mod_poly_fit_length(alphapow, FLINT_MAX(WORD(3), bound + 1), ctx);
fmpz_mod_poly_one(modulus, ctx);
use_stab = 1;
gstab = bstab = astab = 0;
fmpz_fdiv_q_2exp(alpha, fmpz_mod_ctx_modulus(ctx), 1);
choose_prime:
fmpz_sub_ui(alpha, alpha, 1);
if (fmpz_sgn(alpha) <= 0)
{
success = 0;
goto cleanup;
}
FLINT_ASSERT(alphapow->alloc >= 2);
alphapow->length = 2;
fmpz_one(alphapow->coeffs + 0);
fmpz_set(alphapow->coeffs + 1, alpha);
fmpz_mod_poly_eval2_pow(gammaevalp, gammaevalm, gamma, alphapow, ctx);
if (fmpz_is_zero(gammaevalp) || fmpz_is_zero(gammaevalm))
{
goto choose_prime;
}
fmpz_mod_polyu1n_interp_reduce_2sm_poly(Aevalp, Aevalm, A, alphapow, ctx);
fmpz_mod_polyu1n_interp_reduce_2sm_poly(Bevalp, Bevalm, B, alphapow, ctx);
FLINT_ASSERT(Aevalp->length > 0);
FLINT_ASSERT(Aevalm->length > 0);
FLINT_ASSERT(Bevalp->length > 0);
FLINT_ASSERT(Bevalm->length > 0);
if (use_stab && gstab)
{
slong Gdeg;
fmpz_mod_polyu1n_interp_reduce_2sm_poly(Gevalp, Gevalm, G, alphapow, ctx);
Gdeg = G->exps[0];
success = 1;
success = success && _fmpz_mod_poly_degree(Gevalp) == Gdeg;
success = success && _fmpz_mod_poly_degree(Gevalm) == Gdeg;
success = success && fmpz_equal(Gevalp->coeffs + Gdeg, gammaevalp);
success = success && fmpz_equal(Gevalm->coeffs + Gdeg, gammaevalm);
fmpz_mod_poly_divrem(Abarevalp, r, Aevalp, Gevalp, ctx);
success = success && (r->length == 0);
fmpz_mod_poly_divrem(Abarevalm, r, Aevalm, Gevalm, ctx);
success = success && (r->length == 0);
fmpz_mod_poly_divrem(Bbarevalp, r, Bevalp, Gevalp, ctx);
success = success && (r->length == 0);
fmpz_mod_poly_divrem(Bbarevalm, r, Bevalm, Gevalm, ctx);
success = success && (r->length == 0);
if (!success)
{
use_stab = 0;
fmpz_mod_poly_one(modulus, ctx);
goto choose_prime;
}
fmpz_mod_poly_scalar_mul_fmpz(Abarevalp, Abarevalp, gammaevalp, ctx);
fmpz_mod_poly_scalar_mul_fmpz(Abarevalm, Abarevalm, gammaevalm, ctx);
fmpz_mod_poly_scalar_mul_fmpz(Bbarevalp, Bbarevalp, gammaevalp, ctx);
fmpz_mod_poly_scalar_mul_fmpz(Bbarevalm, Bbarevalm, gammaevalm, ctx);
}
else
{
_fmpz_mod_poly_gcd_cofactors(Gevalp, Abarevalp, Bbarevalp,
Aevalp, Bevalp, ctx, r);
_fmpz_mod_poly_gcd_cofactors(Gevalm, Abarevalm, Bbarevalm,
Aevalm, Bevalm, ctx, r);
}
FLINT_ASSERT(Gevalp->length > 0);
FLINT_ASSERT(Abarevalp->length > 0);
FLINT_ASSERT(Bbarevalp->length > 0);
FLINT_ASSERT(Gevalm->length > 0);
FLINT_ASSERT(Abarevalm->length > 0);
FLINT_ASSERT(Bbarevalm->length > 0);
if (_fmpz_mod_poly_degree(Gevalp) == 0 || _fmpz_mod_poly_degree(Gevalm) == 0)
{
fmpz_mod_polyun_one(G, ctx);
fmpz_mod_polyun_swap(Abar, A);
fmpz_mod_polyun_swap(Bbar, B);
goto successful_put_content;
}
if (_fmpz_mod_poly_degree(Gevalp) != _fmpz_mod_poly_degree(Gevalm))
{
goto choose_prime;
}
if (_fmpz_mod_poly_degree(modulus) > 0)
{
FLINT_ASSERT(G->length > 0);
if ((ulong) _fmpz_mod_poly_degree(Gevalp) > G->exps[0])
{
goto choose_prime;
}
else if ((ulong) _fmpz_mod_poly_degree(Gevalp) < G->exps[0])
{
fmpz_mod_poly_one(modulus, ctx);
}
}
fmpz_mod_poly_scalar_mul_fmpz(Gevalp, Gevalp, gammaevalp, ctx);
fmpz_mod_poly_scalar_mul_fmpz(Gevalm, Gevalm, gammaevalm, ctx);
if (fmpz_mod_poly_degree(modulus, ctx) > 0)
{
fmpz_mod_poly_evaluate_fmpz(temp, modulus, alpha, ctx);
fmpz_mod_mul(temp, temp, alpha, ctx);
fmpz_mod_add(temp, temp, temp, ctx);
fmpz_mod_poly_scalar_div_fmpz(modulus, modulus, temp, ctx);
gstab = gstab || !fmpz_mod_polyu1n_interp_crt_2sm_poly(&ldegG, G, T, Gevalp, Gevalm, modulus, alphapow, ctx);
fmpz_mod_polyu1n_interp_crt_2sm_poly(&ldegAbar, Abar, T, Abarevalp, Abarevalm, modulus, alphapow, ctx);
fmpz_mod_polyu1n_interp_crt_2sm_poly(&ldegBbar, Bbar, T, Bbarevalp, Bbarevalm, modulus, alphapow, ctx);
}
else
{
fmpz_mod_polyu1n_interp_lift_2sm_poly(&ldegG, G, Gevalp, Gevalm, alpha, ctx);
fmpz_mod_polyu1n_interp_lift_2sm_poly(&ldegAbar, Abar, Abarevalp, Abarevalm, alpha, ctx);
fmpz_mod_polyu1n_interp_lift_2sm_poly(&ldegBbar, Bbar, Bbarevalp, Bbarevalm, alpha, ctx);
gstab = astab = bstab = 0;
}
fmpz_mod_mul(temp, alpha, alpha, ctx);
fmpz_mod_neg(temp, temp, ctx);
fmpz_mod_poly_shift_left_scalar_addmul_fmpz_mod(modulus, 2, temp, ctx);
if (fmpz_mod_poly_degree(modulus, ctx) < bound)
{
goto choose_prime;
}
FLINT_ASSERT(ldegG >= 0);
FLINT_ASSERT(ldegAbar >= 0);
FLINT_ASSERT(ldegBbar >= 0);
if (deggamma + ldegA == ldegG + ldegAbar &&
deggamma + ldegB == ldegG + ldegBbar)
{
goto successful;
}
fmpz_mod_poly_one(modulus, ctx);
goto choose_prime;
successful:
_fmpz_mod_poly_vec_remove_content(r, G->coeffs, G->length, ctx);
_fmpz_mod_poly_vec_divexact_poly(Abar->coeffs, Abar->length, G->coeffs + 0, ctx);
_fmpz_mod_poly_vec_divexact_poly(Bbar->coeffs, Bbar->length, G->coeffs + 0, ctx);
successful_put_content:
_fmpz_mod_poly_vec_mul_poly(G->coeffs, G->length, cG, ctx);
_fmpz_mod_poly_vec_mul_poly(Abar->coeffs, Abar->length, cAbar, ctx);
_fmpz_mod_poly_vec_mul_poly(Bbar->coeffs, Bbar->length, cBbar, ctx);
success = 1;
cleanup:
#if FLINT_WANT_ASSERT
if (success)
{
FLINT_ASSERT(fmpz_is_one(fmpz_mod_poly_lead(G->coeffs + 0, ctx)));
fmpz_mod_poly_mul(modulus, G->coeffs + 0, Abar->coeffs + 0, ctx);
FLINT_ASSERT(fmpz_mod_poly_equal(modulus, leadA, ctx));
fmpz_mod_poly_mul(modulus, G->coeffs + 0, Bbar->coeffs + 0, ctx);
FLINT_ASSERT(fmpz_mod_poly_equal(modulus, leadB, ctx));
}
fmpz_mod_poly_clear(leadA, ctx);
fmpz_mod_poly_clear(leadB, ctx);
#endif
fmpz_mod_poly_stack_give_back(St_poly, 19);
fmpz_mod_polyun_stack_give_back(St_polyun, 1);
fmpz_clear(alpha);
fmpz_clear(temp);
fmpz_clear(gammaevalp);
fmpz_clear(gammaevalm);
return success;
}
static void fmpz_mod_mpolyn_set_polyun_swap(
fmpz_mod_mpolyn_t A,
fmpz_mod_polyun_t B,
const fmpz_mod_mpoly_ctx_t ctx)
{
slong i, N, off, shift;
flint_bitcnt_t bits = A->bits;
N = mpoly_words_per_exp_sp(bits, ctx->minfo);
mpoly_gen_offset_shift_sp(&off, &shift, 0, bits, ctx->minfo);
fmpz_mod_mpolyn_fit_length(A, B->length, ctx);
for (i = 0; i < B->length; i++)
{
mpoly_monomial_zero(A->exps + N*i, N);
(A->exps + N*i)[off] = B->exps[i] << shift;
fmpz_mod_poly_swap(A->coeffs + i, B->coeffs + i, ctx->ffinfo);
}
A->length = B->length;
}
static void fmpz_mod_mpolyn_get_polyun_swap(
fmpz_mod_polyun_t B,
fmpz_mod_mpolyn_t A,
const fmpz_mod_mpoly_ctx_t ctx)
{
slong i, N, off, shift;
flint_bitcnt_t bits = A->bits;
N = mpoly_words_per_exp_sp(bits, ctx->minfo);
mpoly_gen_offset_shift_sp(&off, &shift, 0, bits, ctx->minfo);
fmpz_mod_polyun_fit_length(B, A->length, ctx->ffinfo);
for (i = 0; i < A->length; i++)
{
B->exps[i] = (A->exps + N*i)[off] >> shift;
fmpz_mod_poly_swap(B->coeffs + i, A->coeffs + i, ctx->ffinfo);
}
B->length = A->length;
}
int fmpz_mod_mpolyn_gcd_brown_smprime(
fmpz_mod_mpolyn_t G,
fmpz_mod_mpolyn_t Abar,
fmpz_mod_mpolyn_t Bbar,
fmpz_mod_mpolyn_t A,
fmpz_mod_mpolyn_t B,
slong var,
const fmpz_mod_mpoly_ctx_t ctx,
const mpoly_gcd_info_t I,
fmpz_mod_poly_polyun_mpolyn_stack_t St)
{
int success, changed;
slong bound, upper_limit;
slong offset, shift;
fmpz_t alpha, temp, gammaevalp, gammaevalm;
fmpz_mod_mpolyn_struct * Aevalp, * Bevalp, * Gevalp, * Abarevalp, * Bbarevalp;
fmpz_mod_mpolyn_struct * Aevalm, * Bevalm, * Gevalm, * Abarevalm, * Bbarevalm;
fmpz_mod_mpolyn_struct * T1, * T2;
slong deggamma, ldegG, ldegAbar, ldegBbar, ldegA, ldegB;
fmpz_mod_poly_struct * cA, * cB, * cG, * cAbar, * cBbar, * gamma;
fmpz_mod_poly_struct * modulus, * alphapow, * t1;
flint_bitcnt_t bits = A->bits;
slong N = mpoly_words_per_exp_sp(bits, ctx->minfo);
#if FLINT_WANT_ASSERT
fmpz_mod_mpolyn_t Aorg, Borg;
fmpz_mod_poly_t leadA, leadB;
#endif
FLINT_ASSERT(bits == St->mpolyn_stack->bits);
FLINT_ASSERT(bits == A->bits);
FLINT_ASSERT(bits == B->bits);
FLINT_ASSERT(bits == G->bits);
FLINT_ASSERT(bits == Abar->bits);
FLINT_ASSERT(bits == Bbar->bits);
FLINT_ASSERT(var > 0);
if (var == 1)
{
fmpz_mod_polyun_struct * mA, * mB, * mG, * mAbar, * mBbar;
fmpz_mod_polyun_stack_fit_request(St->polyun_stack, 5);
mA = fmpz_mod_polyun_stack_take_top(St->polyun_stack);
mB = fmpz_mod_polyun_stack_take_top(St->polyun_stack);
mG = fmpz_mod_polyun_stack_take_top(St->polyun_stack);
mAbar = fmpz_mod_polyun_stack_take_top(St->polyun_stack);
mBbar = fmpz_mod_polyun_stack_take_top(St->polyun_stack);
fmpz_mod_mpolyn_get_polyun_swap(mA, A, ctx);
fmpz_mod_mpolyn_get_polyun_swap(mB, B, ctx);
success = fmpz_mod_polyu1n_gcd_brown_smprime(mG, mAbar, mBbar, mA, mB,
ctx->ffinfo, St->poly_stack, St->polyun_stack);
fmpz_mod_mpolyn_set_polyun_swap(G, mG, ctx);
fmpz_mod_mpolyn_set_polyun_swap(Abar, mAbar, ctx);
fmpz_mod_mpolyn_set_polyun_swap(Bbar, mBbar, ctx);
fmpz_mod_polyun_stack_give_back(St->polyun_stack, 5);
return success;
}
mpoly_gen_offset_shift_sp(&offset, &shift, var - 1, G->bits, ctx->minfo);
#if FLINT_WANT_ASSERT
fmpz_mod_poly_init(leadA, ctx->ffinfo);
fmpz_mod_poly_init(leadB, ctx->ffinfo);
fmpz_mod_poly_set(leadA, A->coeffs + 0, ctx->ffinfo);
fmpz_mod_poly_set(leadB, B->coeffs + 0, ctx->ffinfo);
fmpz_mod_mpolyn_init(Aorg, bits, ctx);
fmpz_mod_mpolyn_init(Borg, bits, ctx);
fmpz_mod_mpolyn_set(Aorg, A, ctx);
fmpz_mod_mpolyn_set(Borg, B, ctx);
#endif
fmpz_init(alpha);
fmpz_init(temp);
fmpz_init(gammaevalp);
fmpz_init(gammaevalm);
fmpz_mod_poly_stack_fit_request(St->poly_stack, 9);
cA = fmpz_mod_poly_stack_take_top(St->poly_stack);
cB = fmpz_mod_poly_stack_take_top(St->poly_stack);
cG = fmpz_mod_poly_stack_take_top(St->poly_stack);
cAbar = fmpz_mod_poly_stack_take_top(St->poly_stack);
cBbar = fmpz_mod_poly_stack_take_top(St->poly_stack);
gamma = fmpz_mod_poly_stack_take_top(St->poly_stack);
alphapow = fmpz_mod_poly_stack_take_top(St->poly_stack);
modulus = fmpz_mod_poly_stack_take_top(St->poly_stack);
t1 = fmpz_mod_poly_stack_take_top(St->poly_stack);
fmpz_mod_mpolyn_stack_fit_request(St->mpolyn_stack, 12, ctx);
Aevalp = fmpz_mod_mpolyn_stack_take_top(St->mpolyn_stack);
Bevalp = fmpz_mod_mpolyn_stack_take_top(St->mpolyn_stack);
Gevalp = fmpz_mod_mpolyn_stack_take_top(St->mpolyn_stack);
Abarevalp = fmpz_mod_mpolyn_stack_take_top(St->mpolyn_stack);
Bbarevalp = fmpz_mod_mpolyn_stack_take_top(St->mpolyn_stack);
Aevalm = fmpz_mod_mpolyn_stack_take_top(St->mpolyn_stack);
Bevalm = fmpz_mod_mpolyn_stack_take_top(St->mpolyn_stack);
Gevalm = fmpz_mod_mpolyn_stack_take_top(St->mpolyn_stack);
Abarevalm = fmpz_mod_mpolyn_stack_take_top(St->mpolyn_stack);
Bbarevalm = fmpz_mod_mpolyn_stack_take_top(St->mpolyn_stack);
T1 = fmpz_mod_mpolyn_stack_take_top(St->mpolyn_stack);
T2 = fmpz_mod_mpolyn_stack_take_top(St->mpolyn_stack);
_fmpz_mod_poly_vec_remove_content(cA, A->coeffs, A->length, ctx->ffinfo);
_fmpz_mod_poly_vec_remove_content(cB, B->coeffs, B->length, ctx->ffinfo);
_fmpz_mod_poly_gcd_cofactors(cG, cAbar, cBbar, cA, cB, ctx->ffinfo, t1);
fmpz_mod_poly_gcd(gamma, A->coeffs + 0, B->coeffs + 0, ctx->ffinfo);
ldegA = fmpz_mod_mpolyn_lastdeg(A, ctx);
ldegB = fmpz_mod_mpolyn_lastdeg(B, ctx);
deggamma = fmpz_mod_poly_degree(gamma, ctx->ffinfo);
bound = 1 + deggamma + FLINT_MAX(ldegA, ldegB);
upper_limit = mpoly_gcd_info_get_brown_upper_limit(I, var, bound);
fmpz_mod_poly_fit_length(alphapow, FLINT_MAX(WORD(3), bound + 1), ctx->ffinfo);
fmpz_mod_poly_one(modulus, ctx->ffinfo);
fmpz_fdiv_q_2exp(alpha, fmpz_mod_ctx_modulus(ctx->ffinfo), 1);
choose_prime:
fmpz_sub_ui(alpha, alpha, 1);
if (fmpz_sgn(alpha) <= 0)
{
success = 0;
goto cleanup;
}
FLINT_ASSERT(alphapow->alloc >= 2);
alphapow->length = 2;
fmpz_one(alphapow->coeffs + 0);
fmpz_set(alphapow->coeffs + 1, alpha);
fmpz_mod_poly_eval2_pow(gammaevalp, gammaevalm, gamma, alphapow, ctx->ffinfo);
if (fmpz_is_zero(gammaevalp) || fmpz_is_zero(gammaevalm))
{
goto choose_prime;
}
fmpz_mod_mpolyn_interp_reduce_2sm_mpolyn(Aevalp, Aevalm, A, var, alphapow, ctx);
fmpz_mod_mpolyn_interp_reduce_2sm_mpolyn(Bevalp, Bevalm, B, var, alphapow, ctx);
FLINT_ASSERT(Aevalp->length > 0);
FLINT_ASSERT(Aevalm->length > 0);
FLINT_ASSERT(Bevalp->length > 0);
FLINT_ASSERT(Bevalm->length > 0);
success = fmpz_mod_mpolyn_gcd_brown_smprime(Gevalp, Abarevalp, Bbarevalp,
Aevalp, Bevalp, var - 1, ctx, I, St);
success = success &&
fmpz_mod_mpolyn_gcd_brown_smprime(Gevalm, Abarevalm, Bbarevalm,
Aevalm, Bevalm, var - 1, ctx, I, St);
if (success == 0)
{
goto choose_prime;
}
FLINT_ASSERT(Gevalp->length > 0);
FLINT_ASSERT(Abarevalp->length > 0);
FLINT_ASSERT(Bbarevalp->length > 0);
FLINT_ASSERT(Gevalm->length > 0);
FLINT_ASSERT(Abarevalm->length > 0);
FLINT_ASSERT(Bbarevalm->length > 0);
if (fmpz_mod_mpolyn_is_nonzero_fmpz(Gevalp, ctx) ||
fmpz_mod_mpolyn_is_nonzero_fmpz(Gevalm, ctx))
{
fmpz_mod_mpolyn_one(G, ctx);
fmpz_mod_mpolyn_swap(Abar, A, ctx);
fmpz_mod_mpolyn_swap(Bbar, B, ctx);
goto successful_put_content;
}
if (Gevalp->coeffs[0].length != Gevalm->coeffs[0].length ||
!mpoly_monomial_equal(Gevalp->exps + N*0, Gevalm->exps + N*0, N))
{
goto choose_prime;
}
if (fmpz_mod_poly_degree(modulus, ctx->ffinfo) > 0)
{
slong k = fmpz_mod_poly_degree(Gevalp->coeffs + 0, ctx->ffinfo);
int cmp = mpoly_monomial_cmp_nomask_extra(G->exps + N*0,
Gevalp->exps + N*0, N, offset, k << shift);
if (cmp < 0)
{
goto choose_prime;
}
else if (cmp > 0)
{
fmpz_mod_poly_one(modulus, ctx->ffinfo);
}
}
fmpz_mod_mpolyn_scalar_mul_fmpz_mod(Gevalp, gammaevalp, ctx);
fmpz_mod_mpolyn_scalar_mul_fmpz_mod(Gevalm, gammaevalm, ctx);
if (fmpz_mod_poly_degree(modulus, ctx->ffinfo) > 0)
{
fmpz_mod_poly_evaluate_fmpz(temp, modulus, alpha, ctx->ffinfo);
fmpz_mod_mul(temp, temp, alpha, ctx->ffinfo);
fmpz_mod_add(temp, temp, temp, ctx->ffinfo);
fmpz_mod_poly_scalar_div_fmpz(modulus, modulus, temp, ctx->ffinfo);
changed = fmpz_mod_mpolyn_interp_crt_2sm_mpolyn(&ldegG, G, T1,
Gevalp, Gevalm, var, modulus, alphapow, ctx);
if (!changed && _fmpz_mod_poly_degree(modulus) < upper_limit)
{
_fmpz_mod_poly_vec_remove_content(t1, G->coeffs, G->length, ctx->ffinfo);
if (fmpz_mod_mpolyn_divides(T1, A, G, ctx) &&
fmpz_mod_mpolyn_divides(T2, B, G, ctx))
{
fmpz_mod_mpolyn_swap(Abar, T1, ctx);
fmpz_mod_mpolyn_swap(Bbar, T2, ctx);
goto successful_fix_lc;
}
_fmpz_mod_poly_vec_mul_poly(G->coeffs, G->length, t1, ctx->ffinfo);
}
changed = fmpz_mod_mpolyn_interp_crt_2sm_mpolyn(&ldegAbar, Abar, T1,
Abarevalp, Abarevalm, var, modulus, alphapow, ctx);
if (!changed && _fmpz_mod_poly_degree(modulus) < upper_limit)
{
_fmpz_mod_poly_vec_remove_content(t1, Abar->coeffs, Abar->length, ctx->ffinfo);
if (fmpz_mod_mpolyn_divides(T1, A, Abar, ctx) &&
fmpz_mod_mpolyn_divides(T2, B, T1, ctx))
{
fmpz_mod_mpolyn_swap(G, T1, ctx);
fmpz_mod_mpolyn_swap(Bbar, T2, ctx);
goto successful_fix_lc;
}
_fmpz_mod_poly_vec_mul_poly(Abar->coeffs, Abar->length, t1, ctx->ffinfo);
}
changed = fmpz_mod_mpolyn_interp_crt_2sm_mpolyn(&ldegBbar, Bbar, T1,
Bbarevalp, Bbarevalm, var, modulus, alphapow, ctx);
if (!changed && _fmpz_mod_poly_degree(modulus) < upper_limit)
{
_fmpz_mod_poly_vec_remove_content(t1, Bbar->coeffs, Bbar->length, ctx->ffinfo);
if (fmpz_mod_mpolyn_divides(T1, B, Bbar, ctx) &&
fmpz_mod_mpolyn_divides(T2, A, T1, ctx))
{
fmpz_mod_mpolyn_swap(G, T1, ctx);
fmpz_mod_mpolyn_swap(Abar, T2, ctx);
goto successful_fix_lc;
}
_fmpz_mod_poly_vec_mul_poly(Bbar->coeffs, Bbar->length, t1, ctx->ffinfo);
}
}
else
{
fmpz_mod_mpolyn_interp_lift_2sm_mpolyn(&ldegG, G,
Gevalp, Gevalm, var, alpha, ctx);
fmpz_mod_mpolyn_interp_lift_2sm_mpolyn(&ldegAbar, Abar,
Abarevalp, Abarevalm, var, alpha, ctx);
fmpz_mod_mpolyn_interp_lift_2sm_mpolyn(&ldegBbar, Bbar,
Bbarevalp, Bbarevalm, var, alpha, ctx);
}
fmpz_mod_mul(temp, alpha, alpha, ctx->ffinfo);
fmpz_mod_neg(temp, temp, ctx->ffinfo);
fmpz_mod_poly_shift_left_scalar_addmul_fmpz_mod(modulus, 2, temp, ctx->ffinfo);
if (fmpz_mod_poly_degree(modulus, ctx->ffinfo) < bound)
{
goto choose_prime;
}
FLINT_ASSERT(ldegG >= 0);
FLINT_ASSERT(ldegAbar >= 0);
FLINT_ASSERT(ldegBbar >= 0);
if (deggamma + ldegA == ldegG + ldegAbar &&
deggamma + ldegB == ldegG + ldegBbar)
{
goto successful;
}
fmpz_mod_poly_one(modulus, ctx->ffinfo);
goto choose_prime;
successful_fix_lc:
fmpz_set(temp, fmpz_mod_poly_lead(G->coeffs + 0, ctx->ffinfo));
if (fmpz_is_one(temp))
goto successful_put_content;
_fmpz_mod_poly_vec_mul_fmpz_mod(Abar->coeffs, Abar->length, temp, ctx->ffinfo);
_fmpz_mod_poly_vec_mul_fmpz_mod(Bbar->coeffs, Bbar->length, temp, ctx->ffinfo);
fmpz_mod_inv(temp, temp, ctx->ffinfo);
_fmpz_mod_poly_vec_mul_fmpz_mod(G->coeffs, G->length, temp, ctx->ffinfo);
goto successful_put_content;
successful:
_fmpz_mod_poly_vec_remove_content(t1, G->coeffs, G->length, ctx->ffinfo);
_fmpz_mod_poly_vec_divexact_poly(Abar->coeffs, Abar->length, G->coeffs + 0, ctx->ffinfo);
_fmpz_mod_poly_vec_divexact_poly(Bbar->coeffs, Bbar->length, G->coeffs + 0, ctx->ffinfo);
successful_put_content:
_fmpz_mod_poly_vec_mul_poly(G->coeffs, G->length, cG, ctx->ffinfo);
_fmpz_mod_poly_vec_mul_poly(Abar->coeffs, Abar->length, cAbar, ctx->ffinfo);
_fmpz_mod_poly_vec_mul_poly(Bbar->coeffs, Bbar->length, cBbar, ctx->ffinfo);
success = 1;
cleanup:
#if FLINT_WANT_ASSERT
if (success)
{
FLINT_ASSERT(fmpz_is_one(fmpz_mod_mpolyn_leadcoeff(G)));
fmpz_mod_poly_mul(modulus, G->coeffs + 0, Abar->coeffs + 0, ctx->ffinfo);
FLINT_ASSERT(fmpz_mod_poly_equal(modulus, leadA, ctx->ffinfo));
fmpz_mod_poly_mul(modulus, G->coeffs + 0, Bbar->coeffs + 0, ctx->ffinfo);
FLINT_ASSERT(fmpz_mod_poly_equal(modulus, leadB, ctx->ffinfo));
}
fmpz_mod_poly_clear(leadA, ctx->ffinfo);
fmpz_mod_poly_clear(leadB, ctx->ffinfo);
fmpz_mod_mpolyn_clear(Aorg, ctx);
fmpz_mod_mpolyn_clear(Borg, ctx);
#endif
fmpz_clear(alpha);
fmpz_clear(temp);
fmpz_clear(gammaevalp);
fmpz_clear(gammaevalm);
fmpz_mod_poly_stack_give_back(St->poly_stack, 9);
fmpz_mod_mpolyn_stack_give_back(St->mpolyn_stack, 12);
FLINT_ASSERT(success || fmpz_bits(fmpz_mod_mpoly_ctx_modulus(ctx)) < 60);
return success;
}