#include "fmpz.h"
#include "fmpz_vec.h"
#include "fmpz_poly.h"
#include "gr.h"
#include "gr_poly.h"
void
_fmpz_poly_divexact(fmpz * Q, const fmpz * A, slong lenA,
const fmpz * B, slong lenB)
{
slong lenQ = lenA - lenB + 1;
if (lenQ == 1)
{
fmpz_divexact(Q, A + lenA - 1, B + lenB - 1);
}
else if (lenB == 1)
{
if (fmpz_is_pm1(B))
_fmpz_vec_scalar_mul_fmpz(Q, A, lenA, B);
else
_fmpz_vec_scalar_divexact_fmpz(Q, A, lenA, B);
}
else if (lenQ <= 100 || lenB <= 16)
{
gr_ctx_t ctx;
gr_ctx_init_fmpz(ctx);
GR_MUST_SUCCEED(_gr_poly_divexact_basecase_bidirectional(Q, A, lenA, B, lenB, ctx));
}
else
{
slong A_bits, B_bits, B_cutoff, Q_cutoff;
gr_ctx_t ctx;
gr_ctx_init_fmpz(ctx);
A_bits = _fmpz_vec_max_bits(A, lenQ);
B_bits = _fmpz_vec_max_bits(B, FLINT_MIN(lenB, lenQ));
A_bits = FLINT_ABS(A_bits);
B_bits = FLINT_ABS(B_bits);
B_cutoff = (B_bits > 3000) ? 20 : 60;
Q_cutoff = (A_bits > 1000) ? 100 : 200;
if (A_bits >= 100 * B_bits)
{
Q_cutoff *= 2;
B_cutoff *= 2;
}
if (lenQ <= Q_cutoff || lenB <= B_cutoff)
GR_MUST_SUCCEED(_gr_poly_divexact_basecase_bidirectional(Q, A, lenA, B, lenB, ctx));
else
_fmpz_poly_div(Q, A, lenA, B, lenB, 0);
}
}
void
fmpz_poly_divexact(fmpz_poly_t Q, const fmpz_poly_t A, const fmpz_poly_t B)
{
fmpz_poly_t T;
slong lenA = A->length;
slong lenB = B->length;
slong lenQ = lenA - lenB + 1;
if (lenB == 0)
{
flint_throw(FLINT_DIVZERO, "Exception (fmpz_poly_divexact). Division by zero.\n");
}
if (lenA < lenB)
{
fmpz_poly_zero(Q);
return;
}
if (Q == A || Q == B)
{
fmpz_poly_init2(T, lenQ);
_fmpz_poly_divexact(T->coeffs, A->coeffs, lenA, B->coeffs, lenB);
_fmpz_poly_set_length(T, lenQ);
fmpz_poly_swap(T, Q);
fmpz_poly_clear(T);
}
else
{
fmpz_poly_fit_length(Q, lenQ);
_fmpz_poly_divexact(Q->coeffs, A->coeffs, lenA, B->coeffs, lenB);
_fmpz_poly_set_length(Q, lenQ);
}
_fmpz_poly_normalise(Q);
}