/* Copyright (C) 2011 Andy Novocin Copyright (C) 2011, 2016 William Hart 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 /* qsort */ #include "flint.h" #include "fmpz.h" #include "fmpz_poly.h" #include "nmod_poly.h" int _compare_poly_lengths(const void * a, const void * b) { const fmpz_poly_struct * p = (fmpz_poly_struct *) a; const fmpz_poly_struct * q = (fmpz_poly_struct *) b; return p->length - q->length; } int fmpz_poly_factor_van_hoeij_check_if_solved(fmpz_mat_t M, fmpz_poly_factor_t final_fac, fmpz_poly_factor_t lifted_fac, const fmpz_poly_t f, fmpz_t P, slong exp, fmpz_t lc) { fmpz_poly_factor_t trial_factors; fmpz_poly_t prod, q, f_copy; fmpz_t temp_lc; fmpz_mat_t U; nmod_poly_t f2, g2, rem; int num_facs, res = 0; slong i, j, r; slong * part; r = lifted_fac->num; part = (slong *) flint_calloc(r, sizeof(slong)); fmpz_poly_factor_init(trial_factors); fmpz_poly_init(prod); fmpz_poly_init(q); fmpz_poly_init(f_copy); fmpz_mat_window_init(U, M, 0, 0, M->r, r); fmpz_init(temp_lc); nmod_poly_init(f2, 2); nmod_poly_init(g2, 2); nmod_poly_init(rem, 2); if ((num_facs = fmpz_mat_col_partition(part, U, 1)) == 0 || num_facs > r) goto cleanup; if (num_facs == 1) { /* f is irreducible */ fmpz_poly_factor_insert(final_fac, f, exp); res = 1; goto cleanup; } /* there is a potential 0-1 basis, so make the potential factors */ fmpz_set(temp_lc, lc); for (i = 1; i <= num_facs; i++) { fmpz_poly_set_fmpz(prod, temp_lc); for (j = 0; j < r; j++) { if (part[j] == i) { fmpz_poly_mul(prod, prod, lifted_fac->p + j); fmpz_poly_scalar_smod_fmpz(prod, prod, P); } } fmpz_poly_content(temp_lc, prod); fmpz_abs(temp_lc, temp_lc); fmpz_poly_scalar_divexact_fmpz(prod, prod, temp_lc); fmpz_poly_factor_insert(trial_factors, prod, 1); } /* sort factors by length */ qsort(trial_factors->p, trial_factors->num, sizeof(fmpz_poly_struct), _compare_poly_lengths); /* trial divide potential factors */ fmpz_poly_set(f_copy, f); for (i = 0; i < trial_factors->num && num_facs > 1; i++) { /* check if the polynomial divides mod 2 */ fmpz_poly_get_nmod_poly(f2, f_copy); fmpz_poly_get_nmod_poly(g2, trial_factors->p + i); nmod_poly_rem(rem, f2, g2); if (nmod_poly_is_zero(rem) && fmpz_poly_divides(q, f_copy, trial_factors->p + i)) { fmpz_poly_swap(q, f_copy); num_facs--; } else goto cleanup; } /* if we found all the factors, insert them */ if (num_facs == 1) { for (j = 0; j < i; j++) fmpz_poly_factor_insert(final_fac, trial_factors->p + j, exp); fmpz_poly_factor_insert(final_fac, f_copy, exp); res = 1; /* we factorised f */ } cleanup: nmod_poly_clear(f2); nmod_poly_clear(g2); nmod_poly_clear(rem); fmpz_clear(temp_lc); fmpz_poly_clear(q); fmpz_poly_clear(f_copy); fmpz_poly_clear(prod); fmpz_poly_factor_clear(trial_factors); fmpz_mat_window_clear(U); flint_free(part); return res; }