1 /*
2 Copyright (C) 2014 William Hart
3
4 This file is part of FLINT.
5
6 FLINT is free software: you can redistribute it and/or modify it under
7 the terms of the GNU Lesser General Public License (LGPL) as published
8 by the Free Software Foundation; either version 2.1 of the License, or
9 (at your option) any later version. See <http://www.gnu.org/licenses/>.
10 */
11
12 #include <stdlib.h>
13 #include <gmp.h>
14 #include "flint.h"
15 #include "fmpz_vec.h"
16 #include "fmpz_mod_poly.h"
17
18 void
_fmpz_mod_poly_discriminant(fmpz_t d,const fmpz * poly,slong len,const fmpz_t mod)19 _fmpz_mod_poly_discriminant(fmpz_t d, const fmpz *poly, slong len, const fmpz_t mod)
20 {
21 fmpz *der = _fmpz_vec_init(len - 1);
22 slong dlen = len - 1, exp;
23 fmpz_t pow;
24
25 _fmpz_mod_poly_derivative(der, poly, len, mod);
26 FMPZ_VEC_NORM(der, dlen);
27
28 if (dlen == 0)
29 {
30 fmpz_zero(d);
31 } else
32 {
33 fmpz_init(pow);
34
35 _fmpz_mod_poly_resultant(d, poly, len, der, dlen, mod);
36 exp = len - dlen - 2;
37
38 if (exp >= 0)
39 fmpz_powm_ui(pow, poly + len - 1, exp, mod);
40 else
41 fmpz_invmod(pow, poly + len - 1, mod);
42
43 fmpz_mul(d, d, pow);
44 fmpz_mod(d, d, mod);
45
46 if ((len & 3) == 0 || (len & 3) == 3) /* degree is not 0, 1 mod 4 */
47 fmpz_negmod(d, d, mod);
48
49 fmpz_clear(pow);
50 }
51
52 _fmpz_vec_clear(der, len - 1);
53 }
54
55 void
fmpz_mod_poly_discriminant(fmpz_t d,const fmpz_mod_poly_t f)56 fmpz_mod_poly_discriminant(fmpz_t d, const fmpz_mod_poly_t f)
57 {
58 const slong len = f->length;
59
60 if (len <= 1)
61 fmpz_zero(d);
62 else
63 _fmpz_mod_poly_discriminant(d, f->coeffs, len, &f->p);
64 }
65
66