/*
Copyright (C) 2012 Lina Kulakova
Copyright (C) 2020 Daniel Schultz
This file is part of FLINT.
FLINT is free software: you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (LGPL) as published
by the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version. See .
*/
#include
#include "fmpz_mod_poly.h"
#include "thread_support.h"
void
fmpz_mod_poly_factor_kaltofen_shoup(fmpz_mod_poly_factor_t res,
const fmpz_mod_poly_t poly, const fmpz_mod_ctx_t ctx)
{
slong i, j, k;
slong num_threads = flint_get_num_threads();
fmpz_mod_poly_t t, DDxp, EDxp;
fmpz_mod_poly_factor_t SF, DD, ED;
res->num = 0;
fmpz_mod_poly_init(t, ctx);
fmpz_mod_poly_make_monic(t, poly, ctx);
if (poly->length <= 2)
{
fmpz_mod_poly_factor_insert(res, t, 1, ctx);
fmpz_mod_poly_clear(t, ctx);
return;
}
fmpz_mod_poly_init(DDxp, ctx);
fmpz_mod_poly_init(EDxp, ctx);
fmpz_mod_poly_factor_init(SF, ctx);
fmpz_mod_poly_factor_init(DD, ctx);
fmpz_mod_poly_factor_init(ED, ctx);
fmpz_mod_poly_factor_squarefree(SF, t, ctx);
for (i = 0; i < SF->num; i++)
{
fmpz_mod_poly_struct * f = SF->poly + i;
fmpz_mod_poly_reverse(t, f, f->length, ctx);
fmpz_mod_poly_inv_series_newton(t, t, f->length, ctx);
fmpz_mod_poly_powmod_x_fmpz_preinv(DDxp, fmpz_mod_ctx_modulus(ctx), f, t, ctx);
/*
TODO Since there is a fair amount of code duplicated in the
threaded version, the two functions should be combined into one.
*/
if (num_threads > 1 && f->length > 256*num_threads)
fmpz_mod_poly_factor_distinct_deg_threaded_with_frob(DD, f, t, DDxp, ctx);
else
fmpz_mod_poly_factor_distinct_deg_with_frob(DD, f, t, DDxp, ctx);
for (j = 0; j < DD->num; j++)
{
fmpz_mod_poly_divrem(t, EDxp, DDxp, DD->poly + j, ctx);
fmpz_mod_poly_factor_equal_deg_with_frob(ED, DD->poly + j,
DD->exp[j], EDxp, ctx);
fmpz_mod_poly_factor_fit_length(res, res->num + ED->num, ctx);
for (k = 0; k < ED->num; k++)
{
fmpz_mod_poly_swap(res->poly + res->num, ED->poly + k, ctx);
res->exp[res->num] = SF->exp[i];
res->num++;
}
}
}
fmpz_mod_poly_clear(t, ctx);
fmpz_mod_poly_clear(DDxp, ctx);
fmpz_mod_poly_clear(EDxp, ctx);
fmpz_mod_poly_factor_clear(SF, ctx);
fmpz_mod_poly_factor_clear(DD, ctx);
fmpz_mod_poly_factor_clear(ED, ctx);
}