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