#include "fmpz.h"
#include "mpoly.h"
#include "fmpz_mpoly.h"
int mpoly_divides_select_exps(fmpz_mpoly_t S, fmpz_mpoly_ctx_t zctx,
slong nworkers, ulong * Aexp, slong Alen,
ulong * Bexp, slong Blen, flint_bitcnt_t bits)
{
int failure;
ulong mask;
ulong * Sexp;
slong Slen;
fmpz * Scoeff;
slong nA = 30 + 8*nworkers;
slong nB = (1 + nworkers)/2;
slong tot;
ulong * T0, * T1;
slong i, j, N;
TMP_INIT;
TMP_START;
N = mpoly_words_per_exp(bits, zctx->minfo);
mask = bits <= FLINT_BITS ? mpoly_overflow_mask_sp(bits) : 0;
FLINT_ASSERT(Alen > 0);
FLINT_ASSERT(Blen > 0);
tot = 16 + nA + 2*nB;
fmpz_mpoly_fit_bits(S, bits, zctx);
S->bits = bits;
fmpz_mpoly_fit_length(S, tot, zctx);
Sexp = S->exps;
Scoeff = S->coeffs;
Slen = 0;
mpoly_monomial_set(Sexp + N*Slen, Aexp + N*0, N);
fmpz_one(Scoeff + Slen);
Slen++;
for (i = 1; i < nA; i++)
{
double a = 1.0;
double b = 0.2;
double d = (double)(i) / (double)(nA);
FLINT_ASSERT(a >= 0);
FLINT_ASSERT(b >= 0);
d = d*(1 + (1 - d)*((2 - a - b)*d - (1 - a)));
j = d * Alen;
j = FLINT_MAX(j, WORD(0));
j = FLINT_MIN(j, Alen - 1);
mpoly_monomial_set(Sexp + N*Slen, Aexp + N*j, N);
fmpz_one(Scoeff + Slen);
Slen++;
}
_fmpz_mpoly_set_length(S, Slen, zctx);
T0 = (ulong *) TMP_ALLOC(N*sizeof(ulong));
T1 = (ulong *) TMP_ALLOC(N*sizeof(ulong));
mpoly_monomial_sub_mp(T0, Aexp + N*0, Bexp + N*0, N);
mpoly_monomial_sub_mp(T1, Aexp + N*(Alen - 1), Bexp + N*(Blen - 1), N);
if (bits <= FLINT_BITS)
{
if ( mpoly_monomial_overflows(T0, N, mask)
|| mpoly_monomial_overflows(T1, N, mask))
{
failure = 1;
goto cleanup;
}
}
else
{
if ( mpoly_monomial_overflows_mp(T0, N, bits)
|| mpoly_monomial_overflows_mp(T1, N, bits))
{
failure = 1;
goto cleanup;
}
}
for (i = 1; i < nB; i++)
{
double d = (double)(i) / (double)(nB);
j = d * Blen;
j = FLINT_MAX(j, WORD(0));
j = FLINT_MIN(j, Blen - 1);
mpoly_monomial_sub_mp(Sexp + N*Slen, Aexp + N*0, Bexp + N*0, N);
mpoly_monomial_add_mp(Sexp + N*Slen, Sexp + N*Slen, Bexp + N*j, N);
fmpz_one(Scoeff + Slen);
if (bits <= FLINT_BITS)
Slen += !(mpoly_monomial_overflows(Sexp + N*Slen, N, mask));
else
Slen += !(mpoly_monomial_overflows_mp(Sexp + N*Slen, N, bits));
mpoly_monomial_sub_mp(Sexp + N*Slen, Aexp + N*(Alen - 1), Bexp + N*(Blen - 1), N);
mpoly_monomial_add_mp(Sexp + N*Slen, Sexp + N*Slen, Bexp + N*j, N);
fmpz_one(Scoeff + Slen);
if (bits <= FLINT_BITS)
Slen += !(mpoly_monomial_overflows(Sexp + N*Slen, N, mask));
else
Slen += !(mpoly_monomial_overflows_mp(Sexp + N*Slen, N, bits));
}
mpoly_monomial_zero(Sexp + N*Slen, N);
fmpz_one(Scoeff + Slen);
Slen++;
FLINT_ASSERT(Slen < tot);
_fmpz_mpoly_set_length(S, Slen, zctx);
fmpz_mpoly_sort_terms(S, zctx);
fmpz_mpoly_combine_like_terms(S, zctx);
failure = 0;
cleanup:
TMP_END;
return failure;
}