Skip to content

Commit 250b2c7

Browse files
committed
Minor refactor for hyperelliptic curve
1 parent 94fe540 commit 250b2c7

File tree

2 files changed

+68
-26
lines changed

2 files changed

+68
-26
lines changed

src/sage/schemes/hyperelliptic_curves/hyperelliptic_finite_field.py

Lines changed: 52 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@
5757
from sage.rings.power_series_ring import PowerSeriesRing
5858
from . import hyperelliptic_generic
5959
from sage.misc.cachefunc import cached_method
60+
from sage.misc.superseded import deprecated_function_alias
6061
from sage.matrix.constructor import identity_matrix, matrix
6162
from sage.misc.functional import rank
6263
from sage.misc.lazy_import import lazy_import
@@ -297,7 +298,7 @@ def frobenius_matrix(self, N=None, algorithm='hypellfrob'):
297298
ValueError: In the current implementation, p must be greater than (2g+1)(2N-1) = 81
298299
"""
299300
if algorithm != 'hypellfrob':
300-
raise ValueError("Unknown algorithm")
301+
raise ValueError("unknown algorithm")
301302

302303
# By default, use precision enough to be able to compute the
303304
# frobenius minimal polynomial
@@ -306,7 +307,7 @@ def frobenius_matrix(self, N=None, algorithm='hypellfrob'):
306307

307308
return self.frobenius_matrix_hypellfrob(N=N)
308309

309-
def frobenius_polynomial_cardinalities(self, a=None):
310+
def _frobenius_polynomial_cardinalities(self, a=None):
310311
r"""
311312
Compute the charpoly of frobenius, as an element of `\ZZ[x]`,
312313
by computing the number of points on the curve over `g` extensions
@@ -321,33 +322,33 @@ def frobenius_polynomial_cardinalities(self, a=None):
321322
322323
sage: R.<t> = PolynomialRing(GF(37))
323324
sage: H = HyperellipticCurve(t^5 + t + 2)
324-
sage: H.frobenius_polynomial_cardinalities()
325+
sage: H.frobenius_polynomial(algorithm='cardinalities')
325326
x^4 + x^3 - 52*x^2 + 37*x + 1369
326327
327328
A quadratic twist::
328329
329330
sage: H = HyperellipticCurve(2*t^5 + 2*t + 4)
330-
sage: H.frobenius_polynomial_cardinalities()
331+
sage: H.frobenius_polynomial(algorithm='cardinalities')
331332
x^4 - x^3 - 52*x^2 - 37*x + 1369
332333
333334
Curve over a non-prime field::
334335
335336
sage: K.<z> = GF(7**2)
336337
sage: R.<t> = PolynomialRing(K)
337338
sage: H = HyperellipticCurve(t^5 + z*t + z^2)
338-
sage: H.frobenius_polynomial_cardinalities()
339+
sage: H.frobenius_polynomial(algorithm='cardinalities')
339340
x^4 + 8*x^3 + 70*x^2 + 392*x + 2401
340341
341342
This method may actually be useful when ``hypellfrob`` does not work::
342343
343344
sage: K = GF(7)
344345
sage: R.<t> = PolynomialRing(K)
345346
sage: H = HyperellipticCurve(t^9 + t^3 + 1)
346-
sage: H.frobenius_polynomial_matrix(algorithm='hypellfrob')
347+
sage: H.frobenius_polynomial(algorithm='matrix')
347348
Traceback (most recent call last):
348349
...
349350
ValueError: In the current implementation, p must be greater than (2g+1)(2N-1) = 81
350-
sage: H.frobenius_polynomial_cardinalities()
351+
sage: H.frobenius_polynomial(algorithm='cardinalities')
351352
x^8 - 5*x^7 + 7*x^6 + 36*x^5 - 180*x^4 + 252*x^3 + 343*x^2 - 1715*x + 2401
352353
"""
353354
g = self.genus()
@@ -372,7 +373,7 @@ def frobenius_polynomial_cardinalities(self, a=None):
372373

373374
return ZZ['x'](coeffs).reverse()
374375

375-
def frobenius_polynomial_matrix(self, M=None, algorithm='hypellfrob'):
376+
def _frobenius_polynomial_matrix(self, M=None, algorithm='hypellfrob'):
376377
r"""
377378
Compute the charpoly of frobenius, as an element of `\ZZ[x]`,
378379
by computing the charpoly of the frobenius matrix.
@@ -384,25 +385,25 @@ def frobenius_polynomial_matrix(self, M=None, algorithm='hypellfrob'):
384385
385386
sage: R.<t> = PolynomialRing(GF(37))
386387
sage: H = HyperellipticCurve(t^5 + t + 2)
387-
sage: H.frobenius_polynomial_matrix()
388+
sage: H.frobenius_polynomial(algorithm='matrix')
388389
x^4 + x^3 - 52*x^2 + 37*x + 1369
389390
390391
A quadratic twist::
391392
392393
sage: H = HyperellipticCurve(2*t^5 + 2*t + 4)
393-
sage: H.frobenius_polynomial_matrix()
394+
sage: H.frobenius_polynomial(algorithm='matrix')
394395
x^4 - x^3 - 52*x^2 - 37*x + 1369
395396
396397
Curves defined over larger prime fields::
397398
398399
sage: K = GF(49999)
399400
sage: R.<t> = PolynomialRing(K)
400401
sage: H = HyperellipticCurve(t^9 + t^5 + 1)
401-
sage: H.frobenius_polynomial_matrix()
402+
sage: H.frobenius_polynomial(algorithm='matrix')
402403
x^8 + 281*x^7 + 55939*x^6 + 14144175*x^5 + 3156455369*x^4 + 707194605825*x^3
403404
+ 139841906155939*x^2 + 35122892542149719*x + 6249500014999800001
404405
sage: H = HyperellipticCurve(t^15 + t^5 + 1)
405-
sage: H.frobenius_polynomial_matrix() # long time, 8s on a Corei7
406+
sage: H.frobenius_polynomial(algorithm='matrix') # long time, 8s on a Corei7
406407
x^14 - 76*x^13 + 220846*x^12 - 12984372*x^11 + 24374326657*x^10 - 1203243210304*x^9
407408
+ 1770558798515792*x^8 - 74401511415210496*x^7 + 88526169366991084208*x^6
408409
- 3007987702642212810304*x^5 + 3046608028331197124223343*x^4
@@ -440,7 +441,7 @@ def frobenius_polynomial_matrix(self, M=None, algorithm='hypellfrob'):
440441

441442
return ZZ['x'](f)
442443

443-
def frobenius_polynomial_pari(self):
444+
def _frobenius_polynomial_pari(self):
444445
r"""
445446
Compute the charpoly of frobenius, as an element of `\ZZ[x]`,
446447
by calling the PARI function ``hyperellcharpoly``.
@@ -449,43 +450,43 @@ def frobenius_polynomial_pari(self):
449450
450451
sage: R.<t> = PolynomialRing(GF(37))
451452
sage: H = HyperellipticCurve(t^5 + t + 2)
452-
sage: H.frobenius_polynomial_pari()
453+
sage: H.frobenius_polynomial(algorithm='pari')
453454
x^4 + x^3 - 52*x^2 + 37*x + 1369
454455
455456
A quadratic twist::
456457
457458
sage: H = HyperellipticCurve(2*t^5 + 2*t + 4)
458-
sage: H.frobenius_polynomial_pari()
459+
sage: H.frobenius_polynomial(algorithm='pari')
459460
x^4 - x^3 - 52*x^2 - 37*x + 1369
460461
461462
Slightly larger example::
462463
463464
sage: K = GF(2003)
464465
sage: R.<t> = PolynomialRing(K)
465466
sage: H = HyperellipticCurve(t^7 + 487*t^5 + 9*t + 1)
466-
sage: H.frobenius_polynomial_pari()
467+
sage: H.frobenius_polynomial(algorithm='pari')
467468
x^6 - 14*x^5 + 1512*x^4 - 66290*x^3 + 3028536*x^2 - 56168126*x + 8036054027
468469
469470
Curves defined over a non-prime field are supported as well::
470471
471472
sage: K.<a> = GF(7^2)
472473
sage: R.<t> = PolynomialRing(K)
473474
sage: H = HyperellipticCurve(t^5 + a*t + 1)
474-
sage: H.frobenius_polynomial_pari()
475+
sage: H.frobenius_polynomial(algorithm='pari')
475476
x^4 + 4*x^3 + 84*x^2 + 196*x + 2401
476477
477478
sage: K.<z> = GF(23**3)
478479
sage: R.<t> = PolynomialRing(K)
479480
sage: H = HyperellipticCurve(t^3 + z*t + 4)
480-
sage: H.frobenius_polynomial_pari()
481+
sage: H.frobenius_polynomial(algorithm='pari')
481482
x^2 - 15*x + 12167
482483
483484
Over prime fields of odd characteristic, `h` may be nonzero::
484485
485486
sage: K = GF(101)
486487
sage: R.<t> = PolynomialRing(K)
487488
sage: H = HyperellipticCurve(t^5 + 27*t + 3, t)
488-
sage: H.frobenius_polynomial_pari()
489+
sage: H.frobenius_polynomial(algorithm='pari')
489490
x^4 + 2*x^3 - 58*x^2 + 202*x + 10201
490491
491492
TESTS:
@@ -495,17 +496,33 @@ def frobenius_polynomial_pari(self):
495496
sage: P.<x> = PolynomialRing(GF(3))
496497
sage: u = x^10 + x^9 + x^8 + x
497498
sage: C = HyperellipticCurve(u)
498-
sage: C.frobenius_polynomial_pari()
499+
sage: C.frobenius_polynomial(algorithm='pari')
499500
x^8 + 2*x^7 + 6*x^6 + 9*x^5 + 18*x^4 + 27*x^3 + 54*x^2 + 54*x + 81
500501
"""
501502
f, h = self.hyperelliptic_polynomials()
502503
return ZZ['x'](pari([f, h]).hyperellcharpoly())
503504

505+
frobenius_polynomial_cardinalities = deprecated_function_alias(40528, _frobenius_polynomial_cardinalities)
506+
frobenius_polynomial_matrix = deprecated_function_alias(40528, _frobenius_polynomial_matrix)
507+
frobenius_polynomial_pari = deprecated_function_alias(40528, _frobenius_polynomial_pari)
508+
504509
@cached_method
505-
def frobenius_polynomial(self):
510+
def frobenius_polynomial(self, algorithm=None, **kwargs):
506511
r"""
507512
Compute the charpoly of frobenius, as an element of `\ZZ[x]`.
508513
514+
INPUT:
515+
516+
- ``algorithm`` -- (default: ``None``) the algorithm to use, one of
517+
``'cardinalities'``, ``'matrix'``, or ``'pari'``.
518+
519+
Refer to :meth:`frobenius_polynomial_cardinalities`,
520+
:meth:`frobenius_polynomial_matrix`, and
521+
:meth:`frobenius_polynomial_pari` respectively.
522+
523+
- ``**kwargs`` -- additional keyword arguments passed to the
524+
methods above. Undocumented feature, may be removed in the future.
525+
509526
EXAMPLES::
510527
511528
sage: R.<t> = PolynomialRing(GF(37))
@@ -578,6 +595,15 @@ def frobenius_polynomial(self):
578595
sage: C.frobenius_polynomial()
579596
x^8 + 2*x^7 + 6*x^6 + 9*x^5 + 18*x^4 + 27*x^3 + 54*x^2 + 54*x + 81
580597
"""
598+
if algorithm == "cardinalities":
599+
return self._frobenius_polynomial_cardinalities(**kwargs)
600+
elif algorithm == "matrix":
601+
return self._frobenius_polynomial_matrix(**kwargs)
602+
elif algorithm == "pari":
603+
return self._frobenius_polynomial_pari(**kwargs)
604+
elif algorithm is not None:
605+
raise ValueError(f"unknown algorithm {algorithm}")
606+
581607
K = self.base_ring()
582608
e = K.degree()
583609
q = K.cardinality()
@@ -588,11 +614,11 @@ def frobenius_polynomial(self):
588614
if (e == 1 and
589615
q >= (2*g+1)*(2*self._frobenius_coefficient_bound_charpoly()-1) and
590616
h == 0 and f.degree() % 2):
591-
return self.frobenius_polynomial_matrix()
617+
return self.frobenius_polynomial(algorithm='matrix')
592618
elif q % 2 == 1:
593-
return self.frobenius_polynomial_pari()
619+
return self.frobenius_polynomial(algorithm='pari')
594620
else:
595-
return self.frobenius_polynomial_cardinalities()
621+
return self.frobenius_polynomial(algorithm='cardinalities')
596622

597623
def _points_fast_sqrt(self):
598624
"""
@@ -1031,7 +1057,7 @@ def count_points_exhaustive(self, n=1, naive=False):
10311057
a.append(self.cardinality_exhaustive(extension_degree=i))
10321058

10331059
# let's not be too naive and compute the frobenius polynomial
1034-
f = self.frobenius_polynomial_cardinalities(a=a)
1060+
f = self._frobenius_polynomial_cardinalities(a=a)
10351061
return self.count_points_frobenius_polynomial(n=n, f=f)
10361062

10371063
def count_points_hypellfrob(self, n=1, N=None, algorithm=None):
@@ -1116,7 +1142,7 @@ def count_points_hypellfrob(self, n=1, N=None, algorithm=None):
11161142
M = self.frobenius_matrix(N=N, algorithm='hypellfrob')
11171143
return self.count_points_matrix_traces(n=n,M=M,N=N)
11181144
elif algorithm == 'charpoly':
1119-
f = self.frobenius_polynomial_matrix(algorithm='hypellfrob')
1145+
f = self._frobenius_polynomial_matrix(algorithm='hypellfrob')
11201146
return self.count_points_frobenius_polynomial(n=n,f=f)
11211147
else:
11221148
raise ValueError("Unknown algorithm")

src/sage/schemes/hyperelliptic_curves/jacobian_generic.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -416,3 +416,19 @@ def geometric_endomorphism_ring_is_ZZ(self, B=200, proof=False):
416416
if proof:
417417
raise NotImplementedError("Rigorous computation of lower bounds of endomorphism rings has not yet been implemented.")
418418
return False
419+
420+
def cardinality(self):
421+
"""
422+
Return the cardinality of the Jacobian.
423+
Use the formula in `<https://math.stackexchange.com/a/2190894>`_.
424+
425+
EXAMPLES::
426+
427+
sage: R.<x> = GF(3663031)[]
428+
sage: HyperellipticCurve(x^5 + 1758294*x^4 + 1908793*x^3 + 3033920*x^2 + 3445698*x + 3020661).jacobian().cardinality()
429+
13403849798842
430+
"""
431+
from sage.categories.finite_fields import FiniteFields
432+
if self.curve().base_ring() not in FiniteFields():
433+
raise NotImplementedError
434+
return self.curve().frobenius_polynomial()(1)

0 commit comments

Comments
 (0)