/* Copyright (C) 2011 Andy Novocin Copyright (C) 2011 Sebastian Pancratz 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_poly.h" void fmpz_poly_factor_deflation(fmpz_poly_factor_t fac, const fmpz_poly_t G, int deflation) { const slong lenG = G->length; fmpz_poly_t g; fac->num = 0; if (lenG <= 1) { if (lenG < 1) fmpz_zero(&fac->c); else fmpz_set(&fac->c, G->coeffs + 0); return; } fmpz_poly_init(g); if (lenG < 5) { fmpz_poly_content(&fac->c, G); if (fmpz_sgn(fmpz_poly_lead(G)) < 0) fmpz_neg(&fac->c, &fac->c); fmpz_poly_scalar_divexact_fmpz(g, G, &fac->c); if (lenG < 3) fmpz_poly_factor_insert(fac, g, 1); else if (lenG == 3) _fmpz_poly_factor_quadratic(fac, g, 1); else _fmpz_poly_factor_cubic(fac, g, 1); } else { slong i, j, k, d; fmpz_poly_factor_t sq_fr_fac; /* Does a presearch for a factor of form x^k */ for (k = 0; fmpz_is_zero(G->coeffs + k); k++) ; if (k != 0) { fmpz_poly_t t; fmpz_poly_init(t); fmpz_poly_set_coeff_ui(t, 1, 1); fmpz_poly_factor_insert(fac, t, k); fmpz_poly_clear(t); } fmpz_poly_shift_right(g, G, k); if (deflation && (d = fmpz_poly_deflation(G)) > 1) { fmpz_poly_factor_t gfac; fmpz_poly_factor_init(gfac); fmpz_poly_deflate(g, g, d); fmpz_poly_factor(gfac, g); fmpz_set(&fac->c, &gfac->c); for (i = 0; i < gfac->num; i++) { fmpz_poly_factor_t hfac; fmpz_poly_factor_init(hfac); fmpz_poly_inflate(gfac->p + i, gfac->p + i, d); fmpz_poly_factor_deflation(hfac, gfac->p + i, 0); for (j = 0; j < hfac->num; j++) fmpz_poly_factor_insert(fac, hfac->p + j, gfac->exp[i] * hfac->exp[j]); fmpz_poly_factor_clear(hfac); } fmpz_poly_factor_clear(gfac); } else { /* Could make other tests for x-1 or simple things maybe take advantage of the composition algorithm */ fmpz_poly_factor_init(sq_fr_fac); fmpz_poly_factor_squarefree(sq_fr_fac, g); fmpz_set(&fac->c, &sq_fr_fac->c); /* Factor each square-free part */ for (j = 0; j < sq_fr_fac->num; j++) { _fmpz_poly_factor_zassenhaus(fac, sq_fr_fac->exp[j], sq_fr_fac->p + j, 8, 1); } fmpz_poly_factor_clear(sq_fr_fac); } } fmpz_poly_clear(g); } void fmpz_poly_factor(fmpz_poly_factor_t fac, const fmpz_poly_t G) { fmpz_poly_factor_deflation(fac, G, 1); }