passagemath-schemes 10.6.40__cp314-cp314-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.

Potentially problematic release.


This version of passagemath-schemes might be problematic. Click here for more details.

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