1
1
r"""
2
-
3
2
Computation of the Frobenius polynomial using Newton's identities
4
-
5
3
"""
6
-
7
-
8
4
# *****************************************************************************
9
5
# Copyright (C) 2018 Edgar Costa <[email protected] >
10
6
# Distributed under the terms of the GNU General Public License (GPL)
11
7
# https://www.gnu.org/licenses/
12
8
# *****************************************************************************
13
-
14
9
from sage .rings .integer_ring import ZZ
15
10
from sage .functions .log import log
16
11
@@ -23,15 +18,15 @@ def charpoly_frobenius(frob_matrix, charpoly_prec, p, weight, a=1, known_factor=
23
18
24
19
- ``frob_matrix`` -- a matrix representing the Frobenius matrix up to some precision
25
20
26
- - ``charpoly_prec`` -- a vector ai, such that, `frob_matrix.change_ring(ZZ).charpoly()[i]`
27
- will be correct mod `p^ai`, this can be easily deduced from the Hodge numbers and
28
- knowing the q-adic precision of ``frob_matrix``
21
+ - ``charpoly_prec`` -- a vector ai, such that, `` frob_matrix.change_ring(ZZ).charpoly()[i]` `
22
+ will be correct mod `p^ai`, this can be easily deduced from the
23
+ Hodge numbers and knowing the q-adic precision of ``frob_matrix``
29
24
30
25
- ``p`` -- prime `p`
31
26
32
27
- ``weight`` -- weight of the motive
33
28
34
- - ``a`` -- `q = q^a`
29
+ - ``a`` -- `p = q^a`
35
30
36
31
- ``known_factor`` -- the list of coefficients of the known factor
37
32
@@ -195,14 +190,12 @@ def charpoly_frobenius(frob_matrix, charpoly_prec, p, weight, a=1, known_factor=
195
190
sage: F+= F.base_ring()(0).add_bigoh(6)*ones_matrix(*F.dimensions())
196
191
sage: charpoly_frobenius(F, [6, 5, 4, 4], 17, 2)
197
192
[-4913, -221, 13, 1]
198
-
199
-
200
193
"""
201
194
assert known_factor [- 1 ] == 1
202
195
try :
203
196
cp = frob_matrix .change_ring (ZZ ).charpoly ().list ()
204
197
except ValueError :
205
- # the given matrix wasn't integral
198
+ # the given matrix was not integral
206
199
cp = frob_matrix .charpoly ().change_ring (ZZ ).list ()
207
200
assert len (charpoly_prec ) == len (cp ) - (len (known_factor ) - 1 )
208
201
assert cp [- 1 ] == 1
@@ -216,7 +209,7 @@ def charpoly_frobenius(frob_matrix, charpoly_prec, p, weight, a=1, known_factor=
216
209
217
210
# figure out the sign
218
211
# i.e., if it is a reciprocal or an antireciprocal polynomial
219
- if weight % 2 == 1 :
212
+ if weight % 2 :
220
213
# for odd weight the sign is always 1
221
214
# it's the charpoly of a USp matrix
222
215
# and charpoly of a symplectic matrix is reciprocal
@@ -227,7 +220,7 @@ def charpoly_frobenius(frob_matrix, charpoly_prec, p, weight, a=1, known_factor=
227
220
raise NotImplementedError ()
228
221
# we compare ith coefficient and (degree - i)th coefficient to deduce the sign
229
222
# note, if degree is even, the middle coefficient will not help us determine the sign
230
- for i in range ((degree + 1 )// 2 ):
223
+ for i in range ((degree + 1 ) // 2 ):
231
224
# Note: degree*weight is even
232
225
p_power = p ** min (
233
226
charpoly_prec [i ],
@@ -248,19 +241,21 @@ def charpoly_frobenius(frob_matrix, charpoly_prec, p, weight, a=1, known_factor=
248
241
# note, this includes the middle coefficient if degree is even
249
242
halfdegree = degree // 2 + 1
250
243
251
- cp [0 ] = sign * p ** ((a * degree * weight ) // 2 ) # Note: degree*weight is even
244
+ cp [0 ] = sign * p ** ((a * degree * weight ) // 2 )
245
+ # Note: degree*weight is even
246
+
252
247
# calculate the i-th power sum of the roots and correct cp along the way
253
248
e = cp [- halfdegree :]
254
249
e .reverse ()
255
250
for k in range (halfdegree ):
256
- if k % 2 != 0 :
251
+ if k % 2 :
257
252
e [k ] = - e [k ] % mod [degree - k ]
258
253
# e[k] = cp[degree - k] if (k%2 ==0) else -cp[degree - k]
259
254
if k > 0 :
260
255
# verify if p^charpoly_prec[degree - k] > 2*degree/k * q^(w*k/2)
261
256
assert (
262
- log (k ) / log ( p ) + charpoly_prec [degree - k ]
263
- > log (2 * degree ) / log ( p ) + a * 0.5 * weight * k
257
+ log (k , p ) + charpoly_prec [degree - k ]
258
+ > log (2 * degree , p ) + a * 0.5 * weight * k
264
259
), (
265
260
"log(k)/log(p) + charpoly_prec[degree - k] <= log(2*degree)/log(p) + a*0.5*weight*k, k = %d"
266
261
% k
@@ -271,7 +266,7 @@ def charpoly_frobenius(frob_matrix, charpoly_prec, p, weight, a=1, known_factor=
271
266
if len (fix_e ) < halfdegree :
272
267
fix_e .extend ([0 ] * (halfdegree - len (fix_e )))
273
268
for i in range (halfdegree ):
274
- if i % 2 != 0 :
269
+ if i % 2 :
275
270
fix_e [i ] *= - 1
276
271
277
272
# e[k] = \sum x_{i_1} x_{i_2} ... x_{i_k} # where x_* are eigenvalues
@@ -280,7 +275,9 @@ def charpoly_frobenius(frob_matrix, charpoly_prec, p, weight, a=1, known_factor=
280
275
# s[k] = \sum x_i ^k for k>0
281
276
s = [None ] * (halfdegree )
282
277
res = [None ] * len (charpoly_prec )
283
- res [0 ] = sign * p ** ((a * degree * weight ) // 2 ) # Note: degree*weight is even
278
+ res [0 ] = sign * p ** ((a * degree * weight ) // 2 )
279
+ # Note: degree*weight is even
280
+
284
281
res [- 1 ] = 1
285
282
e [1 ] -= fix_e [1 ]
286
283
e [1 ] = e [1 ] % mod [degree - 1 ]
@@ -306,8 +303,9 @@ def charpoly_frobenius(frob_matrix, charpoly_prec, p, weight, a=1, known_factor=
306
303
# (-1)^(k-1) s[k] - S = k*e[k]
307
304
e [k ] = (- S + (- 1 )** (k - 1 ) * s [k ]) // k
308
305
assert (- S + (- 1 )** (k - 1 ) * s [k ]) % k == 0
309
- res [degree - k ] = e [k ] if k % 2 == 0 else - e [k ]
306
+ res [degree - k ] = e [k ] if not k % 2 else - e [k ]
310
307
# Note: degree*weight is even
308
+
311
309
res [k ] = sign * res [degree - k ] * p ** ((a * (degree - 2 * k ) * weight ) // 2 )
312
310
# fix e[k + 1]
313
311
if k + 1 < halfdegree :
0 commit comments