/* Copyright (C) 2014 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_vec.h" #include "fmpz_mod_poly.h" void _fmpz_mod_poly_discriminant(fmpz_t d, const fmpz *poly, slong len, const fmpz_t mod) { fmpz *der = _fmpz_vec_init(len - 1); slong dlen = len - 1, exp; fmpz_t pow; _fmpz_mod_poly_derivative(der, poly, len, mod); FMPZ_VEC_NORM(der, dlen); if (dlen == 0) { fmpz_zero(d); } else { fmpz_init(pow); _fmpz_mod_poly_resultant(d, poly, len, der, dlen, mod); exp = len - dlen - 2; if (exp >= 0) fmpz_powm_ui(pow, poly + len - 1, exp, mod); else fmpz_invmod(pow, poly + len - 1, mod); fmpz_mul(d, d, pow); fmpz_mod(d, d, mod); if ((len & 3) == 0 || (len & 3) == 3) /* degree is not 0, 1 mod 4 */ fmpz_negmod(d, d, mod); fmpz_clear(pow); } _fmpz_vec_clear(der, len - 1); } void fmpz_mod_poly_discriminant(fmpz_t d, const fmpz_mod_poly_t f, const fmpz_mod_ctx_t ctx) { const slong len = f->length; if (len <= 1) fmpz_zero(d); else _fmpz_mod_poly_discriminant(d, f->coeffs, len, fmpz_mod_ctx_modulus(ctx)); }