passagemath-schemes 10.8.1a4__cp314-cp314t-macosx_13_0_arm64.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (312) hide show
  1. passagemath_schemes/.dylibs/libflint.22.0.dylib +0 -0
  2. passagemath_schemes/.dylibs/libgmp.10.dylib +0 -0
  3. passagemath_schemes/.dylibs/libgmpxx.4.dylib +0 -0
  4. passagemath_schemes/.dylibs/libmpfr.6.dylib +0 -0
  5. passagemath_schemes/__init__.py +3 -0
  6. passagemath_schemes-10.8.1a4.dist-info/METADATA +203 -0
  7. passagemath_schemes-10.8.1a4.dist-info/METADATA.bak +204 -0
  8. passagemath_schemes-10.8.1a4.dist-info/RECORD +312 -0
  9. passagemath_schemes-10.8.1a4.dist-info/WHEEL +6 -0
  10. passagemath_schemes-10.8.1a4.dist-info/top_level.txt +3 -0
  11. sage/all__sagemath_schemes.py +23 -0
  12. sage/databases/all__sagemath_schemes.py +7 -0
  13. sage/databases/cremona.py +1723 -0
  14. sage/dynamics/all__sagemath_schemes.py +2 -0
  15. sage/dynamics/arithmetic_dynamics/affine_ds.py +1083 -0
  16. sage/dynamics/arithmetic_dynamics/all.py +14 -0
  17. sage/dynamics/arithmetic_dynamics/berkovich_ds.py +1101 -0
  18. sage/dynamics/arithmetic_dynamics/dynamical_semigroup.py +1543 -0
  19. sage/dynamics/arithmetic_dynamics/endPN_automorphism_group.py +2426 -0
  20. sage/dynamics/arithmetic_dynamics/endPN_minimal_model.py +1169 -0
  21. sage/dynamics/arithmetic_dynamics/generic_ds.py +663 -0
  22. sage/dynamics/arithmetic_dynamics/product_projective_ds.py +339 -0
  23. sage/dynamics/arithmetic_dynamics/projective_ds.py +9556 -0
  24. sage/dynamics/arithmetic_dynamics/projective_ds_helper.cpython-314t-darwin.so +0 -0
  25. sage/dynamics/arithmetic_dynamics/projective_ds_helper.pyx +301 -0
  26. sage/dynamics/arithmetic_dynamics/wehlerK3.py +2578 -0
  27. sage/lfunctions/all.py +18 -0
  28. sage/lfunctions/dokchitser.py +727 -0
  29. sage/lfunctions/pari.py +971 -0
  30. sage/lfunctions/zero_sums.cpython-314t-darwin.so +0 -0
  31. sage/lfunctions/zero_sums.pyx +1847 -0
  32. sage/modular/abvar/abvar.py +5132 -0
  33. sage/modular/abvar/abvar_ambient_jacobian.py +414 -0
  34. sage/modular/abvar/abvar_newform.py +246 -0
  35. sage/modular/abvar/all.py +8 -0
  36. sage/modular/abvar/constructor.py +187 -0
  37. sage/modular/abvar/cuspidal_subgroup.py +371 -0
  38. sage/modular/abvar/finite_subgroup.py +896 -0
  39. sage/modular/abvar/homology.py +721 -0
  40. sage/modular/abvar/homspace.py +989 -0
  41. sage/modular/abvar/lseries.py +415 -0
  42. sage/modular/abvar/morphism.py +935 -0
  43. sage/modular/abvar/torsion_point.py +274 -0
  44. sage/modular/abvar/torsion_subgroup.py +741 -0
  45. sage/modular/all.py +43 -0
  46. sage/modular/arithgroup/all.py +20 -0
  47. sage/modular/arithgroup/arithgroup_element.cpython-314t-darwin.so +0 -0
  48. sage/modular/arithgroup/arithgroup_element.pyx +474 -0
  49. sage/modular/arithgroup/arithgroup_generic.py +1406 -0
  50. sage/modular/arithgroup/arithgroup_perm.py +2692 -0
  51. sage/modular/arithgroup/congroup.cpython-314t-darwin.so +0 -0
  52. sage/modular/arithgroup/congroup.pyx +334 -0
  53. sage/modular/arithgroup/congroup_gamma.py +361 -0
  54. sage/modular/arithgroup/congroup_gamma0.py +692 -0
  55. sage/modular/arithgroup/congroup_gamma1.py +659 -0
  56. sage/modular/arithgroup/congroup_gammaH.py +1491 -0
  57. sage/modular/arithgroup/congroup_generic.py +630 -0
  58. sage/modular/arithgroup/congroup_sl2z.py +266 -0
  59. sage/modular/arithgroup/farey_symbol.cpython-314t-darwin.so +0 -0
  60. sage/modular/arithgroup/farey_symbol.pyx +1067 -0
  61. sage/modular/arithgroup/tests.py +425 -0
  62. sage/modular/btquotients/all.py +4 -0
  63. sage/modular/btquotients/btquotient.py +3736 -0
  64. sage/modular/btquotients/pautomorphicform.py +2564 -0
  65. sage/modular/buzzard.py +100 -0
  66. sage/modular/congroup.py +29 -0
  67. sage/modular/congroup_element.py +13 -0
  68. sage/modular/cusps.py +1107 -0
  69. sage/modular/cusps_nf.py +1270 -0
  70. sage/modular/dims.py +571 -0
  71. sage/modular/dirichlet.py +3310 -0
  72. sage/modular/drinfeld_modform/all.py +2 -0
  73. sage/modular/drinfeld_modform/element.py +446 -0
  74. sage/modular/drinfeld_modform/ring.py +773 -0
  75. sage/modular/drinfeld_modform/tutorial.py +236 -0
  76. sage/modular/etaproducts.py +1076 -0
  77. sage/modular/hecke/algebra.py +725 -0
  78. sage/modular/hecke/all.py +19 -0
  79. sage/modular/hecke/ambient_module.py +994 -0
  80. sage/modular/hecke/degenmap.py +119 -0
  81. sage/modular/hecke/element.py +302 -0
  82. sage/modular/hecke/hecke_operator.py +736 -0
  83. sage/modular/hecke/homspace.py +185 -0
  84. sage/modular/hecke/module.py +1744 -0
  85. sage/modular/hecke/morphism.py +139 -0
  86. sage/modular/hecke/submodule.py +970 -0
  87. sage/modular/hypergeometric_misc.cpython-314t-darwin.so +0 -0
  88. sage/modular/hypergeometric_misc.pxd +4 -0
  89. sage/modular/hypergeometric_misc.pyx +166 -0
  90. sage/modular/hypergeometric_motive.py +2020 -0
  91. sage/modular/local_comp/all.py +2 -0
  92. sage/modular/local_comp/liftings.py +292 -0
  93. sage/modular/local_comp/local_comp.py +1070 -0
  94. sage/modular/local_comp/smoothchar.py +1825 -0
  95. sage/modular/local_comp/type_space.py +748 -0
  96. sage/modular/modform/all.py +30 -0
  97. sage/modular/modform/ambient.py +817 -0
  98. sage/modular/modform/ambient_R.py +177 -0
  99. sage/modular/modform/ambient_eps.py +306 -0
  100. sage/modular/modform/ambient_g0.py +120 -0
  101. sage/modular/modform/ambient_g1.py +199 -0
  102. sage/modular/modform/constructor.py +545 -0
  103. sage/modular/modform/cuspidal_submodule.py +708 -0
  104. sage/modular/modform/defaults.py +14 -0
  105. sage/modular/modform/eis_series.py +487 -0
  106. sage/modular/modform/eisenstein_submodule.py +663 -0
  107. sage/modular/modform/element.py +4105 -0
  108. sage/modular/modform/half_integral.py +154 -0
  109. sage/modular/modform/hecke_operator_on_qexp.py +247 -0
  110. sage/modular/modform/j_invariant.py +47 -0
  111. sage/modular/modform/l_series_gross_zagier.py +127 -0
  112. sage/modular/modform/l_series_gross_zagier_coeffs.cpython-314t-darwin.so +0 -0
  113. sage/modular/modform/l_series_gross_zagier_coeffs.pyx +177 -0
  114. sage/modular/modform/notes.py +45 -0
  115. sage/modular/modform/numerical.py +514 -0
  116. sage/modular/modform/periods.py +14 -0
  117. sage/modular/modform/ring.py +1257 -0
  118. sage/modular/modform/space.py +1859 -0
  119. sage/modular/modform/submodule.py +118 -0
  120. sage/modular/modform/tests.py +64 -0
  121. sage/modular/modform/theta.py +110 -0
  122. sage/modular/modform/vm_basis.py +380 -0
  123. sage/modular/modform/weight1.py +221 -0
  124. sage/modular/modform_hecketriangle/abstract_ring.py +1932 -0
  125. sage/modular/modform_hecketriangle/abstract_space.py +2527 -0
  126. sage/modular/modform_hecketriangle/all.py +30 -0
  127. sage/modular/modform_hecketriangle/analytic_type.py +590 -0
  128. sage/modular/modform_hecketriangle/constructor.py +416 -0
  129. sage/modular/modform_hecketriangle/element.py +351 -0
  130. sage/modular/modform_hecketriangle/functors.py +752 -0
  131. sage/modular/modform_hecketriangle/graded_ring.py +541 -0
  132. sage/modular/modform_hecketriangle/graded_ring_element.py +2225 -0
  133. sage/modular/modform_hecketriangle/hecke_triangle_group_element.py +3349 -0
  134. sage/modular/modform_hecketriangle/hecke_triangle_groups.py +1426 -0
  135. sage/modular/modform_hecketriangle/readme.py +1214 -0
  136. sage/modular/modform_hecketriangle/series_constructor.py +580 -0
  137. sage/modular/modform_hecketriangle/space.py +1037 -0
  138. sage/modular/modform_hecketriangle/subspace.py +423 -0
  139. sage/modular/modsym/all.py +17 -0
  140. sage/modular/modsym/ambient.py +3844 -0
  141. sage/modular/modsym/boundary.py +1420 -0
  142. sage/modular/modsym/element.py +336 -0
  143. sage/modular/modsym/g1list.py +178 -0
  144. sage/modular/modsym/ghlist.py +182 -0
  145. sage/modular/modsym/hecke_operator.py +73 -0
  146. sage/modular/modsym/manin_symbol.cpython-314t-darwin.so +0 -0
  147. sage/modular/modsym/manin_symbol.pxd +5 -0
  148. sage/modular/modsym/manin_symbol.pyx +497 -0
  149. sage/modular/modsym/manin_symbol_list.py +1291 -0
  150. sage/modular/modsym/modsym.py +400 -0
  151. sage/modular/modsym/modular_symbols.py +384 -0
  152. sage/modular/modsym/p1list_nf.py +1241 -0
  153. sage/modular/modsym/relation_matrix.py +591 -0
  154. sage/modular/modsym/relation_matrix_pyx.cpython-314t-darwin.so +0 -0
  155. sage/modular/modsym/relation_matrix_pyx.pyx +108 -0
  156. sage/modular/modsym/space.py +2468 -0
  157. sage/modular/modsym/subspace.py +455 -0
  158. sage/modular/modsym/tests.py +376 -0
  159. sage/modular/multiple_zeta.py +2635 -0
  160. sage/modular/multiple_zeta_F_algebra.py +789 -0
  161. sage/modular/overconvergent/all.py +6 -0
  162. sage/modular/overconvergent/genus0.py +1879 -0
  163. sage/modular/overconvergent/hecke_series.py +1187 -0
  164. sage/modular/overconvergent/weightspace.py +776 -0
  165. sage/modular/pollack_stevens/all.py +4 -0
  166. sage/modular/pollack_stevens/distributions.py +874 -0
  167. sage/modular/pollack_stevens/fund_domain.py +1572 -0
  168. sage/modular/pollack_stevens/manin_map.py +856 -0
  169. sage/modular/pollack_stevens/modsym.py +1590 -0
  170. sage/modular/pollack_stevens/padic_lseries.py +417 -0
  171. sage/modular/pollack_stevens/sigma0.py +534 -0
  172. sage/modular/pollack_stevens/space.py +1078 -0
  173. sage/modular/quasimodform/all.py +3 -0
  174. sage/modular/quasimodform/element.py +846 -0
  175. sage/modular/quasimodform/ring.py +826 -0
  176. sage/modular/quatalg/all.py +3 -0
  177. sage/modular/quatalg/brandt.py +1642 -0
  178. sage/modular/ssmod/all.py +8 -0
  179. sage/modular/ssmod/ssmod.py +827 -0
  180. sage/rings/all__sagemath_schemes.py +1 -0
  181. sage/rings/polynomial/all__sagemath_schemes.py +1 -0
  182. sage/rings/polynomial/binary_form_reduce.py +585 -0
  183. sage/schemes/all.py +41 -0
  184. sage/schemes/berkovich/all.py +6 -0
  185. sage/schemes/berkovich/berkovich_cp_element.py +2582 -0
  186. sage/schemes/berkovich/berkovich_space.py +700 -0
  187. sage/schemes/curves/affine_curve.py +2924 -0
  188. sage/schemes/curves/all.py +33 -0
  189. sage/schemes/curves/closed_point.py +434 -0
  190. sage/schemes/curves/constructor.py +397 -0
  191. sage/schemes/curves/curve.py +542 -0
  192. sage/schemes/curves/plane_curve_arrangement.py +1283 -0
  193. sage/schemes/curves/point.py +463 -0
  194. sage/schemes/curves/projective_curve.py +3203 -0
  195. sage/schemes/curves/weighted_projective_curve.py +106 -0
  196. sage/schemes/curves/zariski_vankampen.py +1931 -0
  197. sage/schemes/cyclic_covers/all.py +2 -0
  198. sage/schemes/cyclic_covers/charpoly_frobenius.py +320 -0
  199. sage/schemes/cyclic_covers/constructor.py +137 -0
  200. sage/schemes/cyclic_covers/cycliccover_finite_field.py +1309 -0
  201. sage/schemes/cyclic_covers/cycliccover_generic.py +310 -0
  202. sage/schemes/elliptic_curves/BSD.py +991 -0
  203. sage/schemes/elliptic_curves/Qcurves.py +592 -0
  204. sage/schemes/elliptic_curves/addition_formulas_ring.py +94 -0
  205. sage/schemes/elliptic_curves/all.py +49 -0
  206. sage/schemes/elliptic_curves/cardinality.py +609 -0
  207. sage/schemes/elliptic_curves/cm.py +1103 -0
  208. sage/schemes/elliptic_curves/constructor.py +1530 -0
  209. sage/schemes/elliptic_curves/ec_database.py +175 -0
  210. sage/schemes/elliptic_curves/ell_curve_isogeny.py +3971 -0
  211. sage/schemes/elliptic_curves/ell_egros.py +457 -0
  212. sage/schemes/elliptic_curves/ell_field.py +2837 -0
  213. sage/schemes/elliptic_curves/ell_finite_field.py +3249 -0
  214. sage/schemes/elliptic_curves/ell_generic.py +3760 -0
  215. sage/schemes/elliptic_curves/ell_local_data.py +1207 -0
  216. sage/schemes/elliptic_curves/ell_modular_symbols.py +775 -0
  217. sage/schemes/elliptic_curves/ell_number_field.py +4220 -0
  218. sage/schemes/elliptic_curves/ell_padic_field.py +107 -0
  219. sage/schemes/elliptic_curves/ell_point.py +4944 -0
  220. sage/schemes/elliptic_curves/ell_rational_field.py +7184 -0
  221. sage/schemes/elliptic_curves/ell_tate_curve.py +671 -0
  222. sage/schemes/elliptic_curves/ell_torsion.py +436 -0
  223. sage/schemes/elliptic_curves/ell_wp.py +352 -0
  224. sage/schemes/elliptic_curves/formal_group.py +760 -0
  225. sage/schemes/elliptic_curves/gal_reps.py +1459 -0
  226. sage/schemes/elliptic_curves/gal_reps_number_field.py +1663 -0
  227. sage/schemes/elliptic_curves/gp_simon.py +152 -0
  228. sage/schemes/elliptic_curves/heegner.py +7328 -0
  229. sage/schemes/elliptic_curves/height.py +2108 -0
  230. sage/schemes/elliptic_curves/hom.py +1788 -0
  231. sage/schemes/elliptic_curves/hom_composite.py +1084 -0
  232. sage/schemes/elliptic_curves/hom_fractional.py +544 -0
  233. sage/schemes/elliptic_curves/hom_frobenius.py +522 -0
  234. sage/schemes/elliptic_curves/hom_scalar.py +531 -0
  235. sage/schemes/elliptic_curves/hom_sum.py +681 -0
  236. sage/schemes/elliptic_curves/hom_velusqrt.py +1290 -0
  237. sage/schemes/elliptic_curves/homset.py +271 -0
  238. sage/schemes/elliptic_curves/isogeny_class.py +1523 -0
  239. sage/schemes/elliptic_curves/isogeny_small_degree.py +2797 -0
  240. sage/schemes/elliptic_curves/jacobian.py +247 -0
  241. sage/schemes/elliptic_curves/kodaira_symbol.py +344 -0
  242. sage/schemes/elliptic_curves/kraus.py +1014 -0
  243. sage/schemes/elliptic_curves/lseries_ell.py +915 -0
  244. sage/schemes/elliptic_curves/mod5family.py +105 -0
  245. sage/schemes/elliptic_curves/mod_poly.py +197 -0
  246. sage/schemes/elliptic_curves/mod_sym_num.cpython-314t-darwin.so +0 -0
  247. sage/schemes/elliptic_curves/mod_sym_num.pyx +3796 -0
  248. sage/schemes/elliptic_curves/modular_parametrization.py +305 -0
  249. sage/schemes/elliptic_curves/padic_lseries.py +1793 -0
  250. sage/schemes/elliptic_curves/padics.py +1816 -0
  251. sage/schemes/elliptic_curves/period_lattice.py +2234 -0
  252. sage/schemes/elliptic_curves/period_lattice_region.cpython-314t-darwin.so +0 -0
  253. sage/schemes/elliptic_curves/period_lattice_region.pyx +722 -0
  254. sage/schemes/elliptic_curves/saturation.py +716 -0
  255. sage/schemes/elliptic_curves/sha_tate.py +1158 -0
  256. sage/schemes/elliptic_curves/weierstrass_morphism.py +1117 -0
  257. sage/schemes/elliptic_curves/weierstrass_transform.py +200 -0
  258. sage/schemes/hyperelliptic_curves/all.py +6 -0
  259. sage/schemes/hyperelliptic_curves/constructor.py +369 -0
  260. sage/schemes/hyperelliptic_curves/hyperelliptic_finite_field.py +1948 -0
  261. sage/schemes/hyperelliptic_curves/hyperelliptic_g2.py +192 -0
  262. sage/schemes/hyperelliptic_curves/hyperelliptic_generic.py +936 -0
  263. sage/schemes/hyperelliptic_curves/hyperelliptic_padic_field.py +1332 -0
  264. sage/schemes/hyperelliptic_curves/hyperelliptic_rational_field.py +84 -0
  265. sage/schemes/hyperelliptic_curves/invariants.py +410 -0
  266. sage/schemes/hyperelliptic_curves/jacobian_endomorphism_utils.py +312 -0
  267. sage/schemes/hyperelliptic_curves/jacobian_g2.py +32 -0
  268. sage/schemes/hyperelliptic_curves/jacobian_generic.py +437 -0
  269. sage/schemes/hyperelliptic_curves/jacobian_homset.py +186 -0
  270. sage/schemes/hyperelliptic_curves/jacobian_morphism.py +878 -0
  271. sage/schemes/hyperelliptic_curves/kummer_surface.py +99 -0
  272. sage/schemes/hyperelliptic_curves/mestre.py +302 -0
  273. sage/schemes/hyperelliptic_curves/monsky_washnitzer.py +3863 -0
  274. sage/schemes/jacobians/abstract_jacobian.py +277 -0
  275. sage/schemes/jacobians/all.py +2 -0
  276. sage/schemes/overview.py +161 -0
  277. sage/schemes/plane_conics/all.py +22 -0
  278. sage/schemes/plane_conics/con_field.py +1296 -0
  279. sage/schemes/plane_conics/con_finite_field.py +158 -0
  280. sage/schemes/plane_conics/con_number_field.py +456 -0
  281. sage/schemes/plane_conics/con_rational_field.py +406 -0
  282. sage/schemes/plane_conics/con_rational_function_field.py +581 -0
  283. sage/schemes/plane_conics/constructor.py +249 -0
  284. sage/schemes/plane_quartics/all.py +2 -0
  285. sage/schemes/plane_quartics/quartic_constructor.py +71 -0
  286. sage/schemes/plane_quartics/quartic_generic.py +53 -0
  287. sage/schemes/riemann_surfaces/all.py +1 -0
  288. sage/schemes/riemann_surfaces/riemann_surface.py +4177 -0
  289. sage_wheels/share/cremona/cremona_mini.db +0 -0
  290. sage_wheels/share/ellcurves/rank0 +30427 -0
  291. sage_wheels/share/ellcurves/rank1 +31871 -0
  292. sage_wheels/share/ellcurves/rank10 +6 -0
  293. sage_wheels/share/ellcurves/rank11 +6 -0
  294. sage_wheels/share/ellcurves/rank12 +1 -0
  295. sage_wheels/share/ellcurves/rank14 +1 -0
  296. sage_wheels/share/ellcurves/rank15 +1 -0
  297. sage_wheels/share/ellcurves/rank17 +1 -0
  298. sage_wheels/share/ellcurves/rank19 +1 -0
  299. sage_wheels/share/ellcurves/rank2 +2388 -0
  300. sage_wheels/share/ellcurves/rank20 +1 -0
  301. sage_wheels/share/ellcurves/rank21 +1 -0
  302. sage_wheels/share/ellcurves/rank22 +1 -0
  303. sage_wheels/share/ellcurves/rank23 +1 -0
  304. sage_wheels/share/ellcurves/rank24 +1 -0
  305. sage_wheels/share/ellcurves/rank28 +1 -0
  306. sage_wheels/share/ellcurves/rank3 +836 -0
  307. sage_wheels/share/ellcurves/rank4 +10 -0
  308. sage_wheels/share/ellcurves/rank5 +5 -0
  309. sage_wheels/share/ellcurves/rank6 +5 -0
  310. sage_wheels/share/ellcurves/rank7 +5 -0
  311. sage_wheels/share/ellcurves/rank8 +6 -0
  312. sage_wheels/share/ellcurves/rank9 +7 -0
@@ -0,0 +1,1948 @@
1
+ # sage_setup: distribution = sagemath-schemes
2
+ # sage.doctest: needs sage.rings.finite_rings
3
+ r"""
4
+ Hyperelliptic curves over a finite field
5
+
6
+ EXAMPLES::
7
+
8
+ sage: K.<a> = GF(9, 'a')
9
+ sage: x = polygen(K)
10
+ sage: C = HyperellipticCurve(x^7 - x^5 - 2, x^2 + a)
11
+ sage: C._points_fast_sqrt()
12
+ [(0 : 1 : 0), (a + 1 : a : 1), (a + 1 : a + 1 : 1), (2 : a + 1 : 1),
13
+ (2*a : 2*a + 2 : 1), (2*a : 2*a : 1), (1 : a + 1 : 1)]
14
+
15
+ AUTHORS:
16
+
17
+ - David Kohel (2006)
18
+
19
+ - Robert Bradshaw (2007)
20
+
21
+ - Alyson Deines, Marina Gresham, Gagan Sekhon, (2010)
22
+
23
+ - Daniel Krenn (2011)
24
+
25
+ - Jean-Pierre Flori, Jan Tuitman (2013)
26
+
27
+ - Kiran Kedlaya (2016)
28
+
29
+ - Dean Bisogno (2017): Fixed Hasse-Witt computation
30
+ """
31
+ # ****************************************************************************
32
+ # Copyright (C) 2006 David Kohel <kohel@maths.usyd.edu>
33
+ # Copyright (C) 2007 Robert Bradshaw <robertwb@math.washington.edu>
34
+ # Copyright (C) 2010 Alyson Deines <aly.deines@gmail.com>, Marina Gresham
35
+ # <marina.gresham@coloradocollege.edu>, Gagan Sekhon <gagan.d.sekhon@gmail.com>
36
+ # Copyright (C) 2011 Daniel Krenn
37
+ # Copyright (C) 2013 Jean-Pierre Flori <jean-pierre.flori@ssi.gouv.fr>,
38
+ # Jan Tuitman <jan.tuitman@wis.kuleuven.be>
39
+ # Copyright (C) 2016 Kiran Kedlaya <kedlaya@ucsd.edu>
40
+ #
41
+ # Distributed under the terms of the GNU General Public License (GPL)
42
+ #
43
+ # This code is distributed in the hope that it will be useful,
44
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
45
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
46
+ # General Public License for more details.
47
+ #
48
+ # The full text of the GPL is available at:
49
+ #
50
+ # https://www.gnu.org/licenses/
51
+ # ****************************************************************************
52
+
53
+ from sage.rings.integer_ring import ZZ
54
+ from sage.rings.real_mpfr import RR
55
+ from sage.rings.rational_field import QQ
56
+ from sage.rings.finite_rings.finite_field_constructor import FiniteField as GF
57
+ from sage.arith.misc import binomial
58
+ from sage.rings.power_series_ring import PowerSeriesRing
59
+ from . import hyperelliptic_generic
60
+ from sage.misc.cachefunc import cached_method
61
+ from sage.misc.superseded import deprecated_function_alias
62
+ from sage.matrix.constructor import identity_matrix, matrix
63
+ from sage.misc.functional import rank
64
+ from sage.misc.lazy_import import lazy_import
65
+
66
+ lazy_import('sage.libs.pari', 'pari')
67
+ lazy_import('sage.schemes.hyperelliptic_curves.hypellfrob', 'hypellfrob')
68
+
69
+ from sage.schemes.curves.projective_curve import ProjectivePlaneCurve_finite_field
70
+
71
+
72
+ class HyperellipticCurve_finite_field(hyperelliptic_generic.HyperellipticCurve_generic,
73
+ ProjectivePlaneCurve_finite_field):
74
+ def _frobenius_coefficient_bound_charpoly(self):
75
+ r"""
76
+ Compute bound on number of `p`-adic digits needed to recover
77
+ frobenius polynomial computing the characteristic polynomial
78
+ of the frobenius matrix, i.e. return `B` so that knowledge of
79
+ `a_1`, ..., `a_g` modulo `p^B` determine frobenius polynomial
80
+ uniquely.
81
+
82
+ The bound used here stems from the expression of the coefficients
83
+ of the characteristic polynomial of the Frobenius as sums
84
+ of products of its eigenvalues:
85
+
86
+ .. MATH::
87
+
88
+ \| a_i \| \leq \binom{2g}{i} \sqrt{q}^i
89
+
90
+ EXAMPLES::
91
+
92
+ sage: R.<t> = PolynomialRing(GF(37))
93
+ sage: HyperellipticCurve(t^3 + t + 1)._frobenius_coefficient_bound_charpoly()
94
+ 1
95
+ sage: HyperellipticCurve(t^5 + t + 1)._frobenius_coefficient_bound_charpoly()
96
+ 2
97
+ sage: HyperellipticCurve(t^7 + t + 1)._frobenius_coefficient_bound_charpoly()
98
+ 3
99
+
100
+ sage: R.<t> = PolynomialRing(GF(next_prime(10^9)))
101
+ sage: HyperellipticCurve(t^3 + t + 1)._frobenius_coefficient_bound_charpoly()
102
+ 1
103
+ sage: HyperellipticCurve(t^5 + t + 1)._frobenius_coefficient_bound_charpoly()
104
+ 2
105
+ sage: HyperellipticCurve(t^7 + t + 1)._frobenius_coefficient_bound_charpoly()
106
+ 2
107
+ sage: HyperellipticCurve(t^9 + t + 1)._frobenius_coefficient_bound_charpoly()
108
+ 3
109
+ sage: HyperellipticCurve(t^11 + t + 1)._frobenius_coefficient_bound_charpoly()
110
+ 3
111
+ sage: HyperellipticCurve(t^13 + t + 1)._frobenius_coefficient_bound_charpoly()
112
+ 4
113
+ """
114
+ assert self.base_ring().is_finite()
115
+ p = self.base_ring().characteristic()
116
+ q = self.base_ring().order()
117
+ sqrtq = RR(q).sqrt()
118
+ g = self.genus()
119
+
120
+ # note: this bound is from Kedlaya's paper, but he tells me it's not
121
+ # the best possible
122
+ M = 2 * binomial(2*g, g) * sqrtq**g
123
+ B = ZZ(M.ceil()).exact_log(p)
124
+ if p**B < M:
125
+ B += 1
126
+ return B
127
+
128
+ def _frobenius_coefficient_bound_traces(self, n=1):
129
+ r"""
130
+ Compute bound on number of `p`-adic digits needed to recover
131
+ the number of rational points on `n` extensions computing
132
+ traces of the frobenius matrix powers, i.e. return `B` so that
133
+ knowledge of `\tr(M^1)`, ..., `\tr(M^n)` modulo `p^B` determine
134
+ `N_1`, ..., `N_n` uniquely.
135
+
136
+ The formula stems from the expression of the trace of the Frobenius
137
+ as a sum of `i`-th powers of its eigenvalues.
138
+
139
+ .. MATH::
140
+
141
+ \| \tr(M^i) \| \leq 2 g \sqrt{q}^i
142
+
143
+ EXAMPLES::
144
+
145
+ sage: R.<t> = PolynomialRing(GF(37))
146
+ sage: HyperellipticCurve(t^3 + t + 1)._frobenius_coefficient_bound_traces()
147
+ 1
148
+ sage: HyperellipticCurve(t^5 + t + 1)._frobenius_coefficient_bound_traces()
149
+ 2
150
+ sage: HyperellipticCurve(t^7 + t + 1)._frobenius_coefficient_bound_traces()
151
+ 2
152
+
153
+ sage: R.<t> = PolynomialRing(GF(next_prime(10^9)))
154
+ sage: HyperellipticCurve(t^3 + t + 1)._frobenius_coefficient_bound_traces()
155
+ 1
156
+ sage: HyperellipticCurve(t^5 + t + 1)._frobenius_coefficient_bound_traces()
157
+ 1
158
+ sage: HyperellipticCurve(t^7 + t + 1)._frobenius_coefficient_bound_traces()
159
+ 1
160
+ sage: HyperellipticCurve(t^9 + t + 1)._frobenius_coefficient_bound_traces(n=3)
161
+ 2
162
+ sage: HyperellipticCurve(t^11 + t + 1)._frobenius_coefficient_bound_traces(n=3)
163
+ 2
164
+ sage: HyperellipticCurve(t^13 + t + 1)._frobenius_coefficient_bound_traces(n=5)
165
+ 3
166
+
167
+ sage: R.<t> = PolynomialRing(GF(11))
168
+ sage: H = HyperellipticCurve(t^5 - t + 1)
169
+ sage: H._frobenius_coefficient_bound_traces()
170
+ 2
171
+ """
172
+ p = self.base_ring().characteristic()
173
+ q = self.base_ring().order()
174
+ sqrtq = RR(q).sqrt()
175
+ g = self.genus()
176
+
177
+ M = 4 * g * sqrtq**n
178
+ B = ZZ(M.ceil()).exact_log(p)
179
+ if p**B < M:
180
+ B += 1
181
+ return B
182
+
183
+ def frobenius_matrix_hypellfrob(self, N=None):
184
+ r"""
185
+ Compute `p`-adic frobenius matrix to precision `p^N`.
186
+ If `N` not supplied, a default value is selected, which is the
187
+ minimum needed to recover the charpoly unambiguously.
188
+
189
+ .. NOTE::
190
+
191
+ Implemented using ``hypellfrob``, which means it only works
192
+ over the prime field `GF(p)`, and requires `p > (2g+1)(2N-1)`.
193
+
194
+ EXAMPLES::
195
+
196
+ sage: R.<t> = PolynomialRing(GF(37))
197
+ sage: H = HyperellipticCurve(t^5 + t + 2)
198
+ sage: H.frobenius_matrix_hypellfrob()
199
+ [1258 + O(37^2) 925 + O(37^2) 132 + O(37^2) 587 + O(37^2)]
200
+ [1147 + O(37^2) 814 + O(37^2) 241 + O(37^2) 1011 + O(37^2)]
201
+ [1258 + O(37^2) 1184 + O(37^2) 1105 + O(37^2) 482 + O(37^2)]
202
+ [1073 + O(37^2) 999 + O(37^2) 772 + O(37^2) 929 + O(37^2)]
203
+
204
+ The ``hypellfrob`` program doesn't support non-prime fields::
205
+
206
+ sage: K.<z> = GF(37**3)
207
+ sage: R.<t> = PolynomialRing(K)
208
+ sage: H = HyperellipticCurve(t^9 + z*t^3 + 1)
209
+ sage: H.frobenius_matrix_hypellfrob()
210
+ Traceback (most recent call last):
211
+ ...
212
+ NotImplementedError: Computation of Frobenius matrix only implemented
213
+ for hyperelliptic curves defined over prime fields.
214
+
215
+ nor too small characteristic::
216
+
217
+ sage: K = GF(7)
218
+ sage: R.<t> = PolynomialRing(K)
219
+ sage: H = HyperellipticCurve(t^9 + t^3 + 1)
220
+ sage: H.frobenius_matrix_hypellfrob()
221
+ Traceback (most recent call last):
222
+ ...
223
+ ValueError: In the current implementation, p must be greater than (2g+1)(2N-1) = 81
224
+ """
225
+ p = self.base_ring().characteristic()
226
+ e = self.base_ring().degree()
227
+ if e != 1:
228
+ raise NotImplementedError("Computation of Frobenius matrix only implemented for hyperelliptic curves defined over prime fields.")
229
+
230
+ f, h = self.hyperelliptic_polynomials()
231
+ if h != 0:
232
+ # need y^2 = f(x)
233
+ raise NotImplementedError("only implemented for curves y^2 = f(x)")
234
+
235
+ sign = 1
236
+ if not f.is_monic():
237
+ # at this time we need a monic f
238
+ c = f.leading_coefficient()
239
+ f = f / c
240
+ if c.is_square():
241
+ # solutions of $y^2 = c * f(x)$ correspond naturally to
242
+ # solutions of $(sqrt(c) y)^2 = f(x)$
243
+ pass
244
+ else:
245
+ # we'll count points on a twist and then correct by untwisting...
246
+ sign = -1
247
+ assert f.is_monic()
248
+
249
+ # By default, use precision enough to be able to compute the
250
+ # frobenius minimal polynomial
251
+ if N is None:
252
+ N = self._frobenius_coefficient_bound_charpoly()
253
+
254
+ matrix_of_frobenius = hypellfrob(p, N, f)
255
+ matrix_of_frobenius = sign * matrix_of_frobenius
256
+ return matrix_of_frobenius
257
+
258
+ def frobenius_matrix(self, N=None, algorithm='hypellfrob'):
259
+ r"""
260
+ Compute `p`-adic frobenius matrix to precision `p^N`.
261
+ If `N` not supplied, a default value is selected, which is the
262
+ minimum needed to recover the charpoly unambiguously.
263
+
264
+ .. NOTE::
265
+
266
+ Currently only implemented using ``hypellfrob``,
267
+ which means it only works over the prime field `GF(p)`,
268
+ and requires `p > (2g+1)(2N-1)`.
269
+
270
+ EXAMPLES::
271
+
272
+ sage: R.<t> = PolynomialRing(GF(37))
273
+ sage: H = HyperellipticCurve(t^5 + t + 2)
274
+ sage: H.frobenius_matrix()
275
+ [1258 + O(37^2) 925 + O(37^2) 132 + O(37^2) 587 + O(37^2)]
276
+ [1147 + O(37^2) 814 + O(37^2) 241 + O(37^2) 1011 + O(37^2)]
277
+ [1258 + O(37^2) 1184 + O(37^2) 1105 + O(37^2) 482 + O(37^2)]
278
+ [1073 + O(37^2) 999 + O(37^2) 772 + O(37^2) 929 + O(37^2)]
279
+
280
+ The ``hypellfrob`` program doesn't support non-prime fields::
281
+
282
+ sage: K.<z> = GF(37**3)
283
+ sage: R.<t> = PolynomialRing(K)
284
+ sage: H = HyperellipticCurve(t^9 + z*t^3 + 1)
285
+ sage: H.frobenius_matrix(algorithm='hypellfrob')
286
+ Traceback (most recent call last):
287
+ ...
288
+ NotImplementedError: Computation of Frobenius matrix only implemented
289
+ for hyperelliptic curves defined over prime fields.
290
+
291
+ nor too small characteristic::
292
+
293
+ sage: K = GF(7)
294
+ sage: R.<t> = PolynomialRing(K)
295
+ sage: H = HyperellipticCurve(t^9 + t^3 + 1)
296
+ sage: H.frobenius_matrix(algorithm='hypellfrob')
297
+ Traceback (most recent call last):
298
+ ...
299
+ ValueError: In the current implementation, p must be greater than (2g+1)(2N-1) = 81
300
+ """
301
+ if algorithm != 'hypellfrob':
302
+ raise ValueError("unknown algorithm")
303
+
304
+ # By default, use precision enough to be able to compute the
305
+ # frobenius minimal polynomial
306
+ if N is None:
307
+ N = self._frobenius_coefficient_bound_charpoly()
308
+
309
+ return self.frobenius_matrix_hypellfrob(N=N)
310
+
311
+ def _frobenius_polynomial_cardinalities(self, a=None):
312
+ r"""
313
+ Helper method for :meth:`frobenius_polynomial`.
314
+
315
+ EXAMPLES::
316
+
317
+ sage: R.<t> = PolynomialRing(GF(37))
318
+ sage: H = HyperellipticCurve(t^5 + t + 2)
319
+ sage: H.frobenius_polynomial(algorithm='cardinalities')
320
+ x^4 + x^3 - 52*x^2 + 37*x + 1369
321
+
322
+ A quadratic twist::
323
+
324
+ sage: H = HyperellipticCurve(2*t^5 + 2*t + 4)
325
+ sage: H.frobenius_polynomial(algorithm='cardinalities')
326
+ x^4 - x^3 - 52*x^2 - 37*x + 1369
327
+
328
+ Curve over a non-prime field::
329
+
330
+ sage: K.<z> = GF(7**2)
331
+ sage: R.<t> = PolynomialRing(K)
332
+ sage: H = HyperellipticCurve(t^5 + z*t + z^2)
333
+ sage: H.frobenius_polynomial(algorithm='cardinalities')
334
+ x^4 + 8*x^3 + 70*x^2 + 392*x + 2401
335
+
336
+ This method may actually be useful when ``hypellfrob`` does not work::
337
+
338
+ sage: K = GF(7)
339
+ sage: R.<t> = PolynomialRing(K)
340
+ sage: H = HyperellipticCurve(t^9 + t^3 + 1)
341
+ sage: H.frobenius_polynomial(algorithm='matrix')
342
+ Traceback (most recent call last):
343
+ ...
344
+ ValueError: In the current implementation, p must be greater than (2g+1)(2N-1) = 81
345
+ sage: H.frobenius_polynomial(algorithm='cardinalities')
346
+ x^8 - 5*x^7 + 7*x^6 + 36*x^5 - 180*x^4 + 252*x^3 + 343*x^2 - 1715*x + 2401
347
+ """
348
+ g = self.genus()
349
+ q = self.base_ring().cardinality()
350
+
351
+ if a is None:
352
+ # this may actually call frobenius_polynomial()
353
+ a = self.count_points(g)
354
+ # maybe calling count_points_exhaustive() would make more sense
355
+ # but the method is currently only called with a precomputed list
356
+ # of number of points so it does not really matter
357
+
358
+ # computation of the reciprocal polynomial
359
+ s = [ai - q**(i+1) - 1 for i, ai in enumerate(a)]
360
+ coeffs = [1]
361
+ for i in range(1, g + 1):
362
+ c = 0
363
+ for j in range(i):
364
+ c += s[i-1-j]*coeffs[j]
365
+ coeffs.append(c/i)
366
+ coeffs = coeffs + [coeffs[g-i] * q**(i) for i in range(1, g + 1)]
367
+
368
+ return ZZ['x'](coeffs).reverse()
369
+
370
+ def _frobenius_polynomial_matrix(self, M=None, algorithm='hypellfrob'):
371
+ r"""
372
+ Helper method for :meth:`frobenius_polynomial`.
373
+
374
+ EXAMPLES::
375
+
376
+ sage: R.<t> = PolynomialRing(GF(37))
377
+ sage: H = HyperellipticCurve(t^5 + t + 2)
378
+ sage: H.frobenius_polynomial(algorithm='matrix')
379
+ x^4 + x^3 - 52*x^2 + 37*x + 1369
380
+
381
+ A quadratic twist::
382
+
383
+ sage: H = HyperellipticCurve(2*t^5 + 2*t + 4)
384
+ sage: H.frobenius_polynomial(algorithm='matrix')
385
+ x^4 - x^3 - 52*x^2 - 37*x + 1369
386
+
387
+ Curves defined over larger prime fields::
388
+
389
+ sage: K = GF(49999)
390
+ sage: R.<t> = PolynomialRing(K)
391
+ sage: H = HyperellipticCurve(t^9 + t^5 + 1)
392
+ sage: H.frobenius_polynomial(algorithm='matrix')
393
+ x^8 + 281*x^7 + 55939*x^6 + 14144175*x^5 + 3156455369*x^4 + 707194605825*x^3
394
+ + 139841906155939*x^2 + 35122892542149719*x + 6249500014999800001
395
+ sage: H = HyperellipticCurve(t^15 + t^5 + 1)
396
+ sage: H.frobenius_polynomial(algorithm='matrix') # long time, 8s on a Corei7
397
+ x^14 - 76*x^13 + 220846*x^12 - 12984372*x^11 + 24374326657*x^10 - 1203243210304*x^9
398
+ + 1770558798515792*x^8 - 74401511415210496*x^7 + 88526169366991084208*x^6
399
+ - 3007987702642212810304*x^5 + 3046608028331197124223343*x^4
400
+ - 81145833008762983138584372*x^3 + 69007473838551978905211279154*x^2
401
+ - 1187357507124810002849977200076*x + 781140631562281254374947500349999
402
+
403
+ This ``hypellfrob`` program doesn't support non-prime fields::
404
+
405
+ sage: K.<z> = GF(37**3)
406
+ sage: R.<t> = PolynomialRing(K)
407
+ sage: H = HyperellipticCurve(t^9 + z*t^3 + 1)
408
+ sage: H.frobenius_polynomial_matrix(algorithm='hypellfrob')
409
+ Traceback (most recent call last):
410
+ ...
411
+ NotImplementedError: Computation of Frobenius matrix only implemented
412
+ for hyperelliptic curves defined over prime fields.
413
+ """
414
+ K = self.base_ring()
415
+ p = K.characteristic()
416
+ q = K.cardinality()
417
+ g = self.genus()
418
+ N = self._frobenius_coefficient_bound_charpoly()
419
+ # compute charpoly over ZZ and then reduce back
420
+ # (because charpoly of p-adic matrices sometimes loses precision)
421
+ M = self.frobenius_matrix(N=N, algorithm=algorithm).change_ring(ZZ)
422
+
423
+ # get a_g, ..., a_0 in ZZ (i.e. with correct signs)
424
+ f = M.charpoly().list()[g:2*g+1]
425
+ ppow = p**N
426
+ f = [x % ppow for x in f]
427
+ f = [x if 2*x < ppow else x - ppow for x in f]
428
+
429
+ # get a_{2g}, ..., a_{g+1}
430
+ f = [f[g-i] * q**(g-i) for i in range(g)] + f
431
+
432
+ return ZZ['x'](f)
433
+
434
+ def _frobenius_polynomial_pari(self):
435
+ r"""
436
+ Helper method for :meth:`frobenius_polynomial`.
437
+
438
+ EXAMPLES::
439
+
440
+ sage: R.<t> = PolynomialRing(GF(37))
441
+ sage: H = HyperellipticCurve(t^5 + t + 2)
442
+ sage: H.frobenius_polynomial(algorithm='pari')
443
+ x^4 + x^3 - 52*x^2 + 37*x + 1369
444
+
445
+ A quadratic twist::
446
+
447
+ sage: H = HyperellipticCurve(2*t^5 + 2*t + 4)
448
+ sage: H.frobenius_polynomial(algorithm='pari')
449
+ x^4 - x^3 - 52*x^2 - 37*x + 1369
450
+
451
+ Slightly larger example::
452
+
453
+ sage: K = GF(2003)
454
+ sage: R.<t> = PolynomialRing(K)
455
+ sage: H = HyperellipticCurve(t^7 + 487*t^5 + 9*t + 1)
456
+ sage: H.frobenius_polynomial(algorithm='pari')
457
+ x^6 - 14*x^5 + 1512*x^4 - 66290*x^3 + 3028536*x^2 - 56168126*x + 8036054027
458
+
459
+ Curves defined over a non-prime field are supported as well::
460
+
461
+ sage: K.<a> = GF(7^2)
462
+ sage: R.<t> = PolynomialRing(K)
463
+ sage: H = HyperellipticCurve(t^5 + a*t + 1)
464
+ sage: H.frobenius_polynomial(algorithm='pari')
465
+ x^4 + 4*x^3 + 84*x^2 + 196*x + 2401
466
+
467
+ sage: K.<z> = GF(23**3)
468
+ sage: R.<t> = PolynomialRing(K)
469
+ sage: H = HyperellipticCurve(t^3 + z*t + 4)
470
+ sage: H.frobenius_polynomial(algorithm='pari')
471
+ x^2 - 15*x + 12167
472
+
473
+ Over prime fields of odd characteristic, `h` may be nonzero::
474
+
475
+ sage: K = GF(101)
476
+ sage: R.<t> = PolynomialRing(K)
477
+ sage: H = HyperellipticCurve(t^5 + 27*t + 3, t)
478
+ sage: H.frobenius_polynomial(algorithm='pari')
479
+ x^4 + 2*x^3 - 58*x^2 + 202*x + 10201
480
+
481
+ TESTS:
482
+
483
+ Check that :issue:`28789` is fixed::
484
+
485
+ sage: P.<x> = PolynomialRing(GF(3))
486
+ sage: u = x^10 + x^9 + x^8 + x
487
+ sage: C = HyperellipticCurve(u)
488
+ sage: C.frobenius_polynomial(algorithm='pari')
489
+ x^8 + 2*x^7 + 6*x^6 + 9*x^5 + 18*x^4 + 27*x^3 + 54*x^2 + 54*x + 81
490
+ """
491
+ f, h = self.hyperelliptic_polynomials()
492
+ return ZZ['x'](pari([f, h]).hyperellcharpoly())
493
+
494
+ frobenius_polynomial_cardinalities = deprecated_function_alias(
495
+ 40528, _frobenius_polynomial_cardinalities,
496
+ replacement='frobenius_polynomial(algorithm="cardinalities")',
497
+ replacement_rst_doc=':meth:`frobenius_polynomial(algorithm="cardinalities") <frobenius_polynomial>`')
498
+ frobenius_polynomial_matrix = deprecated_function_alias(
499
+ 40528, _frobenius_polynomial_matrix,
500
+ replacement='frobenius_polynomial(algorithm="matrix")',
501
+ replacement_rst_doc=':meth:`frobenius_polynomial(algorithm="matrix") <frobenius_polynomial>`')
502
+ frobenius_polynomial_pari = deprecated_function_alias(
503
+ 40528, _frobenius_polynomial_pari,
504
+ replacement='frobenius_polynomial(algorithm="pari")',
505
+ replacement_rst_doc=':meth:`frobenius_polynomial(algorithm="pari") <frobenius_polynomial>`')
506
+
507
+ @cached_method
508
+ def frobenius_polynomial(self, algorithm=None, **kwargs):
509
+ r"""
510
+ Compute the charpoly of frobenius, as an element of `\ZZ[x]`.
511
+
512
+ INPUT:
513
+
514
+ - ``algorithm`` -- the algorithm to use, one of
515
+
516
+ - ``None`` (default) -- automatically select an algorithm.
517
+
518
+ - ``'pari'`` -- use the PARI function ``hyperellcharpoly``.
519
+
520
+ - ``'cardinalities'`` -- compute the number of points on the curve over `g`
521
+ extensions of the base field where `g` is the genus of the curve.
522
+
523
+ .. WARNING::
524
+
525
+ This is highly inefficient when the base field or the genus of the
526
+ curve are large.
527
+
528
+ - ``'matrix'`` -- compute the charpoly of the frobenius matrix.
529
+
530
+ This is currently only supported when the base field is prime
531
+ and large enough using the ``hypellfrob`` library.
532
+
533
+ - ``**kwargs`` -- additional keyword arguments passed to the
534
+ internal method. Undocumented feature, may be removed in the future.
535
+
536
+ EXAMPLES::
537
+
538
+ sage: R.<t> = PolynomialRing(GF(37))
539
+ sage: H = HyperellipticCurve(t^5 + t + 2)
540
+ sage: H.frobenius_polynomial()
541
+ x^4 + x^3 - 52*x^2 + 37*x + 1369
542
+
543
+ A quadratic twist::
544
+
545
+ sage: H = HyperellipticCurve(2*t^5 + 2*t + 4)
546
+ sage: H.frobenius_polynomial()
547
+ x^4 - x^3 - 52*x^2 - 37*x + 1369
548
+
549
+ Slightly larger example::
550
+
551
+ sage: K = GF(2003)
552
+ sage: R.<t> = PolynomialRing(K)
553
+ sage: H = HyperellipticCurve(t^7 + 487*t^5 + 9*t + 1)
554
+ sage: H.frobenius_polynomial()
555
+ x^6 - 14*x^5 + 1512*x^4 - 66290*x^3 + 3028536*x^2 - 56168126*x + 8036054027
556
+
557
+ Curves defined over a non-prime field of odd characteristic,
558
+ or an odd prime field which is too small compared to the genus,
559
+ are supported via PARI::
560
+
561
+ sage: K.<z> = GF(23**3)
562
+ sage: R.<t> = PolynomialRing(K)
563
+ sage: H = HyperellipticCurve(t^3 + z*t + 4)
564
+ sage: H.frobenius_polynomial()
565
+ x^2 - 15*x + 12167
566
+
567
+ sage: K.<z> = GF(3**3)
568
+ sage: R.<t> = PolynomialRing(K)
569
+ sage: H = HyperellipticCurve(t^5 + z*t + z**3)
570
+ sage: H.frobenius_polynomial()
571
+ x^4 - 3*x^3 + 10*x^2 - 81*x + 729
572
+
573
+ Over prime fields of odd characteristic, `h` may be nonzero::
574
+
575
+ sage: K = GF(101)
576
+ sage: R.<t> = PolynomialRing(K)
577
+ sage: H = HyperellipticCurve(t^5 + 27*t + 3, t)
578
+ sage: H.frobenius_polynomial()
579
+ x^4 + 2*x^3 - 58*x^2 + 202*x + 10201
580
+
581
+ Over prime fields of odd characteristic, `f` may have even degree::
582
+
583
+ sage: H = HyperellipticCurve(t^6 + 27*t + 3)
584
+ sage: H.frobenius_polynomial()
585
+ x^4 + 25*x^3 + 322*x^2 + 2525*x + 10201
586
+
587
+ In even characteristic, the naive algorithm could cover all cases
588
+ because we can easily check for squareness in quotient rings of
589
+ polynomial rings over finite fields but these rings unfortunately
590
+ do not support iteration::
591
+
592
+ sage: K.<z> = GF(2**5)
593
+ sage: R.<t> = PolynomialRing(K)
594
+ sage: H = HyperellipticCurve(t^5 + z*t + z**3, t)
595
+ sage: H.frobenius_polynomial()
596
+ x^4 - x^3 + 16*x^2 - 32*x + 1024
597
+
598
+ TESTS:
599
+
600
+ Check that :issue:`28789` is fixed::
601
+
602
+ sage: P.<x> = PolynomialRing(GF(3))
603
+ sage: u = x^10 + x^9 + x^8 + x
604
+ sage: C = HyperellipticCurve(u)
605
+ sage: C.frobenius_polynomial()
606
+ x^8 + 2*x^7 + 6*x^6 + 9*x^5 + 18*x^4 + 27*x^3 + 54*x^2 + 54*x + 81
607
+ """
608
+ if algorithm == "cardinalities":
609
+ return self._frobenius_polynomial_cardinalities(**kwargs)
610
+ elif algorithm == "matrix":
611
+ return self._frobenius_polynomial_matrix(**kwargs)
612
+ elif algorithm == "pari":
613
+ return self._frobenius_polynomial_pari(**kwargs)
614
+ elif algorithm is not None:
615
+ raise ValueError(f"unknown algorithm {algorithm}")
616
+
617
+ K = self.base_ring()
618
+ e = K.degree()
619
+ q = K.cardinality()
620
+
621
+ g = self.genus()
622
+ f, h = self.hyperelliptic_polynomials()
623
+
624
+ if (e == 1 and
625
+ q >= (2*g+1)*(2*self._frobenius_coefficient_bound_charpoly()-1) and
626
+ h == 0 and f.degree() % 2):
627
+ return self.frobenius_polynomial(algorithm='matrix')
628
+ elif q % 2 == 1:
629
+ return self.frobenius_polynomial(algorithm='pari')
630
+ else:
631
+ return self.frobenius_polynomial(algorithm='cardinalities')
632
+
633
+ def _points_fast_sqrt(self):
634
+ """
635
+ List points by enumerating over x and solving the resulting
636
+ quadratic for y.
637
+
638
+ EXAMPLES::
639
+
640
+ sage: K.<a> = GF(9, 'a')
641
+ sage: x = polygen(K)
642
+ sage: C = HyperellipticCurve(x^7 - 1, x^2 + a)
643
+ sage: C._points_fast_sqrt()
644
+ [(0 : 1 : 0), (a : 2*a + 1 : 1), (2 : a + 1 : 1), (2*a + 2 : 2*a : 1),
645
+ (2*a + 2 : 1 : 1), (1 : 2*a + 2 : 1), (1 : 0 : 1)]
646
+ sage: K.<a> = GF(49, 'a')
647
+ sage: x = polygen(K)
648
+ sage: C = HyperellipticCurve(x^5 - x^2 - 1, x^2 + a)
649
+ sage: len(C._points_fast_sqrt())
650
+ 31
651
+
652
+ TESTS::
653
+
654
+ sage: x = polygen(GF(16, 'a'))
655
+ sage: C = HyperellipticCurve(x^5 - x + 1, x^2 + x + 1)
656
+ sage: set(C._points_fast_sqrt()) == set(C._points_cache_sqrt())
657
+ True
658
+ sage: x = polygen(GF(19))
659
+ sage: C = HyperellipticCurve(x^5 + 5*x^2 + 1, x + 1)
660
+ sage: set(C._points_fast_sqrt()) == set(C._points_cache_sqrt())
661
+ True
662
+ sage: x = polygen(GF(13))
663
+ sage: C = HyperellipticCurve(x^3 + x^2 - 1)
664
+ sage: C._points_fast_sqrt()
665
+ [(0 : 1 : 0), (0 : 5 : 1), (0 : 8 : 1), (1 : 1 : 1), (1 : 12 : 1),
666
+ (3 : 3 : 1), (3 : 10 : 1), (4 : 1 : 1), (4 : 12 : 1), (6 : 2 : 1),
667
+ (6 : 11 : 1), (7 : 1 : 1), (7 : 12 : 1), (8 : 4 : 1), (8 : 9 : 1),
668
+ (9 : 4 : 1), (9 : 9 : 1), (12 : 5 : 1), (12 : 8 : 1)]
669
+ sage: set(C._points_fast_sqrt()) == set(C._points_cache_sqrt())
670
+ True
671
+ """
672
+ # For givaro finite fields, taking square roots is very fast
673
+ # so no need to cache as in prime case
674
+ K = self.base_ring()
675
+ f, h = self.hyperelliptic_polynomials()
676
+ one = K(1)
677
+
678
+ # start with the points at infinity
679
+ P = self.defining_polynomial()
680
+ if not P(K(0), K(1), K(0)):
681
+ # (0:1:0) is a point on the curve
682
+ points = [self.point([K(0), K(1), K(0)], check=True)]
683
+ else:
684
+ points = []
685
+ if P.degree() > 2:
686
+ # P(1, y, 0) = r*y + s
687
+ s = P(K(1), K(0), K(0))
688
+ r = P(K(1), K(1), K(0)) - s
689
+ if r: # r not zero
690
+ points.append(self.point([K(1), -s/r, K(0)], check=True))
691
+ # the case r = 0 need not be considered
692
+ elif K.characteristic() == 2: # deg(P) = 2 and char(K) = 2
693
+ # quadratic equation doesn't work in characteristic 2 so use brute
694
+ # force
695
+ points += [self.point([K(1), y, K(0)], check=True) for y in K
696
+ if not P(K(1), y, K(0))]
697
+ else: # deg(P) = 2 and char(K) not 2
698
+ # P(1, y, 0) = y^2 + r*y + s
699
+ s = -f[2]
700
+ r = h[1]
701
+ d = r**2/4 - s
702
+ if not d: # d = 0
703
+ points.append(self.point([K(1), -r/2, K(0)], check=True))
704
+ elif d.is_square():
705
+ sqrtd = d.sqrt()
706
+ points.append(self.point([K(1), -r/2+sqrtd, K(0)], check=True))
707
+ points.append(self.point([K(1), -r/2-sqrtd, K(0)], check=True))
708
+
709
+ if K.characteristic() == 2:
710
+ # quadratic equation doesn't work in characteristic 2
711
+ if h.is_zero():
712
+ for x in K:
713
+ points.append(self.point([x, f(x).sqrt(), one], check=True))
714
+ else:
715
+ a_sqrts = { } # Artin-Schreier 2-roots
716
+ for x in K:
717
+ a_sqrts[x**2 + x] = x # char 2 => x^2 - x == x^2 + x
718
+ for x in K:
719
+ b = h(x)
720
+ c = f(x)
721
+ if b:
722
+ try:
723
+ r = a_sqrts[c / b**2]
724
+ points.append(self.point([x, r*b, one], check=True))
725
+ points.append(self.point([x, r*b+b, one], check=True))
726
+ except KeyError:
727
+ # y^2 + by + c irreducible, so yields no points
728
+ pass
729
+ else: # b == 0
730
+ points.append(self.point([x, c.sqrt(), one], check=True))
731
+ elif h.is_zero():
732
+ # special case to save work if we are of the form y^2 = f(x)
733
+ for x in K:
734
+ y2 = f(x)
735
+ if not y2: # y = 0
736
+ points.append(self.point([x, y2, one], check=True))
737
+ elif y2.is_square():
738
+ y = y2.sqrt()
739
+ points.append(self.point([x, y, one], check=True))
740
+ points.append(self.point([x, -y, one], check=True))
741
+ else:
742
+ b = -h/2
743
+ D = b*b + f
744
+ for x in K:
745
+ Dval = D(x)
746
+ if not Dval: # D(x) = 0
747
+ points.append(self.point([x, b(x), one], check=True))
748
+ elif Dval.is_square():
749
+ sqrtD = Dval.sqrt()
750
+ v = b(x)
751
+ points.append(self.point([x, v+sqrtD, one], check=True))
752
+ points.append(self.point([x, v-sqrtD, one], check=True))
753
+ return points
754
+
755
+ def _points_cache_sqrt(self, brute_force=False):
756
+ """
757
+ List points by enumerating over x and solving the resulting
758
+ quadratic for y.
759
+
760
+ Caches all square roots ahead of time by squaring every element of
761
+ the field. Elements must have an __index__ method.
762
+
763
+ EXAMPLES::
764
+
765
+ sage: x = polygen(GF(7))
766
+ sage: C = HyperellipticCurve(x^3 + x^2 - 1)
767
+ sage: C._points_cache_sqrt()
768
+ [(0 : 1 : 0), (1 : 6 : 1), (1 : 1 : 1), (2 : 5 : 1), (2 : 2 : 1),
769
+ (3 : 0 : 1), (4 : 4 : 1), (4 : 3 : 1), (5 : 4 : 1), (5 : 3 : 1)]
770
+ sage: set(C._points_cache_sqrt()) == set(C._points_cache_sqrt(brute_force=True))
771
+ True
772
+ """
773
+ K = self.base_ring()
774
+ if K.characteristic() != 2:
775
+ # cache the squares (faster than O(p) sqrts)
776
+ square_roots = [None] * len(K)
777
+ for x in K:
778
+ square_roots[x*x] = x
779
+ f, h = self.hyperelliptic_polynomials()
780
+ one = K(1)
781
+
782
+ # start with the points at infinity
783
+ P = self.defining_polynomial()
784
+ if not P(K(0), K(1), K(0)):
785
+ # (0:1:0) is a point on the curve
786
+ points = [self.point([K(0), K(1), K(0)], check=True)]
787
+ else:
788
+ points = []
789
+ if P.degree() > 2:
790
+ # P(1, y, 0) = r*y + s
791
+ s = P(K(1), K(0), K(0))
792
+ r = P(K(1), K(1), K(0)) - s
793
+ if r: # r not zero
794
+ points.append(self.point([K(1), -s/r, K(0)], check=True))
795
+ # the case r = 0 need not be considered
796
+ elif K.characteristic() == 2: # deg(P) = 2 and char(K) = 2
797
+ # quadratic equation doesn't work in characteristic 2 so use brute
798
+ # force
799
+ points += [self.point([K(1), y, K(0)], check=True) for y in K
800
+ if not P(K(1), y, K(0))]
801
+ else: # deg(P) = 2 and char(K) not 2
802
+ # P(1, y, 0) = y^2 + r*y + s
803
+ s = -f[2]
804
+ r = h[1]
805
+ d = r**2/4 - s
806
+ sqrtd = square_roots[d]
807
+ if not d: # d = 0
808
+ points.append(self.point([K(1), -r/2, K(0)], check=True))
809
+ elif sqrtd is not None:
810
+ points.append(self.point([K(1), -r/2+sqrtd, K(0)], check=True))
811
+ points.append(self.point([K(1), -r/2-sqrtd, K(0)], check=True))
812
+
813
+ if K.characteristic() == 2 or brute_force:
814
+ # quadratic equation doesn't work in characteristic 2
815
+ # but there are only 4 affine points, so just test them
816
+ f = self.defining_polynomial()
817
+ points += [self.point([x, y, one], check=True) for x in K for y in K if not f(x, y, one)]
818
+ elif h.is_zero():
819
+ # special case to save work if we are of the form y^2 = f(x)
820
+ for x in K:
821
+ y2 = f(x)
822
+ y = square_roots[y2]
823
+ if not y2: # y = 0
824
+ points.append(self.point([x, y2, one], check=True))
825
+ elif y is not None:
826
+ points.append(self.point([x, y, one], check=True))
827
+ points.append(self.point([x, -y, one], check=True))
828
+ else:
829
+ b = -h/2
830
+ D = b*b + f # this is really disc/4
831
+ for x in K:
832
+ Dval = D(x)
833
+ sqrtD = square_roots[Dval]
834
+ if not Dval: # D(x) = 0
835
+ points.append(self.point([x, b(x), one], check=True))
836
+ elif sqrtD is not None:
837
+ v = b(x)
838
+ points.append(self.point([x, v+sqrtD, one], check=True))
839
+ points.append(self.point([x, v-sqrtD, one], check=True))
840
+ return points
841
+
842
+ def points(self):
843
+ r"""
844
+ All the points on this hyperelliptic curve.
845
+
846
+ EXAMPLES::
847
+
848
+ sage: x = polygen(GF(7))
849
+ sage: C = HyperellipticCurve(x^7 - x^2 - 1)
850
+ sage: C.points()
851
+ [(0 : 1 : 0), (2 : 5 : 1), (2 : 2 : 1), (3 : 0 : 1), (4 : 6 : 1),
852
+ (4 : 1 : 1), (5 : 0 : 1), (6 : 5 : 1), (6 : 2 : 1)]
853
+
854
+ ::
855
+
856
+ sage: x = polygen(GF(121, 'a'))
857
+ sage: C = HyperellipticCurve(x^5 + x - 1, x^2 + 2)
858
+ sage: len(C.points())
859
+ 122
860
+
861
+ Conics are allowed (the issue reported at :issue:`11800`
862
+ has been resolved)::
863
+
864
+ sage: R.<x> = GF(7)[]
865
+ sage: H = HyperellipticCurve(3*x^2 + 5*x + 1)
866
+ sage: H.points()
867
+ [(0 : 6 : 1), (0 : 1 : 1), (1 : 4 : 1), (1 : 3 : 1), (2 : 4 : 1),
868
+ (2 : 3 : 1), (3 : 6 : 1), (3 : 1 : 1)]
869
+
870
+ The method currently lists points on the plane projective model, that
871
+ is the closure in `\mathbb{P}^2` of the curve defined by `y^2+hy=f`.
872
+ This means that one point `(0:1:0)` at infinity is returned if the
873
+ degree of the curve is at least 4 and `\deg(f)>\deg(h)+1`. This point
874
+ is a singular point of the plane model. Later implementations may
875
+ consider a smooth model instead since that would be a more relevant
876
+ object. Then, for a curve whose only singularity is at `(0:1:0)`, the
877
+ point at infinity would be replaced by a number of rational points of
878
+ the smooth model. We illustrate this with an example of a genus 2
879
+ hyperelliptic curve::
880
+
881
+ sage: R.<x>=GF(11)[]
882
+ sage: H = HyperellipticCurve(x*(x+1)*(x+2)*(x+3)*(x+4)*(x+5))
883
+ sage: H.points()
884
+ [(0 : 1 : 0), (0 : 0 : 1), (1 : 7 : 1), (1 : 4 : 1), (5 : 7 : 1), (5 : 4 : 1),
885
+ (6 : 0 : 1), (7 : 0 : 1), (8 : 0 : 1), (9 : 0 : 1), (10 : 0 : 1)]
886
+
887
+ The plane model of the genus 2 hyperelliptic curve in the above example
888
+ is the curve in `\mathbb{P}^2` defined by `y^2z^4=g(x,z)` where
889
+ `g(x,z)=x(x+z)(x+2z)(x+3z)(x+4z)(x+5z).` This model has one point at
890
+ infinity `(0:1:0)` which is also the only singular point of the plane
891
+ model. In contrast, the hyperelliptic curve is smooth and imbeds via
892
+ the equation `y^2=g(x,z)` into weighted projected space
893
+ `\mathbb{P}(1,3,1)`. The latter model has two points at infinity:
894
+ `(1:1:0)` and `(1:-1:0)`.
895
+ """
896
+ from sage.rings.finite_rings.finite_field_constructor import zech_log_bound
897
+ try:
898
+ return self.__points
899
+ except AttributeError:
900
+ pass
901
+
902
+ if self.base_ring().is_prime_field():
903
+ self.__points = self._points_cache_sqrt()
904
+ else:
905
+ if self.base_ring().order() < zech_log_bound:
906
+ self.__points = self._points_fast_sqrt() # this is fast using Zech logarithms
907
+ else:
908
+ self.__points = self._points_cache_sqrt()
909
+
910
+ return self.__points
911
+
912
+ def count_points_matrix_traces(self, n=1, M=None, N=None):
913
+ r"""
914
+ Count the number of points on the curve over the first `n` extensions
915
+ of the base field by computing traces of powers of the frobenius
916
+ matrix.
917
+ This requires less `p`-adic precision than computing the charpoly
918
+ of the matrix when `n < g` where `g` is the genus of the curve.
919
+
920
+ EXAMPLES::
921
+
922
+ sage: K = GF(49999)
923
+ sage: R.<t> = PolynomialRing(K)
924
+ sage: H = HyperellipticCurve(t^19 + t + 1)
925
+ sage: H.count_points_matrix_traces(3)
926
+ [49491, 2500024375, 124992509154249]
927
+
928
+ TESTS:
929
+
930
+ Check that :issue:`18831` is fixed::
931
+
932
+ sage: R.<t> = PolynomialRing(GF(11))
933
+ sage: H = HyperellipticCurve(t^5 - t + 1)
934
+ sage: H.count_points_matrix_traces()
935
+ Traceback (most recent call last):
936
+ ...
937
+ ValueError: In the current implementation, p must be greater than (2g+1)(2N-1) = 15
938
+ """
939
+ if N is None:
940
+ N = self._frobenius_coefficient_bound_traces(n=n)
941
+
942
+ if M is None:
943
+ M = self.frobenius_matrix(N=N)
944
+
945
+ K = self.base_ring()
946
+ p = K.characteristic()
947
+ q = K.cardinality()
948
+ ppow = p**N
949
+
950
+ t = []
951
+ Mpow = 1
952
+ for i in range(n):
953
+ Mpow *= M
954
+ t.append(Mpow.trace())
955
+
956
+ t = [x.lift() for x in t]
957
+ t = [x if 2*x < ppow else x - ppow for x in t]
958
+
959
+ return [q**(i+1) + 1 - t[i] for i in range(n)]
960
+
961
+ def count_points_frobenius_polynomial(self, n=1, f=None):
962
+ r"""
963
+ Count the number of points on the curve over the first `n` extensions
964
+ of the base field by computing the frobenius polynomial.
965
+
966
+ EXAMPLES::
967
+
968
+ sage: K = GF(49999)
969
+ sage: R.<t> = PolynomialRing(K)
970
+ sage: H = HyperellipticCurve(t^19 + t + 1)
971
+
972
+ The following computation takes a long time as the complete
973
+ characteristic polynomial of the frobenius is computed::
974
+
975
+ sage: H.count_points_frobenius_polynomial(3) # long time, 20s on a Corei7 (when computed before the following test of course)
976
+ [49491, 2500024375, 124992509154249]
977
+
978
+ As the polynomial is cached, further computations of number of points
979
+ are really fast::
980
+
981
+ sage: H.count_points_frobenius_polynomial(19) # long time, because of the previous test
982
+ [49491,
983
+ 2500024375,
984
+ 124992509154249,
985
+ 6249500007135192947,
986
+ 312468751250758776051811,
987
+ 15623125093747382662737313867,
988
+ 781140631562281338861289572576257,
989
+ 39056250437482500417107992413002794587,
990
+ 1952773465623687539373429411200893147181079,
991
+ 97636720507718753281169963459063147221761552935,
992
+ 4881738388665429945305281187129778704058864736771824,
993
+ 244082037694882831835318764490138139735446240036293092851,
994
+ 12203857802706446708934102903106811520015567632046432103159713,
995
+ 610180686277519628999996211052002771035439565767719719151141201339,
996
+ 30508424133189703930370810556389262704405225546438978173388673620145499,
997
+ 1525390698235352006814610157008906752699329454643826047826098161898351623931,
998
+ 76268009521069364988723693240288328729528917832735078791261015331201838856825193,
999
+ 3813324208043947180071195938321176148147244128062172555558715783649006587868272993991,
1000
+ 190662397077989315056379725720120486231213267083935859751911720230901597698389839098903847]
1001
+ """
1002
+ if f is None:
1003
+ f = self.frobenius_polynomial()
1004
+
1005
+ q = self.base_ring().cardinality()
1006
+ S = PowerSeriesRing(QQ, default_prec=n+1, names='t')
1007
+ frev = f.reverse()
1008
+ # the coefficients() method of power series only returns
1009
+ # nonzero coefficients so let us use the list() method but
1010
+ # this does not work for zero which gives the empty list
1011
+ flog = S(frev).log()
1012
+ return [q**(i+1) + 1 + ZZ((i+1)*flog[i+1]) for i in range(n)]
1013
+
1014
+ def count_points_exhaustive(self, n=1, naive=False):
1015
+ r"""
1016
+ Count the number of points on the curve over the first `n` extensions
1017
+ of the base field by exhaustive search if `n` if smaller than `g`,
1018
+ the genus of the curve, and by computing the frobenius polynomial
1019
+ after performing exhaustive search on the first `g` extensions if
1020
+ `n > g` (unless ``naive == True``).
1021
+
1022
+ EXAMPLES::
1023
+
1024
+ sage: K = GF(5)
1025
+ sage: R.<t> = PolynomialRing(K)
1026
+ sage: H = HyperellipticCurve(t^9 + t^3 + 1)
1027
+ sage: H.count_points_exhaustive(n=5)
1028
+ [9, 27, 108, 675, 3069]
1029
+
1030
+ When `n > g`, the frobenius polynomial is computed from the numbers
1031
+ of points of the curve over the first `g` extension, so that computing
1032
+ the number of points on extensions of degree `n > g` is not much more
1033
+ expensive than for `n == g`::
1034
+
1035
+ sage: H.count_points_exhaustive(n=15)
1036
+ [9,
1037
+ 27,
1038
+ 108,
1039
+ 675,
1040
+ 3069,
1041
+ 16302,
1042
+ 78633,
1043
+ 389475,
1044
+ 1954044,
1045
+ 9768627,
1046
+ 48814533,
1047
+ 244072650,
1048
+ 1220693769,
1049
+ 6103414827,
1050
+ 30517927308]
1051
+
1052
+ This behavior can be disabled by passing ``naive=True``::
1053
+
1054
+ sage: H.count_points_exhaustive(n=6, naive=True) # long time, 7s on a Corei7
1055
+ [9, 27, 108, 675, 3069, 16302]
1056
+ """
1057
+ g = self.genus()
1058
+ a = [self.cardinality_exhaustive(extension_degree=i)
1059
+ for i in range(1, min(n, g) + 1)]
1060
+
1061
+ if n <= g:
1062
+ return a
1063
+
1064
+ if naive:
1065
+ a.extend(self.cardinality_exhaustive(extension_degree=i)
1066
+ for i in range(g + 1, n + 1))
1067
+
1068
+ # let's not be too naive and compute the frobenius polynomial
1069
+ f = self._frobenius_polynomial_cardinalities(a=a)
1070
+ return self.count_points_frobenius_polynomial(n=n, f=f)
1071
+
1072
+ def count_points_hypellfrob(self, n=1, N=None, algorithm=None):
1073
+ r"""
1074
+ Count the number of points on the curve over the first `n` extensions
1075
+ of the base field using the ``hypellfrob`` program.
1076
+
1077
+ This only supports prime fields of large enough characteristic.
1078
+
1079
+ EXAMPLES::
1080
+
1081
+ sage: K = GF(49999)
1082
+ sage: R.<t> = PolynomialRing(K)
1083
+ sage: H = HyperellipticCurve(t^21 + 3*t^5 + 5)
1084
+ sage: H.count_points_hypellfrob()
1085
+ [49804]
1086
+ sage: H.count_points_hypellfrob(2)
1087
+ [49804, 2499799038]
1088
+
1089
+ sage: K = GF(2**7-1)
1090
+ sage: R.<t> = PolynomialRing(K)
1091
+ sage: H = HyperellipticCurve(t^11 + 3*t^5 + 5)
1092
+ sage: H.count_points_hypellfrob()
1093
+ [127]
1094
+ sage: H.count_points_hypellfrob(n=5)
1095
+ [127, 16335, 2045701, 260134299, 33038098487]
1096
+
1097
+ sage: K = GF(2**7-1)
1098
+ sage: R.<t> = PolynomialRing(K)
1099
+ sage: H = HyperellipticCurve(t^13 + 3*t^5 + 5)
1100
+ sage: H.count_points(n=6)
1101
+ [112, 16360, 2045356, 260199160, 33038302802, 4195868633548]
1102
+
1103
+ The base field should be prime::
1104
+
1105
+ sage: K.<z> = GF(19**10)
1106
+ sage: R.<t> = PolynomialRing(K)
1107
+ sage: H = HyperellipticCurve(t^9 + (z+1)*t^5 + 1)
1108
+ sage: H.count_points_hypellfrob()
1109
+ Traceback (most recent call last):
1110
+ ...
1111
+ ValueError: hypellfrob does not support non-prime fields
1112
+
1113
+ and the characteristic should be large enough::
1114
+
1115
+ sage: K = GF(7)
1116
+ sage: R.<t> = PolynomialRing(K)
1117
+ sage: H = HyperellipticCurve(t^9 + t^3 + 1)
1118
+ sage: H.count_points_hypellfrob()
1119
+ Traceback (most recent call last):
1120
+ ...
1121
+ ValueError: p=7 should be greater than (2*g+1)(2*N-1)=27
1122
+ """
1123
+ K = self.base_ring()
1124
+ e = K.degree()
1125
+
1126
+ if e != 1:
1127
+ raise ValueError("hypellfrob does not support non-prime fields")
1128
+
1129
+ # K is a prime field
1130
+ p = K.cardinality()
1131
+ g = self.genus()
1132
+
1133
+ if algorithm is None:
1134
+ if n < g:
1135
+ algorithm = 'traces'
1136
+ else:
1137
+ algorithm = 'charpoly'
1138
+
1139
+ if N is None:
1140
+ if algorithm == 'traces':
1141
+ N = self._frobenius_coefficient_bound_traces(n)
1142
+ elif algorithm == 'charpoly':
1143
+ N = self._frobenius_coefficient_bound_charpoly()
1144
+ else:
1145
+ raise ValueError("Unknown algorithm")
1146
+
1147
+ if p <= (2*g+1)*(2*N-1):
1148
+ raise ValueError("p=%d should be greater than (2*g+1)(2*N-1)=%d" % (p,(2*g+1)*(2*N-1)))
1149
+
1150
+ if algorithm == 'traces':
1151
+ M = self.frobenius_matrix(N=N, algorithm='hypellfrob')
1152
+ return self.count_points_matrix_traces(n=n,M=M,N=N)
1153
+ elif algorithm == 'charpoly':
1154
+ f = self._frobenius_polynomial_matrix(algorithm='hypellfrob')
1155
+ return self.count_points_frobenius_polynomial(n=n,f=f)
1156
+ else:
1157
+ raise ValueError("Unknown algorithm")
1158
+
1159
+ def count_points(self, n=1):
1160
+ r"""
1161
+ Count points over finite fields.
1162
+
1163
+ INPUT:
1164
+
1165
+ - ``n`` -- integer
1166
+
1167
+ OUTPUT:
1168
+
1169
+ An integer. The number of points over `\GF{q}, \ldots,
1170
+ \GF{q^n}` on a hyperelliptic curve over a finite field `\GF{q}`.
1171
+
1172
+ .. WARNING::
1173
+
1174
+ This is currently using exhaustive search for hyperelliptic curves
1175
+ over non-prime fields, which can be awfully slow.
1176
+
1177
+ EXAMPLES::
1178
+
1179
+ sage: P.<x> = PolynomialRing(GF(3))
1180
+ sage: C = HyperellipticCurve(x^3+x^2+1)
1181
+ sage: C.count_points(4)
1182
+ [6, 12, 18, 96]
1183
+ sage: C.base_extend(GF(9,'a')).count_points(2)
1184
+ [12, 96]
1185
+
1186
+ sage: K = GF(2**31-1)
1187
+ sage: R.<t> = PolynomialRing(K)
1188
+ sage: H = HyperellipticCurve(t^5 + 3*t + 5)
1189
+ sage: H.count_points() # long time, 2.4 sec on a Corei7
1190
+ [2147464821]
1191
+ sage: H.count_points(n=2) # long time, 30s on a Corei7
1192
+ [2147464821, 4611686018988310237]
1193
+
1194
+ sage: K = GF(2**7-1)
1195
+ sage: R.<t> = PolynomialRing(K)
1196
+ sage: H = HyperellipticCurve(t^13 + 3*t^5 + 5)
1197
+ sage: H.count_points(n=6)
1198
+ [112, 16360, 2045356, 260199160, 33038302802, 4195868633548]
1199
+
1200
+ sage: P.<x> = PolynomialRing(GF(3))
1201
+ sage: H = HyperellipticCurve(x^3+x^2+1)
1202
+ sage: C1 = H.count_points(4); C1
1203
+ [6, 12, 18, 96]
1204
+ sage: C2 = sage.schemes.generic.scheme.Scheme.count_points(H,4); C2 # long time, 2s on a Corei7
1205
+ [6, 12, 18, 96]
1206
+ sage: C1 == C2 # long time, because we need C2 to be defined
1207
+ True
1208
+
1209
+ sage: P.<x> = PolynomialRing(GF(9,'a'))
1210
+ sage: H = HyperellipticCurve(x^5+x^2+1)
1211
+ sage: H.count_points(5)
1212
+ [18, 78, 738, 6366, 60018]
1213
+
1214
+ sage: F.<a> = GF(4); P.<x> = F[]
1215
+ sage: H = HyperellipticCurve(x^5+a*x^2+1, x+a+1)
1216
+ sage: H.count_points(6)
1217
+ [2, 24, 74, 256, 1082, 4272]
1218
+
1219
+ This example shows that :issue:`20391` is resolved::
1220
+
1221
+ sage: x = polygen(GF(4099))
1222
+ sage: H = HyperellipticCurve(x^6 + x + 1)
1223
+ sage: H.count_points(1)
1224
+ [4106]
1225
+ """
1226
+ K = self.base_ring()
1227
+ q = K.cardinality()
1228
+ e = K.degree()
1229
+ g = self.genus()
1230
+ f, h = self.hyperelliptic_polynomials()
1231
+
1232
+ if e == 1 and h == 0 and f.degree() % 2 == 1:
1233
+ N1 = self._frobenius_coefficient_bound_traces(n)
1234
+ N2 = self._frobenius_coefficient_bound_charpoly()
1235
+ if n < g and q > (2*g+1)*(2*N1-1):
1236
+ return self.count_points_hypellfrob(n, N=N1, algorithm='traces')
1237
+ elif q > (2*g+1)*(2*N2-1):
1238
+ return self.count_points_hypellfrob(n, N=N2, algorithm='charpoly')
1239
+
1240
+ # No smart method available
1241
+ return self.count_points_exhaustive(n)
1242
+
1243
+ def cardinality_exhaustive(self, extension_degree=1, algorithm=None):
1244
+ r"""
1245
+ Count points on a single extension of the base field
1246
+ by enumerating over x and solving the resulting quadratic
1247
+ equation for y.
1248
+
1249
+ EXAMPLES::
1250
+
1251
+ sage: K.<a> = GF(9, 'a')
1252
+ sage: x = polygen(K)
1253
+ sage: C = HyperellipticCurve(x^7 - 1, x^2 + a)
1254
+ sage: C.cardinality_exhaustive()
1255
+ 7
1256
+
1257
+ sage: K = GF(next_prime(1<<10))
1258
+ sage: R.<t> = PolynomialRing(K)
1259
+ sage: H = HyperellipticCurve(t^7 + 3*t^5 + 5)
1260
+ sage: H.cardinality_exhaustive()
1261
+ 1025
1262
+
1263
+ sage: P.<x> = PolynomialRing(GF(9,'a'))
1264
+ sage: H = HyperellipticCurve(x^5+x^2+1)
1265
+ sage: H.count_points(5)
1266
+ [18, 78, 738, 6366, 60018]
1267
+
1268
+ sage: F.<a> = GF(4); P.<x> = F[]
1269
+ sage: H = HyperellipticCurve(x^5+a*x^2+1, x+a+1)
1270
+ sage: H.count_points(6)
1271
+ [2, 24, 74, 256, 1082, 4272]
1272
+
1273
+ TESTS:
1274
+
1275
+ Check for :issue:`19122`::
1276
+
1277
+ sage: x = polygen(GF(19), 'x')
1278
+ sage: f = 15*x^4 + 7*x^3 + 3*x^2 + 7*x + 18
1279
+ sage: HyperellipticCurve(f).cardinality_exhaustive(1)
1280
+ 19
1281
+
1282
+ Points at infinity on general curves of genus 1 are counted
1283
+ correctly (see :issue:`21195`)::
1284
+
1285
+ sage: S.<z> = PolynomialRing(ZZ)
1286
+ sage: C = HyperellipticCurve(-z^2 + z, z^2)
1287
+ sage: C.base_extend(GF(2)).count_points_exhaustive()
1288
+ [5]
1289
+ sage: C.base_extend(GF(3)).count_points_exhaustive()
1290
+ [5]
1291
+ """
1292
+ K = self.base_ring()
1293
+ g = self.genus()
1294
+ n = extension_degree
1295
+
1296
+ if g == 0:
1297
+ # here is the projective line
1298
+ return K.cardinality() ** n + 1
1299
+
1300
+ f, h = self.hyperelliptic_polynomials()
1301
+ a = 0
1302
+
1303
+ if n == 1:
1304
+ # the base field
1305
+ L = K
1306
+ fext = f
1307
+ hext = h
1308
+ else:
1309
+ # extension of the base field
1310
+ from sage.categories.homset import Hom
1311
+ L = GF(K.cardinality()**n, names='z')
1312
+ P = L['t']
1313
+ emb = Hom(K, L)[0]
1314
+ fext = P([emb(c) for c in f])
1315
+ hext = P([emb(c) for c in h])
1316
+
1317
+ # We solve equations of the form y^2 + r*y - s == 0.
1318
+ # For the points at infinity (on the smooth model),
1319
+ # solve y^2 + h[g+1]*y == f[2*g+2].
1320
+ # For the affine points with given x-coordinate,
1321
+ # solve y^2 + h(x)*y == f(x).
1322
+
1323
+ if K.characteristic() == 2:
1324
+ # points at infinity
1325
+ r = h[g+1]
1326
+ if not r:
1327
+ a += 1
1328
+ elif n % 2 == 0 or (f[2*g+2]/r**2).trace() == 0:
1329
+ # Artin-Schreier equation t^2 + t = s/r^2
1330
+ # always has a solution in extensions of even degree
1331
+ a += 2
1332
+ # affine points
1333
+ for x in L:
1334
+ r = hext(x)
1335
+ if not r:
1336
+ a += 1
1337
+ elif (fext(x)/r**2).trace() == 0:
1338
+ a += 2
1339
+ else:
1340
+ # points at infinity
1341
+ d = h[g+1]**2 + 4*f[2*g+2]
1342
+ if not d:
1343
+ a += 1
1344
+ elif n % 2 == 0 or d.is_square():
1345
+ a += 2
1346
+ # affine points
1347
+ for x in L:
1348
+ d = hext(x)**2 + 4*fext(x)
1349
+ if not d:
1350
+ a += 1
1351
+ elif d.is_square():
1352
+ a += 2
1353
+
1354
+ return a
1355
+
1356
+ def cardinality_hypellfrob(self, extension_degree=1, algorithm=None):
1357
+ r"""
1358
+ Count points on a single extension of the base field
1359
+ using the ``hypellfrob`` program.
1360
+
1361
+ EXAMPLES::
1362
+
1363
+ sage: K = GF(next_prime(1<<10))
1364
+ sage: R.<t> = PolynomialRing(K)
1365
+ sage: H = HyperellipticCurve(t^7 + 3*t^5 + 5)
1366
+ sage: H.cardinality_hypellfrob()
1367
+ 1025
1368
+
1369
+ sage: K = GF(49999)
1370
+ sage: R.<t> = PolynomialRing(K)
1371
+ sage: H = HyperellipticCurve(t^7 + 3*t^5 + 5)
1372
+ sage: H.cardinality_hypellfrob()
1373
+ 50162
1374
+ sage: H.cardinality_hypellfrob(3)
1375
+ 124992471088310
1376
+ """
1377
+ # the following actually computes the cardinality for several extensions
1378
+ # but the overhead is negligible
1379
+ return self.count_points_hypellfrob(n=extension_degree, algorithm=algorithm)[-1]
1380
+
1381
+ @cached_method
1382
+ def cardinality(self, extension_degree=1):
1383
+ r"""
1384
+ Count points on a single extension of the base field.
1385
+
1386
+ EXAMPLES::
1387
+
1388
+ sage: K = GF(101)
1389
+ sage: R.<t> = PolynomialRing(K)
1390
+ sage: H = HyperellipticCurve(t^9 + 3*t^5 + 5)
1391
+ sage: H.cardinality()
1392
+ 106
1393
+ sage: H.cardinality(15)
1394
+ 1160968955369992567076405831000
1395
+ sage: H.cardinality(100)
1396
+ 270481382942152609326719471080753083367793838278100277689020104911710151430673927943945601434674459120495370826289654897190781715493352266982697064575800553229661690000887425442240414673923744999504000
1397
+
1398
+ sage: K = GF(37)
1399
+ sage: R.<t> = PolynomialRing(K)
1400
+ sage: H = HyperellipticCurve(t^9 + 3*t^5 + 5)
1401
+ sage: H.cardinality()
1402
+ 40
1403
+ sage: H.cardinality(2)
1404
+ 1408
1405
+ sage: H.cardinality(3)
1406
+ 50116
1407
+
1408
+ The following example shows that :issue:`20391` has been resolved::
1409
+
1410
+ sage: F=GF(23)
1411
+ sage: x=polygen(F)
1412
+ sage: C=HyperellipticCurve(x^8+1)
1413
+ sage: C.cardinality()
1414
+ 24
1415
+ """
1416
+ K = self.base_ring()
1417
+ q = K.cardinality()
1418
+ e = K.degree()
1419
+ g = self.genus()
1420
+ f, h = self.hyperelliptic_polynomials()
1421
+ n = extension_degree
1422
+
1423
+ # We may:
1424
+ # - check for actual field of definition of the curve (up to isomorphism)
1425
+ if e == 1 and h == 0 and f.degree() % 2 == 1:
1426
+ N1 = self._frobenius_coefficient_bound_traces(n)
1427
+ N2 = self._frobenius_coefficient_bound_charpoly()
1428
+ if n < g and q > (2*g+1)*(2*N1-1):
1429
+ return self.cardinality_hypellfrob(n, algorithm='traces')
1430
+ elif q > (2*g+1)*(2*N2-1):
1431
+ return self.cardinality_hypellfrob(n, algorithm='charpoly')
1432
+
1433
+ # No smart method available
1434
+ return self.cardinality_exhaustive(n)
1435
+
1436
+ def zeta_function(self):
1437
+ r"""
1438
+ Compute the zeta function of the hyperelliptic curve.
1439
+
1440
+ EXAMPLES::
1441
+
1442
+ sage: F = GF(2); R.<t> = F[]
1443
+ sage: H = HyperellipticCurve(t^9 + t, t^4)
1444
+ sage: H.zeta_function()
1445
+ (16*x^8 + 8*x^7 + 8*x^6 + 4*x^5 + 6*x^4 + 2*x^3 + 2*x^2 + x + 1)/(2*x^2 - 3*x + 1)
1446
+
1447
+ sage: F.<a> = GF(4); R.<t> = F[]
1448
+ sage: H = HyperellipticCurve(t^5 + t^3 + t^2 + t + 1, t^2 + t + 1)
1449
+ sage: H.zeta_function()
1450
+ (16*x^4 + 8*x^3 + x^2 + 2*x + 1)/(4*x^2 - 5*x + 1)
1451
+
1452
+ sage: F.<a> = GF(9); R.<t> = F[]
1453
+ sage: H = HyperellipticCurve(t^5 + a*t)
1454
+ sage: H.zeta_function()
1455
+ (81*x^4 + 72*x^3 + 32*x^2 + 8*x + 1)/(9*x^2 - 10*x + 1)
1456
+
1457
+ sage: R.<t> = PolynomialRing(GF(37))
1458
+ sage: H = HyperellipticCurve(t^5 + t + 2)
1459
+ sage: H.zeta_function()
1460
+ (1369*x^4 + 37*x^3 - 52*x^2 + x + 1)/(37*x^2 - 38*x + 1)
1461
+
1462
+ A quadratic twist::
1463
+
1464
+ sage: R.<t> = PolynomialRing(GF(37))
1465
+ sage: H = HyperellipticCurve(2*t^5 + 2*t + 4)
1466
+ sage: H.zeta_function()
1467
+ (1369*x^4 - 37*x^3 - 52*x^2 - x + 1)/(37*x^2 - 38*x + 1)
1468
+ """
1469
+ q = self.base_ring().cardinality()
1470
+ P = self.frobenius_polynomial()
1471
+ x = P.parent().gen(0)
1472
+ return P.reverse() / ((1-x)*(1-q*x))
1473
+
1474
+ # This where Cartier Matrix is actually computed. This is either called by
1475
+ # E.Cartier_matrix, E.a_number, or E.Hasse_Witt.
1476
+ @cached_method
1477
+ def _Cartier_matrix_cached(self):
1478
+ r"""
1479
+ INPUT:
1480
+
1481
+ - ``self`` -- Hyperelliptic Curve of the form `y^2 = f(x)` over a
1482
+ finite field, `\GF{q}`
1483
+
1484
+ OUTPUT:
1485
+
1486
+ - 'matrix(Fq,M)' The matrix `M = (c_(pi-j)), f(x)^((p-1)/2) = \sum c_i x^i`
1487
+ - 'Coeff' List of Coeffs of F, this is needed for Hasse-Witt function.
1488
+ - 'g' genus of the curve self, this is needed by a-number.
1489
+ - 'Fq' is the base field of self, and it is needed for Hasse-Witt
1490
+ - 'p' is the char(Fq), this is needed for Hasse-Witt.
1491
+ - 'E' The initial elliptic curve to check some caching conditions.
1492
+
1493
+ EXAMPLES::
1494
+
1495
+ sage: K.<x>=GF(9,'x')[]
1496
+ sage: C=HyperellipticCurve(x^7-1,0)
1497
+ sage: C._Cartier_matrix_cached()
1498
+ (
1499
+ [0 0 2]
1500
+ [0 0 0]
1501
+ [0 1 0], [2, 0, 0, 0, 0, 0, 0, 1, 0], 3, Finite Field in x of size 3^2, 3, Hyperelliptic Curve over Finite Field in x of size 3^2 defined by y^2 = x^7 + 2
1502
+ )
1503
+ sage: K.<x>=GF(49,'x')[]
1504
+ sage: C=HyperellipticCurve(x^5+1,0)
1505
+ sage: C._Cartier_matrix_cached()
1506
+ (
1507
+ [0 3]
1508
+ [0 0], [1, 0, 0, 0, 0, 3, 0, 0, 0, 0, 3, 0, 0, 0, 0, 1], 2, Finite Field in x of size 7^2, 7, Hyperelliptic Curve over Finite Field in x of size 7^2 defined by y^2 = x^5 + 1
1509
+ )
1510
+
1511
+ sage: P.<x>=GF(9,'a')[]
1512
+ sage: C=HyperellipticCurve(x^29+1,0)
1513
+ sage: C._Cartier_matrix_cached()
1514
+ (
1515
+ [0 0 1 0 0 0 0 0 0 0 0 0 0 0]
1516
+ [0 0 0 0 0 1 0 0 0 0 0 0 0 0]
1517
+ [0 0 0 0 0 0 0 0 1 0 0 0 0 0]
1518
+ [0 0 0 0 0 0 0 0 0 0 0 1 0 0]
1519
+ [0 0 0 0 0 0 0 0 0 0 0 0 0 0]
1520
+ [0 0 0 0 0 0 0 0 0 0 0 0 0 0]
1521
+ [0 0 0 0 0 0 0 0 0 0 0 0 0 0]
1522
+ [0 0 0 0 0 0 0 0 0 0 0 0 0 0]
1523
+ [0 0 0 0 0 0 0 0 0 0 0 0 0 0]
1524
+ [1 0 0 0 0 0 0 0 0 0 0 0 0 0]
1525
+ [0 0 0 1 0 0 0 0 0 0 0 0 0 0]
1526
+ [0 0 0 0 0 0 1 0 0 0 0 0 0 0]
1527
+ [0 0 0 0 0 0 0 0 0 1 0 0 0 0]
1528
+ [0 0 0 0 0 0 0 0 0 0 0 0 1 0], [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], 14, Finite Field in a of size 3^2, 3, Hyperelliptic Curve over Finite Field in a of size 3^2 defined by y^2 = x^29 + 1
1529
+ )
1530
+
1531
+ TESTS::
1532
+
1533
+ sage: K.<x>=GF(2,'x')[]
1534
+ sage: C=HyperellipticCurve(x^7-1,x)
1535
+ sage: C._Cartier_matrix_cached()
1536
+ Traceback (most recent call last):
1537
+ ...
1538
+ ValueError: p must be odd
1539
+
1540
+ sage: K.<x>=GF(5,'x')[]
1541
+ sage: C=HyperellipticCurve(x^7-1,4)
1542
+ sage: C._Cartier_matrix_cached()
1543
+ Traceback (most recent call last):
1544
+ ...
1545
+ ValueError: E must be of the form y^2 = f(x)
1546
+
1547
+ sage: K.<x>=GF(5,'x')[]
1548
+ sage: C=HyperellipticCurve(x^8-1,0)
1549
+ sage: C._Cartier_matrix_cached()
1550
+ Traceback (most recent call last):
1551
+ ...
1552
+ ValueError: In this implementation the degree of f must be odd
1553
+
1554
+ sage: K.<x>=GF(5,'x')[]
1555
+ sage: C=HyperellipticCurve(x^5+1,0,check_squarefree=False)
1556
+ sage: C._Cartier_matrix_cached()
1557
+ Traceback (most recent call last):
1558
+ ...
1559
+ ValueError: curve is not smooth
1560
+ """
1561
+ # Compute the finite field and prime p.
1562
+ Fq = self.base_ring()
1563
+ p = Fq.characteristic()
1564
+ #checks
1565
+
1566
+ if p == 2:
1567
+ raise ValueError("p must be odd")
1568
+
1569
+ g = self.genus()
1570
+
1571
+ #retrieve the function f(x) ,where y^2=f(x)
1572
+ f,h = self.hyperelliptic_polynomials()
1573
+ #This implementation only deals with h=0
1574
+ if h != 0:
1575
+ raise ValueError("E must be of the form y^2 = f(x)")
1576
+
1577
+ d = f.degree()
1578
+ #this implementation is for odd degree only, even degree will be handled later.
1579
+ if d % 2 == 0:
1580
+ raise ValueError("In this implementation the degree of f must be odd")
1581
+ #Compute resultant to make sure no repeated roots
1582
+ df = f.derivative()
1583
+ R = df.resultant(f)
1584
+ if R == 0:
1585
+ raise ValueError("curve is not smooth")
1586
+
1587
+ #computing F, since the entries of the matrix are c_i where F= \sum c_i x^i
1588
+
1589
+ F = f**((p-1)/2)
1590
+
1591
+ #coefficients returns a_0, ... , a_n where f(x) = a_n x^n + ... + a_0
1592
+
1593
+ Coeff = F.list()
1594
+
1595
+ #inserting zeros when necessary-- that is, when deg(F) < p*g-1, (simplified if p <2g-1)
1596
+ #which is the highest powered coefficient needed for our matrix
1597
+ #So we don't have enough coefficients we add extra zeros to have the same poly,
1598
+ #but enough coeff.
1599
+
1600
+ zeros = [0 for i in range(p*g-len(Coeff))]
1601
+ Coeff = Coeff + zeros
1602
+
1603
+ # compute each row of matrix as list and then M=list of lists(rows)
1604
+
1605
+ M = []
1606
+ for j in range(1,g+1):
1607
+ H = [Coeff[i] for i in range((p*j-1), (p*j-g-1),-1)]
1608
+ M.append(H)
1609
+ return matrix(Fq,M), Coeff, g, Fq,p, self
1610
+
1611
+ # This is what is called from command line
1612
+ def Cartier_matrix(self):
1613
+ r"""
1614
+ INPUT:
1615
+
1616
+ - ``self`` -- Hyperelliptic Curve of the form `y^2 = f(x)` over a
1617
+ finite field, `\GF{q}`
1618
+
1619
+ OUTPUT:
1620
+
1621
+ The matrix `M = (c_{pi-j})`, where `c_i` are the coefficients of
1622
+ `f(x)^{(p-1)/2} = \sum c_i x^i`.
1623
+
1624
+ REFERENCES:
1625
+
1626
+ N. Yui. On the Jacobian varieties of hyperelliptic curves over fields of characteristic `p > 2`.
1627
+
1628
+ EXAMPLES::
1629
+
1630
+ sage: K.<x> = GF(9,'x')[]
1631
+ sage: C = HyperellipticCurve(x^7 - 1, 0)
1632
+ sage: C.Cartier_matrix()
1633
+ [0 0 2]
1634
+ [0 0 0]
1635
+ [0 1 0]
1636
+
1637
+ sage: K.<x> = GF(49, 'x')[]
1638
+ sage: C = HyperellipticCurve(x^5 + 1, 0)
1639
+ sage: C.Cartier_matrix()
1640
+ [0 3]
1641
+ [0 0]
1642
+
1643
+ sage: P.<x> = GF(9, 'a')[]
1644
+ sage: E = HyperellipticCurve(x^29 + 1, 0)
1645
+ sage: E.Cartier_matrix()
1646
+ [0 0 1 0 0 0 0 0 0 0 0 0 0 0]
1647
+ [0 0 0 0 0 1 0 0 0 0 0 0 0 0]
1648
+ [0 0 0 0 0 0 0 0 1 0 0 0 0 0]
1649
+ [0 0 0 0 0 0 0 0 0 0 0 1 0 0]
1650
+ [0 0 0 0 0 0 0 0 0 0 0 0 0 0]
1651
+ [0 0 0 0 0 0 0 0 0 0 0 0 0 0]
1652
+ [0 0 0 0 0 0 0 0 0 0 0 0 0 0]
1653
+ [0 0 0 0 0 0 0 0 0 0 0 0 0 0]
1654
+ [0 0 0 0 0 0 0 0 0 0 0 0 0 0]
1655
+ [1 0 0 0 0 0 0 0 0 0 0 0 0 0]
1656
+ [0 0 0 1 0 0 0 0 0 0 0 0 0 0]
1657
+ [0 0 0 0 0 0 1 0 0 0 0 0 0 0]
1658
+ [0 0 0 0 0 0 0 0 0 1 0 0 0 0]
1659
+ [0 0 0 0 0 0 0 0 0 0 0 0 1 0]
1660
+
1661
+ TESTS::
1662
+
1663
+ sage: K.<x>=GF(2,'x')[]
1664
+ sage: C=HyperellipticCurve(x^7-1,x)
1665
+ sage: C.Cartier_matrix()
1666
+ Traceback (most recent call last):
1667
+ ...
1668
+ ValueError: p must be odd
1669
+
1670
+ sage: K.<x>=GF(5,'x')[]
1671
+ sage: C=HyperellipticCurve(x^7-1,4)
1672
+ sage: C.Cartier_matrix()
1673
+ Traceback (most recent call last):
1674
+ ...
1675
+ ValueError: E must be of the form y^2 = f(x)
1676
+
1677
+ sage: K.<x>=GF(5,'x')[]
1678
+ sage: C=HyperellipticCurve(x^8-1,0)
1679
+ sage: C.Cartier_matrix()
1680
+ Traceback (most recent call last):
1681
+ ...
1682
+ ValueError: In this implementation the degree of f must be odd
1683
+
1684
+ sage: K.<x>=GF(5,'x')[]
1685
+ sage: C=HyperellipticCurve(x^5+1,0,check_squarefree=False)
1686
+ sage: C.Cartier_matrix()
1687
+ Traceback (most recent call last):
1688
+ ...
1689
+ ValueError: curve is not smooth
1690
+ """
1691
+ #checking first that Cartier matrix is not already cached. Since
1692
+ #it can be called by either Hasse_Witt or a_number.
1693
+ #This way it does not matter which function is called first
1694
+ #in the code.
1695
+ # Github Issue #11115: Why shall we waste time by studying
1696
+ # the cache manually? We only need to check whether the cached
1697
+ # data belong to self.
1698
+ M, Coeffs,g, Fq, p, E = self._Cartier_matrix_cached()
1699
+ if E != self:
1700
+ self._Cartier_matrix_cached.clear_cache()
1701
+ M, Coeffs,g, Fq, p, E = self._Cartier_matrix_cached()
1702
+ return M
1703
+
1704
+ @cached_method
1705
+ def _Hasse_Witt_cached(self):
1706
+ r"""
1707
+ This is where Hasse_Witt is actually computed.
1708
+
1709
+ This is either called by E.Hasse_Witt or E.p_rank.
1710
+
1711
+ INPUT:
1712
+
1713
+ - ``E`` -- hyperelliptic Curve of the form `y^2 = f(x)` over
1714
+ a finite field, `\GF{q}`
1715
+
1716
+ OUTPUT:
1717
+
1718
+ - ``N`` -- the matrix `N = M M^p \dots M^{p^{g-1}}` where
1719
+ `M = c_{pi-j}, f(x)^{(p-1)/2} = \sum c_i x^i`
1720
+
1721
+ - ``E`` -- the initial curve to check some caching conditions
1722
+
1723
+ EXAMPLES::
1724
+
1725
+ sage: K.<x> = GF(9,'x')[]
1726
+ sage: C = HyperellipticCurve(x^7-1,0)
1727
+ sage: C._Hasse_Witt_cached()
1728
+ (
1729
+ [0 0 0]
1730
+ [0 0 0]
1731
+ [0 0 0], Hyperelliptic Curve over Finite Field in x of size 3^2 defined by y^2 = x^7 + 2
1732
+ )
1733
+
1734
+ sage: K.<x> = GF(49,'x')[]
1735
+ sage: C = HyperellipticCurve(x^5+1,0)
1736
+ sage: C._Hasse_Witt_cached()
1737
+ (
1738
+ [0 0]
1739
+ [0 0], Hyperelliptic Curve over Finite Field in x of size 7^2 defined by y^2 = x^5 + 1
1740
+ )
1741
+
1742
+ sage: P.<x> = GF(9,'a')[]
1743
+ sage: C = HyperellipticCurve(x^29+1,0)
1744
+ sage: C._Hasse_Witt_cached()
1745
+ (
1746
+ [0 0 0 0 0 0 0 0 0 0 0 0 0 0]
1747
+ [0 0 0 0 0 0 0 0 0 0 0 0 0 0]
1748
+ [0 0 0 0 0 0 0 0 0 0 0 0 0 0]
1749
+ [0 0 0 0 0 0 0 0 0 0 0 0 0 0]
1750
+ [0 0 0 0 0 0 0 0 0 0 0 0 0 0]
1751
+ [0 0 0 0 0 0 0 0 0 0 0 0 0 0]
1752
+ [0 0 0 0 0 0 0 0 0 0 0 0 0 0]
1753
+ [0 0 0 0 0 0 0 0 0 0 0 0 0 0]
1754
+ [0 0 0 0 0 0 0 0 0 0 0 0 0 0]
1755
+ [0 0 0 0 0 0 0 0 0 0 0 0 0 0]
1756
+ [0 0 0 0 0 0 0 0 0 0 0 0 0 0]
1757
+ [0 0 0 0 0 0 0 0 0 0 0 0 0 0]
1758
+ [0 0 0 0 0 0 0 0 0 0 0 0 0 0]
1759
+ [0 0 0 0 0 0 0 0 0 0 0 0 0 0], Hyperelliptic Curve over Finite Field in a of size 3^2 defined by y^2 = x^29 + 1
1760
+ )
1761
+
1762
+ TESTS:
1763
+
1764
+ This shows that the bug at :issue:`23181` is fixed::
1765
+
1766
+ sage: K.<z> = PolynomialRing(GF(5))
1767
+ sage: L.<a> = GF(5).extension(z^3+3*z+3,'a')
1768
+ sage: H.<x> = L[]
1769
+ sage: E = HyperellipticCurve(x^5+x^4+a^92*x^3+a^18*x^2+a^56*x,0)
1770
+ sage: E.p_rank()
1771
+ 0
1772
+ """
1773
+ # If Cartier Matrix is already cached for this curve, use that or evaluate it to get M,
1774
+ #Coeffs, genus, Fq=base field of self, p=char(Fq). This is so we have one less matrix to
1775
+ #compute.
1776
+
1777
+ #We use caching here since Cartier matrix is needed to compute Hasse Witt. So if the Cartier
1778
+ #is already computed it is stored in list A. If it was not cached (i.e. A is empty), we simply
1779
+ #compute it. If it is cached then we need to make sure that we have the correct one. So check
1780
+ #which curve does the matrix correspond to. Since caching stores a lot of stuff, we only check
1781
+ #the last entry in A. If it does not match, clear A and compute Cartier.
1782
+ #
1783
+ #Since Github Issue #11115, there is a different cache for methods
1784
+ #that don't accept arguments. Anyway, the easiest is to call
1785
+ #the cached method and simply see whether the data belong to self.
1786
+ M, Coeffs, g, Fq, p, E = self._Cartier_matrix_cached()
1787
+ if E != self:
1788
+ self._Cartier_matrix_cached.clear_cache()
1789
+ M, Coeffs, g, Fq, p, E = self._Cartier_matrix_cached()
1790
+
1791
+ #This compute the action of p^kth Frobenius on list of coefficients
1792
+ def frob_mat(Coeffs, k):
1793
+ a = p ** k
1794
+ mat = []
1795
+ Coeffs_pow = [c ** a for c in Coeffs]
1796
+ for i in range(1, g + 1):
1797
+ H = [(Coeffs_pow[j]) for j in range((p*i-1), (p*i - g-1), -1)]
1798
+ mat.append(H)
1799
+ return matrix(Fq, mat)
1800
+
1801
+ #Computes all the different possible action of frobenius on matrix M and stores in list Mall
1802
+ Mall = [M] + [frob_mat(Coeffs, k) for k in range(1, g)]
1803
+ Mall = reversed(Mall)
1804
+ #initial N=I, so we can go through Mall and multiply all matrices with I and
1805
+ #get the Hasse-Witt matrix.
1806
+ N = identity_matrix(Fq, g)
1807
+ for l in Mall:
1808
+ N = N * l
1809
+ return N, E
1810
+
1811
+ # This is the function which is actually called by command line
1812
+ def Hasse_Witt(self):
1813
+ r"""
1814
+ INPUT:
1815
+
1816
+ - ``self`` -- Hyperelliptic Curve of the form `y^2 = f(x)` over a
1817
+ finite field, `\GF{q}`
1818
+
1819
+ OUTPUT:
1820
+
1821
+ The matrix `N = M M^p \dots M^{p^{g-1}}` where `M = c_{pi-j}`, and
1822
+ `f(x)^{(p-1)/2} = \sum c_i x^i`.
1823
+
1824
+ Reference-N. Yui. On the Jacobian varieties of hyperelliptic curves over fields of characteristic `p > 2`.
1825
+
1826
+ EXAMPLES::
1827
+
1828
+ sage: K.<x> = GF(9, 'x')[]
1829
+ sage: C = HyperellipticCurve(x^7 - 1, 0)
1830
+ sage: C.Hasse_Witt()
1831
+ [0 0 0]
1832
+ [0 0 0]
1833
+ [0 0 0]
1834
+
1835
+ sage: K.<x> = GF(49, 'x')[]
1836
+ sage: C = HyperellipticCurve(x^5 + 1, 0)
1837
+ sage: C.Hasse_Witt()
1838
+ [0 0]
1839
+ [0 0]
1840
+
1841
+ sage: P.<x> = GF(9, 'a')[]
1842
+ sage: E = HyperellipticCurve(x^29 + 1, 0)
1843
+ sage: E.Hasse_Witt()
1844
+ [0 0 0 0 0 0 0 0 0 0 0 0 0 0]
1845
+ [0 0 0 0 0 0 0 0 0 0 0 0 0 0]
1846
+ [0 0 0 0 0 0 0 0 0 0 0 0 0 0]
1847
+ [0 0 0 0 0 0 0 0 0 0 0 0 0 0]
1848
+ [0 0 0 0 0 0 0 0 0 0 0 0 0 0]
1849
+ [0 0 0 0 0 0 0 0 0 0 0 0 0 0]
1850
+ [0 0 0 0 0 0 0 0 0 0 0 0 0 0]
1851
+ [0 0 0 0 0 0 0 0 0 0 0 0 0 0]
1852
+ [0 0 0 0 0 0 0 0 0 0 0 0 0 0]
1853
+ [0 0 0 0 0 0 0 0 0 0 0 0 0 0]
1854
+ [0 0 0 0 0 0 0 0 0 0 0 0 0 0]
1855
+ [0 0 0 0 0 0 0 0 0 0 0 0 0 0]
1856
+ [0 0 0 0 0 0 0 0 0 0 0 0 0 0]
1857
+ [0 0 0 0 0 0 0 0 0 0 0 0 0 0]
1858
+ """
1859
+ # Since Github Issue #11115, there is a special
1860
+ # type of cached for those methods that don't
1861
+ # accept arguments. We want to get Hasse-Witt
1862
+ # from the cache - but apparently it could be
1863
+ # that the cached value does not belong to self.
1864
+ # So, the easiest is:
1865
+ N, E = self._Hasse_Witt_cached()
1866
+ if E != self:
1867
+ self._Hasse_Witt_cached.clear_cache()
1868
+ N, E = self._Hasse_Witt_cached()
1869
+ return N
1870
+
1871
+ def a_number(self):
1872
+ r"""
1873
+ INPUT:
1874
+
1875
+ - ``self`` -- Hyperelliptic Curve of the form `y^2 = f(x)` over a
1876
+ finite field, `\GF{q}`
1877
+
1878
+ OUTPUT: a-number
1879
+
1880
+ EXAMPLES::
1881
+
1882
+ sage: K.<x> = GF(49, 'x')[]
1883
+ sage: C = HyperellipticCurve(x^5 + 1, 0)
1884
+ sage: C.a_number()
1885
+ 1
1886
+
1887
+ sage: K.<x> = GF(9, 'x')[]
1888
+ sage: C = HyperellipticCurve(x^7 - 1, 0)
1889
+ sage: C.a_number()
1890
+ 1
1891
+
1892
+ sage: P.<x> = GF(9, 'a')[]
1893
+ sage: E = HyperellipticCurve(x^29 + 1, 0)
1894
+ sage: E.a_number()
1895
+ 5
1896
+ """
1897
+ #We use caching here since Cartier matrix is needed to compute a_number. So if the Cartier
1898
+ #is already computed it is stored in list A. If it was not cached (i.e. A is empty), we simply
1899
+ #compute it. If it is cached then we need to make sure that we have the correct one. So check
1900
+ #which curve does the matrix correspond to. Since caching stores a lot of stuff, we only check
1901
+ #the last entry in A. If it does not match, clear A and compute Cartier.
1902
+ # Since Github Issue #11115, there is a special cache for methods
1903
+ # that don't accept arguments. The easiest is: Call the cached
1904
+ # method, and test whether the last entry is self.
1905
+ M,Coeffs,g, Fq, p,E = self._Cartier_matrix_cached()
1906
+ if E != self:
1907
+ self._Cartier_matrix_cached.clear_cache()
1908
+ M,Coeffs,g, Fq, p,E = self._Cartier_matrix_cached()
1909
+ return g - rank(M)
1910
+
1911
+ def p_rank(self):
1912
+ r"""
1913
+ INPUT:
1914
+
1915
+ - ``self`` -- Hyperelliptic Curve of the form `y^2 = f(x)` over a
1916
+ finite field, `\GF{q}`
1917
+
1918
+ OUTPUT: p-rank
1919
+
1920
+ EXAMPLES::
1921
+
1922
+ sage: K.<x> = GF(49, 'x')[]
1923
+ sage: C = HyperellipticCurve(x^5 + 1, 0)
1924
+ sage: C.p_rank()
1925
+ 0
1926
+
1927
+ sage: K.<x> = GF(9, 'x')[]
1928
+ sage: C = HyperellipticCurve(x^7 - 1, 0)
1929
+ sage: C.p_rank()
1930
+ 0
1931
+
1932
+ sage: P.<x> = GF(9, 'a')[]
1933
+ sage: E = HyperellipticCurve(x^29 + 1, 0)
1934
+ sage: E.p_rank()
1935
+ 0
1936
+ """
1937
+ #We use caching here since Hasse Witt is needed to compute p_rank. So if the Hasse Witt
1938
+ #is already computed it is stored in list A. If it was not cached (i.e. A is empty), we simply
1939
+ #compute it. If it is cached then we need to make sure that we have the correct one. So check
1940
+ #which curve does the matrix correspond to. Since caching stores a lot of stuff, we only check
1941
+ #the last entry in A. If it does not match, clear A and compute Hasse Witt.
1942
+ # However, it seems a waste of time to manually analyse the cache
1943
+ # -- See Github Issue #11115
1944
+ N, E = self._Hasse_Witt_cached()
1945
+ if E != self:
1946
+ self._Hasse_Witt_cached.clear_cache()
1947
+ N, E = self._Hasse_Witt_cached()
1948
+ return rank(N)