#include "nmod.h"
#include "n_poly.h"
#include "nmod_mpoly_factor.h"
int n_bpoly_mod_hlift2_cubic(
n_bpoly_t A,
n_bpoly_t B0,
n_bpoly_t B1,
ulong alpha,
slong degree_inner,
nmod_t ctx,
nmod_eval_interp_t E,
n_poly_bpoly_stack_t St)
{
int success;
slong len = nmod_eval_interp_eval_length(E);
slong i, j;
n_poly_struct * c, * s, * t, * u, * v, * ce;
n_bpoly_struct * B0e, * B1e;
FLINT_ASSERT(n_bpoly_mod_is_canonical(A, ctx));
FLINT_ASSERT(n_bpoly_mod_is_canonical(B0, ctx));
FLINT_ASSERT(n_bpoly_mod_is_canonical(B1, ctx));
if (A->length < 1 || B0->length < 1 || B1->length < 1)
return -1;
n_poly_stack_fit_request(St->poly_stack, 6);
c = n_poly_stack_take_top(St->poly_stack);
s = n_poly_stack_take_top(St->poly_stack);
t = n_poly_stack_take_top(St->poly_stack);
u = n_poly_stack_take_top(St->poly_stack);
v = n_poly_stack_take_top(St->poly_stack);
ce = n_poly_stack_take_top(St->poly_stack);
n_bpoly_stack_fit_request(St->bpoly_stack, 2);
B0e = n_bpoly_stack_take_top(St->bpoly_stack);
B1e = n_bpoly_stack_take_top(St->bpoly_stack);
n_bpoly_mod_taylor_shift_gen0(A, alpha, ctx);
n_bpoly_mod_taylor_shift_gen0(B0, alpha, ctx);
n_bpoly_mod_taylor_shift_gen0(B1, alpha, ctx);
#if FLINT_WANT_ASSERT
{
n_poly_t T;
n_poly_init(T);
n_poly_mod_mul(T, B0->coeffs + 0, B1->coeffs + 0, ctx);
FLINT_ASSERT(n_poly_equal(A->coeffs + 0, T));
n_poly_clear(T);
}
#endif
if (n_poly_degree(A->coeffs + 0) != degree_inner)
{
success = -1;
goto cleanup;
}
FLINT_ASSERT(n_bpoly_degree1(A) == n_poly_degree(A->coeffs + 0));
if (!n_poly_mod_invmod(s, B1->coeffs + 0, B0->coeffs + 0, ctx))
{
success = -2;
goto cleanup;
}
n_bpoly_fit_length(B0, A->length);
n_bpoly_fit_length(B0e, A->length);
for (i = 0; i < B0->length; i++)
nmod_eval_interp_from_coeffs_poly(B0e->coeffs + i, B0->coeffs + i, E, ctx);
for (i = B0->length; i < A->length; i++)
{
n_poly_zero(B0->coeffs + i);
nmod_evals_zero(B0e->coeffs + i);
}
n_bpoly_fit_length(B1, A->length);
n_bpoly_fit_length(B1e, A->length);
for (i = 0; i < B1->length; i++)
nmod_eval_interp_from_coeffs_poly(B1e->coeffs + i, B1->coeffs + i, E, ctx);
for (i = B1->length; i < A->length; i++)
{
n_poly_zero(B1->coeffs + i);
nmod_evals_zero(B1e->coeffs + i);
}
for (j = 1; j < A->length; j++)
{
nmod_evals_zero(ce);
for (i = 0; i <= j; i++)
{
if (i < B0->length && j - i < B1->length)
{
nmod_evals_addmul(ce, B0e->coeffs + i,
B1e->coeffs + j - i, len, ctx);
}
}
nmod_eval_interp_to_coeffs_poly(c, ce, E, ctx);
n_poly_mod_sub(c, A->coeffs + j, c, ctx);
#if FLINT_WANT_ASSERT
{
n_poly_t c_check;
n_poly_init(c_check);
n_poly_set(c_check, A->coeffs + j);
for (i = 0; i <= j; i++)
{
if (i < B0->length && j - i < B1->length)
{
n_poly_mod_mul(t, B0->coeffs + i, B1->coeffs + j - i, ctx);
n_poly_mod_sub(c_check, c_check, t, ctx);
}
}
FLINT_ASSERT(n_poly_equal(c, c_check));
n_poly_clear(c_check);
}
#endif
if (n_poly_is_zero(c))
continue;
n_poly_mod_mul(t, s, c, ctx);
n_poly_mod_rem(u, t, B0->coeffs + 0, ctx);
n_poly_mod_mul(t, u, B1->coeffs + 0, ctx);
n_poly_mod_sub(c, c, t, ctx);
n_poly_mod_divexact(v, c, B0->coeffs + 0, ctx);
if (!n_poly_is_zero(u))
{
n_poly_mod_add(B0->coeffs + j, B0->coeffs + j, u, ctx);
nmod_eval_interp_from_coeffs_poly(B0e->coeffs + j, B0->coeffs + j, E, ctx);
}
if (!n_poly_is_zero(v))
{
n_poly_mod_add(B1->coeffs + j, B1->coeffs + j, v, ctx);
nmod_eval_interp_from_coeffs_poly(B1e->coeffs + j, B1->coeffs + j, E, ctx);
}
if (!n_poly_is_zero(B0->coeffs + j))
B0->length = FLINT_MAX(B0->length, j + 1);
if (!n_poly_is_zero(B1->coeffs + j))
B1->length = FLINT_MAX(B1->length, j + 1);
if (B0->length - 1 + B1->length - 1 > A->length - 1)
{
success = 0;
goto cleanup;
}
}
n_bpoly_mod_taylor_shift_gen0(B0, nmod_neg(alpha, ctx), ctx);
n_bpoly_mod_taylor_shift_gen0(B1, nmod_neg(alpha, ctx), ctx);
success = 1;
cleanup:
#if FLINT_WANT_ASSERT
if (success > 0)
{
n_bpoly_t tp1, tp2;
n_bpoly_init(tp1);
n_bpoly_init(tp2);
n_bpoly_mod_taylor_shift_gen0(A, nmod_neg(alpha, ctx), ctx);
n_bpoly_mod_mul(tp1, B0, B1, ctx);
FLINT_ASSERT(n_bpoly_equal(tp1, A));
n_bpoly_clear(tp1);
n_bpoly_clear(tp2);
}
#endif
n_poly_stack_give_back(St->poly_stack, 6);
n_bpoly_stack_give_back(St->bpoly_stack, 2);
return success;
}
int n_bpoly_mod_hlift2(
n_bpoly_t A,
n_bpoly_t B0,
n_bpoly_t B1,
ulong alpha,
slong degree_inner,
nmod_t ctx,
n_poly_bpoly_stack_t St)
{
int success;
slong i, j;
n_poly_struct * c, * s, * t, * u, * v;
FLINT_ASSERT(n_bpoly_mod_is_canonical(A, ctx));
FLINT_ASSERT(n_bpoly_mod_is_canonical(B0, ctx));
FLINT_ASSERT(n_bpoly_mod_is_canonical(B1, ctx));
if (A->length < 1 || B0->length < 1 || B1->length < 1)
return -1;
n_poly_stack_fit_request(St->poly_stack, 5);
c = n_poly_stack_take_top(St->poly_stack);
s = n_poly_stack_take_top(St->poly_stack);
t = n_poly_stack_take_top(St->poly_stack);
u = n_poly_stack_take_top(St->poly_stack);
v = n_poly_stack_take_top(St->poly_stack);
n_bpoly_mod_taylor_shift_gen0(A, alpha, ctx);
n_bpoly_mod_taylor_shift_gen0(B0, alpha, ctx);
n_bpoly_mod_taylor_shift_gen0(B1, alpha, ctx);
#if FLINT_WANT_ASSERT
{
n_poly_t T;
n_poly_init(T);
n_poly_mod_mul(T, B0->coeffs + 0, B1->coeffs + 0, ctx);
FLINT_ASSERT(n_poly_equal(A->coeffs + 0, T));
n_poly_clear(T);
}
#endif
if (n_poly_degree(A->coeffs + 0) != degree_inner)
{
success = -1;
goto cleanup;
}
FLINT_ASSERT(n_bpoly_degree1(A) == n_poly_degree(A->coeffs + 0));
if (!n_poly_mod_invmod(s, B1->coeffs + 0, B0->coeffs + 0, ctx))
{
success = -2;
goto cleanup;
}
n_bpoly_fit_length(B0, A->length);
n_bpoly_fit_length(B1, A->length);
for (j = 1; j < A->length; j++)
{
n_poly_set(c, A->coeffs + j);
for (i = 0; i <= j; i++)
{
if (i < B0->length && j - i < B1->length)
{
n_poly_mod_mul(t, B0->coeffs + i, B1->coeffs + j - i, ctx);
n_poly_mod_sub(c, c, t, ctx);
}
}
if (n_poly_is_zero(c))
continue;
n_poly_mod_mul(t, s, c, ctx);
n_poly_mod_rem(u, t, B0->coeffs + 0, ctx);
n_poly_mod_mul(t, u, B1->coeffs + 0, ctx);
n_poly_mod_sub(c, c, t, ctx);
n_poly_mod_divexact(v, c, B0->coeffs + 0, ctx);
if (j < B0->length)
n_poly_mod_add(B0->coeffs + j, B0->coeffs + j, u, ctx);
else
n_poly_set(B0->coeffs + j, u);
if (j < B1->length)
n_poly_mod_add(B1->coeffs + j, B1->coeffs + j, v, ctx);
else
n_poly_set(B1->coeffs + j, v);
if (!n_poly_is_zero(B0->coeffs + j))
B0->length = FLINT_MAX(B0->length, j + 1);
if (!n_poly_is_zero(B1->coeffs + j))
B1->length = FLINT_MAX(B1->length, j + 1);
if (B0->length - 1 + B1->length - 1 > A->length - 1)
{
success = 0;
goto cleanup;
}
}
n_bpoly_mod_taylor_shift_gen0(B0, nmod_neg(alpha, ctx), ctx);
n_bpoly_mod_taylor_shift_gen0(B1, nmod_neg(alpha, ctx), ctx);
success = 1;
cleanup:
#if FLINT_WANT_ASSERT
if (success > 0)
{
n_bpoly_t tp1, tp2;
n_bpoly_init(tp1);
n_bpoly_init(tp2);
n_bpoly_mod_taylor_shift_gen0(A, nmod_neg(alpha, ctx), ctx);
n_bpoly_mod_mul(tp1, B0, B1, ctx);
FLINT_ASSERT(n_bpoly_equal(tp1, A));
n_bpoly_clear(tp1);
n_bpoly_clear(tp2);
}
#endif
n_poly_stack_give_back(St->poly_stack, 5);
return success;
}
int n_bpoly_mod_hlift_cubic(
slong r,
n_bpoly_t A,
n_bpoly_struct * B,
ulong alpha,
slong degree_inner,
nmod_t ctx,
nmod_eval_interp_t E,
n_poly_bpoly_stack_t St)
{
int success;
slong len = nmod_eval_interp_eval_length(E);
slong i, j, k, tdeg;
n_poly_struct * p, * c, * t, * ce;
n_poly_struct ** s, * vk, ** Binv, * vek;
n_bpoly_struct ** Ue, ** Be;
#if FLINT_WANT_ASSERT
n_bpoly_t Acopy;
n_bpoly_struct * Bcqt;
int successcqt;
#endif
TMP_INIT;
FLINT_ASSERT(r > 2);
FLINT_ASSERT(n_bpoly_mod_is_canonical(A, ctx));
if (A->length < 1)
return -1;
for (i = 0; i < r; i++)
{
FLINT_ASSERT(n_bpoly_mod_is_canonical(B + i, ctx));
if (B[i].length < 1)
return -1;
}
TMP_START;
#if FLINT_WANT_ASSERT
n_bpoly_init(Acopy);
n_bpoly_set(Acopy, A);
Bcqt = FLINT_ARRAY_ALLOC(r, n_bpoly_struct);
for (i = 0; i < r; i++)
{
n_bpoly_init(Bcqt + i);
n_bpoly_set(Bcqt + i, B + i);
}
successcqt = n_bpoly_mod_hlift(r, Acopy, Bcqt, alpha, degree_inner, ctx, St);
#endif
n_bpoly_stack_fit_request(St->bpoly_stack, 2*r);
Ue = TMP_ARRAY_ALLOC(2*r, n_bpoly_struct *);
Be = Ue + r;
for (i = 0; i < r; i++)
{
Ue[i] = n_bpoly_stack_take_top(St->bpoly_stack);
Be[i] = n_bpoly_stack_take_top(St->bpoly_stack);
}
n_poly_stack_fit_request(St->poly_stack, 2*r + 5);
s = TMP_ARRAY_ALLOC(2*r, n_poly_struct *);
Binv = s + r;
for (i = 0; i < r; i++)
{
s[i] = n_poly_stack_take_top(St->poly_stack);
Binv[i] = n_poly_stack_take_top(St->poly_stack);
}
vk = n_poly_stack_take_top(St->poly_stack);
vek = n_poly_stack_take_top(St->poly_stack);
c = n_poly_stack_take_top(St->poly_stack);
t = n_poly_stack_take_top(St->poly_stack);
ce = n_poly_stack_take_top(St->poly_stack);
n_bpoly_mod_taylor_shift_gen0(A, alpha, ctx);
for (i = 0; i < r; i++)
n_bpoly_mod_taylor_shift_gen0(B + i, alpha, ctx);
#if FLINT_WANT_ASSERT
{
n_poly_t T;
n_poly_init(T);
n_poly_mod_mul(T, B[0].coeffs + 0, B[1].coeffs + 0, ctx);
for (i = 2; i < r; i++)
n_poly_mod_mul(T, T, B[i].coeffs + 0, ctx);
FLINT_ASSERT(n_poly_equal(A->coeffs + 0, T));
n_poly_clear(T);
}
#endif
if (n_poly_degree(A->coeffs + 0) != degree_inner)
{
success = -1;
goto cleanup;
}
FLINT_ASSERT(n_bpoly_degree1(A) == degree_inner);
for (k = 0; k < r; k++)
{
n_poly_mod_divexact(t, A->coeffs + 0, B[k].coeffs + 0, ctx);
if (!n_poly_mod_invmod(s[k], t, B[k].coeffs + 0, ctx))
{
success = -1;
goto cleanup;
}
n_poly_reverse(t, B[k].coeffs + 0, B[k].coeffs[0].length);
n_poly_mod_inv_series(Binv[k], t, B[k].coeffs[0].length, ctx);
n_bpoly_fit_length(B + k, A->length);
n_bpoly_fit_length(Be[k], A->length);
for (i = 0; i < B[k].length; i++)
nmod_eval_interp_from_coeffs_poly(Be[k]->coeffs + i,
B[k].coeffs + i, E, ctx);
for (i = B[k].length; i < A->length; i++)
{
n_poly_zero(B[k].coeffs + i);
nmod_evals_zero(Be[k]->coeffs + i);
}
if (k > 0)
{
n_bpoly_fit_length(Ue[k], A->length);
Ue[k]->length = A->length;
for (i = 0; i < A->length; i++)
nmod_evals_zero(Ue[k]->coeffs + i);
}
}
k = r - 2;
nmod_evals_mul(Ue[k]->coeffs + 0, Be[k]->coeffs + 0,
Be[k + 1]->coeffs + 0, len, ctx);
for (k--; k > 0; k--)
nmod_evals_mul(Ue[k]->coeffs + 0, Be[k]->coeffs + 0,
Ue[k + 1]->coeffs + 0, len, ctx);
for (j = 1; j < A->length; j++)
{
k = r - 2;
nmod_evals_zero(Ue[k]->coeffs + j);
for (i = 0; i <= j; i++)
nmod_evals_addmul(Ue[k]->coeffs + j, Be[k]->coeffs + i,
Be[k + 1]->coeffs + j - i, len, ctx);
for (k--; k > 0; k--)
{
nmod_evals_zero(Ue[k]->coeffs + j);
for (i = 0; i <= j; i++)
nmod_evals_addmul(Ue[k]->coeffs + j, Be[k]->coeffs + i,
Ue[k + 1]->coeffs + j - i, len, ctx);
}
nmod_evals_zero(ce);
for (i = 0; i <= j; i++)
nmod_evals_addmul(ce, Be[0]->coeffs + i, Ue[1]->coeffs + j - i, len, ctx);
nmod_eval_interp_to_coeffs_poly(c, ce, E, ctx);
n_poly_mod_sub(c, A->coeffs + j, c, ctx);
if (n_poly_is_zero(c))
continue;
tdeg = 0;
for (k = r - 1; k >= 0; k--)
{
n_poly_mod_rem(t, c, B[k].coeffs + 0, ctx);
n_poly_mod_mulmod_preinv(vk, s[k], t, B[k].coeffs + 0, Binv[k], ctx);
nmod_eval_interp_from_coeffs_poly(vek, vk, E, ctx);
if (!n_poly_is_zero(vk))
{
nmod_evals_add_inplace(Be[k]->coeffs + j, vek, len, ctx);
n_poly_mod_add(B[k].coeffs + j, B[k].coeffs + j, vk, ctx);
if (!n_poly_is_zero(B[k].coeffs + j))
B[k].length = FLINT_MAX(B[k].length, j + 1);
}
tdeg += B[k].length - 1;
if (k > r - 2)
{
n_poly_swap(ce, vek);
}
else if (k > 0)
{
p = (k == r - 2) ? Be[k + 1]->coeffs : Ue[k + 1]->coeffs;
nmod_evals_fmma(ce, Be[k]->coeffs + 0, ce, p, vek, len, ctx);
nmod_evals_add_inplace(Ue[k]->coeffs + j, ce, len, ctx);
}
}
if (tdeg >= A->length)
{
success = 0;
goto cleanup;
}
}
for (k = 0; k < r; k++)
n_bpoly_mod_taylor_shift_gen0(B + k, nmod_neg(alpha, ctx), ctx);
success = 1;
cleanup:
#if FLINT_WANT_ASSERT
FLINT_ASSERT(success == successcqt);
if (success > 0)
{
for (i = 0; i < r; i++)
FLINT_ASSERT(n_bpoly_equal(Bcqt + i, B + i));
}
n_bpoly_clear(Acopy);
for (i = 0; i < r; i++)
n_bpoly_clear(Bcqt + i);
flint_free(Bcqt);
#endif
n_bpoly_stack_give_back(St->bpoly_stack, 2*r);
n_poly_stack_give_back(St->poly_stack, 2*r + 5);
TMP_END;
return success;
}
int n_bpoly_mod_hlift(
slong r,
n_bpoly_t A,
n_bpoly_struct * B,
ulong alpha,
slong degree_inner,
nmod_t ctx,
n_poly_bpoly_stack_t St)
{
int success;
slong i, j, k, tdeg;
n_poly_struct * c, * t, * u;
n_poly_struct ** s, ** v, ** Binv;
n_bpoly_struct ** U;
TMP_INIT;
FLINT_ASSERT(r > 2);
FLINT_ASSERT(n_bpoly_mod_is_canonical(A, ctx));
if (A->length < 1)
return -1;
for (i = 0; i < r; i++)
{
FLINT_ASSERT(n_bpoly_mod_is_canonical(B + i, ctx));
if (B[i].length < 1)
return -1;
}
TMP_START;
n_bpoly_stack_fit_request(St->bpoly_stack, r);
U = TMP_ARRAY_ALLOC(r, n_bpoly_struct *);
for (i = 0; i < r; i++)
{
U[i] = n_bpoly_stack_take_top(St->bpoly_stack);
n_bpoly_fit_length(U[i], A->length);
for (j = 0; j < A->length; j++)
n_poly_zero(U[i]->coeffs + j);
U[i]->length = A->length;
n_bpoly_fit_length(B + i, A->length);
}
n_poly_stack_fit_request(St->poly_stack, 3*r + 3);
s = TMP_ARRAY_ALLOC(3*r, n_poly_struct *);
v = s + r;
Binv = v + r;
for (i = 0; i < r; i++)
{
s[i] = n_poly_stack_take_top(St->poly_stack);
v[i] = n_poly_stack_take_top(St->poly_stack);
Binv[i] = n_poly_stack_take_top(St->poly_stack);
}
c = n_poly_stack_take_top(St->poly_stack);
t = n_poly_stack_take_top(St->poly_stack);
u = n_poly_stack_take_top(St->poly_stack);
n_bpoly_mod_taylor_shift_gen0(A, alpha, ctx);
for (i = 0; i < r; i++)
n_bpoly_mod_taylor_shift_gen0(B + i, alpha, ctx);
#if FLINT_WANT_ASSERT
{
n_poly_t T;
n_poly_init(T);
n_poly_mod_mul(T, B[0].coeffs + 0, B[1].coeffs + 0, ctx);
for (i = 2; i < r; i++)
n_poly_mod_mul(T, T, B[i].coeffs + 0, ctx);
FLINT_ASSERT(n_poly_equal(A->coeffs + 0, T));
n_poly_clear(T);
}
#endif
if (n_poly_degree(A->coeffs + 0) != degree_inner)
{
success = -1;
goto cleanup;
}
FLINT_ASSERT(n_bpoly_degree1(A) == n_poly_degree(A->coeffs + 0));
for (i = 0; i < r; i++)
{
n_poly_one(t);
for (j = 0; j < r; j++)
{
if (j != i)
n_poly_mod_mul(t, t, B[j].coeffs + 0, ctx);
}
if (!n_poly_mod_invmod(s[i], t, B[i].coeffs + 0, ctx))
{
success = -1;
goto cleanup;
}
n_poly_reverse(t, B[i].coeffs + 0, B[i].coeffs[0].length);
n_poly_mod_inv_series(Binv[i], t, B[i].coeffs[0].length, ctx);
}
k = r - 2;
n_poly_mod_mul(U[k]->coeffs + 0, B[k].coeffs + 0, B[k + 1].coeffs + 0, ctx);
for (k--; k > 0; k--)
n_poly_mod_mul(U[k]->coeffs + 0, B[k].coeffs + 0, U[k + 1]->coeffs + 0, ctx);
for (j = 1; j < A->length; j++)
{
for (k = 0; k < r; k++)
n_poly_zero(U[k]->coeffs + j);
k = r - 2;
n_poly_zero(U[k]->coeffs + j);
for (i = 0; i <= j; i++)
{
if (i < B[k].length && j - i < B[k + 1].length)
{
n_poly_mod_mul(t, B[k].coeffs + i, B[k + 1].coeffs + j - i, ctx);
n_poly_mod_add(U[k]->coeffs + j, U[k]->coeffs + j, t, ctx);
}
}
for (k--; k > 0; k--)
{
n_poly_zero(U[k]->coeffs + j);
for (i = 0; i <= j; i++)
{
if (i < B[k].length)
{
n_poly_mod_mul(t, B[k].coeffs + i, U[k + 1]->coeffs + j - i, ctx);
n_poly_mod_add(U[k]->coeffs + j, U[k]->coeffs + j, t, ctx);
}
}
}
n_poly_set(c, A->coeffs + j);
for (i = 0; i <= j; i++)
{
if (i < B[0].length)
{
n_poly_mod_mul(t, B[0].coeffs + i, U[1]->coeffs + j - i, ctx);
n_poly_mod_sub(c, c, t, ctx);
}
}
if (n_poly_is_zero(c))
continue;
tdeg = 0;
for (i = 0; i < r; i++)
{
n_poly_mod_rem(t, c, B[i].coeffs + 0, ctx);
n_poly_mod_mulmod_preinv(v[i], s[i], t, B[i].coeffs + 0, Binv[i], ctx);
while (j >= B[i].length)
{
n_poly_zero(B[i].coeffs + B[i].length);
B[i].length++;
}
n_poly_mod_add(B[i].coeffs + j, B[i].coeffs + j, v[i], ctx);
n_bpoly_normalise(B + i);
tdeg += B[i].length - 1;
}
if (tdeg >= A->length)
{
success = 0;
goto cleanup;
}
k = r - 2;
n_poly_mod_mul(t, B[k].coeffs + 0, v[k + 1], ctx);
n_poly_mod_mul(u, B[k + 1].coeffs + 0, v[k], ctx);
n_poly_mod_add(t, t, u, ctx);
n_poly_mod_add(U[k]->coeffs + j, U[k]->coeffs + j, t, ctx);
for (k--; k > 0; k--)
{
n_poly_mod_mul(u, B[k].coeffs + 0, t, ctx);
n_poly_mod_mul(t, U[k + 1]->coeffs + 0, v[k], ctx);
n_poly_mod_add(t, t, u, ctx);
n_poly_mod_add(U[k]->coeffs + j, U[k]->coeffs + j, t, ctx);
}
}
for (i = 0; i < r; i++)
n_bpoly_mod_taylor_shift_gen0(B + i, nmod_neg(alpha, ctx), ctx);
success = 1;
cleanup:
#if FLINT_WANT_ASSERT
if (success > 0)
{
n_bpoly_t tp1, tp2;
n_bpoly_init(tp1);
n_bpoly_init(tp2);
n_bpoly_mod_taylor_shift_gen0(A, nmod_neg(alpha, ctx), ctx);
n_bpoly_mod_mul(tp1, B + 0, B + 1, ctx);
for (i = 2; i < r; i++)
{
n_bpoly_mod_mul(tp2, tp1, B + i, ctx);
n_bpoly_swap(tp1, tp2);
}
FLINT_ASSERT(n_bpoly_equal(tp1, A));
n_bpoly_clear(tp1);
n_bpoly_clear(tp2);
}
#endif
n_bpoly_stack_give_back(St->bpoly_stack, r);
n_poly_stack_give_back(St->poly_stack, 3*r + 3);
TMP_END;
return success;
}