/* Copyright (C) 2021 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 #include "flint.h" #include "fmpz_mod_vec.h" #include "fmpz_mod_poly.h" /* check if (p, n) = mullow(poly1, len1, poly2, n, n) where len1 > 0, n >= 0 */ static int _fmpz_mod_poly_mullow_classical_check(const fmpz * p, const fmpz * poly1, slong len1, const fmpz * poly2, slong n, fmpz_mod_ctx_t mod) { slong i, n1; fmpz_t c; int res = 1; len1 = FLINT_MIN(len1, n); if (n == 0) return 1; fmpz_init(c); if (n == 1) { fmpz_mod_mul(c, poly1 + 0, poly2 + 0, mod); res = fmpz_equal(p + 0, c); } else { for (i = 0; i < n; i++) { n1 = FLINT_MIN(len1 - 1, i); _fmpz_mod_vec_dot_rev(c, poly1, poly2 + i - n1, n1 + 1, mod); if (!fmpz_equal(p + i, c)) { res = 0; break; } } } fmpz_clear(c); return res; } int _fmpz_mod_poly_divides_classical(fmpz * Q, const fmpz * A, slong lenA, const fmpz * B, slong lenB, fmpz_mod_ctx_t ctx) { slong lenQ = lenA - lenB + 1; fmpz * W; int res; fmpz_t invB; W = _fmpz_vec_init(lenA); fmpz_init(invB); fmpz_invmod(invB, B + lenB - 1, fmpz_mod_ctx_modulus(ctx)); _fmpz_mod_poly_div_basecase(Q, W, A, lenA, B, lenB, invB, fmpz_mod_ctx_modulus(ctx)); /* check coefficients of product one at a time */ res = _fmpz_mod_poly_mullow_classical_check(A, Q, lenQ, B, lenB - 1, ctx); if (!res) _fmpz_vec_zero(Q, lenQ); fmpz_clear(invB); _fmpz_vec_clear(W, lenA); return res; } int fmpz_mod_poly_divides_classical(fmpz_mod_poly_t Q, const fmpz_mod_poly_t A, const fmpz_mod_poly_t B, fmpz_mod_ctx_t ctx) { fmpz_mod_poly_t tQ; fmpz * q; slong lenA, lenB; int res; lenA = A->length; lenB = B->length; if (lenB == 0 || lenA < lenB) { fmpz_mod_poly_zero(Q, ctx); return lenA == 0; } if (Q == A || Q == B) { fmpz_mod_poly_init2(tQ, lenA - lenB + 1, ctx); q = tQ->coeffs; } else { fmpz_mod_poly_fit_length(Q, lenA - lenB + 1, ctx); q = Q->coeffs; } res = _fmpz_mod_poly_divides_classical(q, A->coeffs, lenA, B->coeffs, lenB, ctx); if (Q == A || Q == B) { fmpz_mod_poly_swap(tQ, Q, ctx); fmpz_mod_poly_clear(tQ, ctx); } _fmpz_mod_poly_set_length(Q, lenA - lenB + 1); _fmpz_mod_poly_normalise(Q); return res; }