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,1309 @@
1
+ # sage_setup: distribution = sagemath-schemes
2
+ # sage.doctest: needs sage.rings.finite_rings
3
+ r"""
4
+
5
+ Cyclic covers over a finite field
6
+
7
+ The most interesting feature is computation of Frobenius matrix on
8
+ Monsky-Washnitzer cohomology and the Frobenius polynomial.
9
+
10
+ REFERENCES:
11
+
12
+ - [ABCMT2019]_
13
+
14
+ EXAMPLES::
15
+
16
+ sage: p = 13
17
+ sage: x = PolynomialRing(GF(p),"x").gen()
18
+ sage: C = CyclicCover(4, x^4 + 1)
19
+ sage: C.frobenius_polynomial()
20
+ x^6 - 6*x^5 + 3*x^4 + 60*x^3 + 39*x^2 - 1014*x + 2197
21
+ sage: R.<t> = PowerSeriesRing(Integers())
22
+ sage: C.projective_closure().zeta_series(2,t)
23
+ 1 + 8*t + 102*t^2 + O(t^3)
24
+ sage: C.frobenius_polynomial().reverse()(t)/((1-t)*(1-p*t)) + O(t^5)
25
+ 1 + 8*t + 102*t^2 + 1384*t^3 + 18089*t^4 + O(t^5)
26
+
27
+ sage: p = 49999
28
+ sage: x = PolynomialRing(GF(p),"x").gen()
29
+ sage: CyclicCover(5, x^5 + x).frobenius_polynomial() # long time
30
+ x^12 + 299994*x^10 + 37498500015*x^8 + 2499850002999980*x^6 + 93742500224997000015*x^4
31
+ + 1874812507499850001499994*x^2 + 15623125093747500037499700001
32
+ sage: CyclicCover(5, 2*x^5 + x).frobenius_polynomial() # long time
33
+ x^12 + 299994*x^10 + 37498500015*x^8 + 2499850002999980*x^6 + 93742500224997000015*x^4
34
+ + 1874812507499850001499994*x^2 + 15623125093747500037499700001
35
+
36
+ sage: p = 107
37
+ sage: x = PolynomialRing(GF(p),"x").gen()
38
+ sage: CyclicCover(2, x^5 + x).frobenius_matrix()
39
+ [ O(107^2) 89*107 + O(107^2) O(107^2) O(107^2)]
40
+ [ 89*107 + O(107^2) O(107^2) O(107^2) O(107^2)]
41
+ [ O(107^2) O(107^2) O(107^2) 105 + 5*107 + O(107^2)]
42
+ [ O(107^2) O(107^2) 89 + 53*107 + O(107^2) O(107^2)]
43
+ sage: CyclicCover(2, 3*x^5 + x).frobenius_matrix()
44
+ [ O(107^2) 14*107 + O(107^2) O(107^2) O(107^2)]
45
+ [ 69*107 + O(107^2) O(107^2) O(107^2) O(107^2)]
46
+ [ O(107^2) O(107^2) O(107^2) 61 + 58*107 + O(107^2)]
47
+ [ O(107^2) O(107^2) 69 + 53*107 + O(107^2) O(107^2)]
48
+ sage: CyclicCover(3, x^3 + x).frobenius_matrix()
49
+ [ 0 0 O(107) O(107)]
50
+ [ 0 0 52 + O(107) O(107)]
51
+ [ O(107) 35 + O(107) 0 0]
52
+ [44 + O(107) O(107) 0 0]
53
+ sage: CyclicCover(3, 3*x^3 + x).frobenius_matrix()
54
+ [ 0 0 O(107) O(107)]
55
+ [ 0 0 79 + O(107) O(107)]
56
+ [ O(107) 42 + O(107) 0 0]
57
+ [30 + O(107) O(107) 0 0]
58
+ """
59
+
60
+ # *****************************************************************************
61
+ # Copyright (C) 2018 Vishal Arul <varul@mit.edu>,
62
+ # Alex Best <alex.j.best@gmail.com>,
63
+ # Edgar Costa <edgarc@mit.edu>,
64
+ # Richard Magner <rmagner@bu.edu>,
65
+ # Nicholas Triantafillou <ngtriant@mit.edu>
66
+ # Distributed under the terms of the GNU General Public License (GPL)
67
+ # https://www.gnu.org/licenses/
68
+ # *****************************************************************************
69
+
70
+ from sage.arith.misc import euler_phi
71
+ from sage.matrix.constructor import matrix, zero_matrix
72
+ from sage.misc.cachefunc import cached_method
73
+ from sage.misc.lazy_import import lazy_import
74
+ from sage.modules.free_module_element import vector
75
+ from sage.rings.finite_rings.integer_mod_ring import IntegerModRing
76
+ from sage.rings.integer_ring import ZZ
77
+ from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing
78
+ from sage.rings.power_series_ring import PowerSeriesRing
79
+
80
+ lazy_import("sage.functions.log", "log")
81
+ lazy_import("sage.functions.other", ["ceil", "binomial", "floor"])
82
+ lazy_import('sage.rings.padics.factory', ['Zp', 'Zq', 'Qq'])
83
+ lazy_import('sage.schemes.hyperelliptic_curves.hypellfrob', 'interval_products')
84
+
85
+ from .charpoly_frobenius import charpoly_frobenius
86
+ from . import cycliccover_generic
87
+
88
+
89
+ def _N0_nodenominators(p, g, n):
90
+ """
91
+ Return the necessary `p`-adic precision for the Frobenius matrix to deduce
92
+ the characteristic polynomial of Frobenius using the Newton identities,
93
+ using :meth:`charpoly_frobenius`, which assumes that the Frobenius matrix
94
+ is integral, i.e., has no denominators.
95
+
96
+ INPUT:
97
+
98
+ - ``p`` -- prime
99
+ - ``g`` -- genus
100
+ - ``n`` -- degree of residue field
101
+
102
+ TESTS::
103
+
104
+ sage: sage.schemes.cyclic_covers.cycliccover_finite_field._N0_nodenominators(4999, 4, 5)
105
+ 11
106
+ """
107
+ return max(
108
+ ceil(log(2 * (2 * g) / ZZ(i), p) + (n * i) / ZZ(2)) for i in range(1, g + 1)
109
+ )
110
+
111
+
112
+ class CyclicCover_finite_field(cycliccover_generic.CyclicCover_generic):
113
+ def __init__(self, AA, r, f, names=None, verbose=0):
114
+ """
115
+ EXAMPLES::
116
+
117
+ sage: p = 13
118
+ sage: x = PolynomialRing(GF(p), "x").gen()
119
+ sage: C = CyclicCover(4, x^4 + 1)
120
+ sage: C.frobenius_polynomial()
121
+ x^6 - 6*x^5 + 3*x^4 + 60*x^3 + 39*x^2 - 1014*x + 2197
122
+ sage: R.<t> = PowerSeriesRing(Integers())
123
+ sage: C.projective_closure().zeta_series(2,t)
124
+ 1 + 8*t + 102*t^2 + O(t^3)
125
+ sage: C.frobenius_polynomial().reverse()(t)/((1-t)*(1-p*t)) + O(t^5)
126
+ 1 + 8*t + 102*t^2 + 1384*t^3 + 18089*t^4 + O(t^5)
127
+ """
128
+ cycliccover_generic.CyclicCover_generic.__init__(self, AA, r, f, names=names)
129
+ self._verbose = verbose
130
+ self._init_frobQ = False
131
+ self._N0 = None
132
+
133
+ def _init_frob(self, desired_prec=None):
134
+ """
135
+ Initialise everything for Frobenius polynomial computation.
136
+
137
+ TESTS::
138
+
139
+ sage: p = 4999
140
+ sage: x = PolynomialRing(GF(p),"x").gen()
141
+ sage: C = CyclicCover(3, x^4 + 4*x^3 + 9*x^2 + 3*x + 1)
142
+ sage: C._init_frob()
143
+ sage: C._init_frobQ
144
+ True
145
+ sage: C._plarge
146
+ True
147
+ sage: C._sqrtp
148
+ True
149
+ """
150
+
151
+ def _N0_RH():
152
+ return ceil(
153
+ log(2 * binomial(2 * self._genus, self._genus), self._p)
154
+ + self._genus * self._n / ZZ(2)
155
+ )
156
+
157
+ def _find_N0():
158
+ if self._nodenominators:
159
+ return _N0_nodenominators(self._p, self._genus, self._n)
160
+ else:
161
+ return _N0_RH() + self._extraprec
162
+
163
+ def _find_N_43():
164
+ """
165
+ Find the precision used for thm 4.3 in Goncalves
166
+ for p >> 0, N = N0 + 2
167
+ """
168
+ p = self._p
169
+ r = self._r
170
+ d = self._d
171
+ delta = self._delta
172
+ N0 = self._N0
173
+ left_side = N0 + floor(log((d * p * (r - 1) + r) / delta) / log(p))
174
+
175
+ def right_side_log(n):
176
+ return floor(log(p * (r * n - 1) - r) / log(p))
177
+
178
+ n = left_side
179
+ while n <= left_side + right_side_log(n):
180
+ n += 1
181
+ return n
182
+
183
+ if not self._init_frobQ or self._N0 != desired_prec:
184
+ if self._r < 2 or self._d < 2:
185
+ raise NotImplementedError("Only implemented for r, f.degree() >= 2")
186
+
187
+ self._init_frobQ = True
188
+
189
+ self._Fq = self._f.base_ring()
190
+ self._p = self._Fq.characteristic()
191
+ self._q = self._Fq.cardinality()
192
+ self._n = self._Fq.degree()
193
+ self._epsilon = 0 if self._delta == 1 else 1
194
+
195
+ # our basis choice doesn't always give an integral matrix
196
+ if self._epsilon == 0:
197
+ self._extraprec = floor(
198
+ log(self._r, self._p)
199
+ + log((2 * self._genus + (self._delta - 2)) / self._delta, self._p)
200
+ )
201
+ else:
202
+ self._extraprec = floor(log(self._r * 2 - 1, self._p))
203
+
204
+ self._nodenominators = self._extraprec == 0
205
+
206
+ if desired_prec is None:
207
+ self._N0 = _find_N0()
208
+ else:
209
+ self._N0 = desired_prec
210
+
211
+ self._plarge = self._p > self._d * self._r * (self._N0 + self._epsilon)
212
+
213
+ # working prec
214
+ if self._plarge:
215
+ self._N = self._N0 + 1
216
+ else:
217
+ self._N = _find_N_43()
218
+
219
+ # we will use the sqrt(p) version?
220
+ self._sqrtp = self._plarge and self._p == self._q
221
+ self._extraworkingprec = self._extraprec
222
+ if not self._plarge:
223
+ # we might have some denominators showing up during horizontal
224
+ # and vertical reductions
225
+ self._extraworkingprec += 2 * ceil(
226
+ log(self._d * self._r * (self._N0 + self._epsilon), self._p)
227
+ )
228
+
229
+ # Rings
230
+ if self._plarge and self._nodenominators:
231
+ if self._n == 1:
232
+ # IntegerModRing is significantly faster than Zq
233
+ self._Zq = IntegerModRing(self._p**self._N)
234
+ if self._sqrtp:
235
+ self._Zq0 = IntegerModRing(self._p**(self._N - 1))
236
+ self._Qq = Qq(self._p, prec=self._N, type='capped-rel')
237
+ self._w = 1
238
+ else:
239
+ self._Zq = Zq(
240
+ self._q,
241
+ names='w',
242
+ modulus=self._Fq.polynomial(),
243
+ prec=self._N,
244
+ type='capped-abs',
245
+ )
246
+ self._w = self._Zq.gen()
247
+ self._Qq = self._Zq.fraction_field()
248
+ else:
249
+ self._Zq = Qq(
250
+ self._q,
251
+ names='w',
252
+ modulus=self._Fq.polynomial(),
253
+ prec=self._N + self._extraworkingprec,
254
+ )
255
+ self._w = self._Zq.gen()
256
+ self._Qq = self._Zq
257
+ self._Zp = Zp(self._p, prec=self._N + self._extraworkingprec)
258
+
259
+ self._Zqx = PolynomialRing(self._Zq, "x")
260
+
261
+ # Want to take a lift of f from Fq to Zq
262
+ if self._n == 1:
263
+ # When n = 1, can lift from Fp[x] to Z[x] and then to Zp[x]
264
+ self._flift = self._Zqx([elt.lift() for elt in self._f.list()])
265
+ self._frobf = self._Zqx(self._flift.list())
266
+ else: # When n > 1, need to be more careful with the lift
267
+ self._flift = self._Zqx(
268
+ [
269
+ elt.polynomial().change_ring(ZZ)(self._Zq.gen())
270
+ for elt in self._f.list()
271
+ ]
272
+ )
273
+
274
+ self._frobf = self._Zqx([elt.frobenius() for elt in self._flift.list()])
275
+
276
+ self._dflift = self._flift.derivative()
277
+
278
+ # Set up local cache for Frob(f)^s
279
+
280
+ # This variable will store the powers of frob(f)
281
+ frobpow = [None] * (self._N0 + 2)
282
+ frobpow[0] = self._Zqx(1)
283
+ for k in range(self._N0 + 1):
284
+ frobpow[k + 1] = self._frobf * frobpow[k]
285
+ # We don't make it a polynomials as we need to keep track that the
286
+ # ith coefficient represents (i*p)-th
287
+ self._frobpow_list = [elt.list() for elt in frobpow]
288
+
289
+ if self._sqrtp:
290
+ # precision of self._Zq0
291
+ N = self._N - 1
292
+ vandermonde = matrix(self._Zq0, N, N)
293
+ for i in range(N):
294
+ vandermonde[i, 0] = 1
295
+ for j in range(1, N):
296
+ vandermonde[i, j] = vandermonde[i, j - 1] * (i + 1)
297
+ self._vandermonde = vandermonde.inverse()
298
+
299
+ self._horizontal_fat_s = {}
300
+ self._vertical_fat_s = {}
301
+
302
+ def _divide_vector(self, D, vect, R):
303
+ """
304
+ Divide the vector `vect` by `D` as a vector over `R`.
305
+
306
+ TESTS::
307
+
308
+ sage: p = 4999
309
+ sage: x = PolynomialRing(GF(p), "x").gen()
310
+ sage: C = CyclicCover(3, x^4 + 4*x^3 + 9*x^2 + 3*x + 1)
311
+ sage: C._init_frob()
312
+ sage: C._divide_vector(p, vector(C._Qq, [p, p^2, p^3]), C._Qq)
313
+ (1 + O(4999^3), 4999 + O(4999^4), 4999^2 + O(4999^5))
314
+ """
315
+ DQq = self._Qq(D).lift_to_precision(self._Qq.precision_cap())
316
+ m = 1 / DQq
317
+ if not R.is_field():
318
+ vectQq = vector(
319
+ self._Qq,
320
+ [
321
+ m * self._Qq(elt).lift_to_precision(self._Qq.precision_cap())
322
+ for elt in vect
323
+ ],
324
+ )
325
+ return vector(R, [R(elt) for elt in vectQq])
326
+ else:
327
+ return vector(R, [(m * elt).lift_to_precision() for elt in vect])
328
+
329
+ def _frob_sparse(self, i, j, N0):
330
+ r"""
331
+ Compute `Frob(x^i y^(-j) dx ) / dx` for y^r = f(x) with N0 terms.
332
+
333
+ INPUT:
334
+
335
+ - ``i`` -- the power of x in the expression `Frob(x^i dx/y^j) / dx`
336
+
337
+ - ``j`` -- the (negative) power of y in the expression
338
+ `Frob(x^i dx/y^j) / dx`
339
+
340
+ OUTPUT:
341
+
342
+ ``frobij`` -- a Matrix of size (d * (N0 - 1) + ) x (N0)
343
+ that represents the Frobenius expansion of
344
+ x^i dx/y^j modulo p^(N0 + 1)
345
+
346
+ the entry (l, s) corresponds to the coefficient associated
347
+ to the monomial x**(p * (i + 1 + l) -1) * y**(p * -(j + r*s))
348
+ (l, s) --> (p * (i + 1 + l) -1, p * -(j + r*s))
349
+
350
+ ALGORITHM:
351
+
352
+ Compute:
353
+
354
+ Frob(x^i dx/y^j) / dx = p * x ** (p * (i+1) - 1) * y ** (-j*p) * Sigma
355
+
356
+ where:
357
+
358
+ .. MATH::
359
+
360
+ Sigma = \sum_{k = 0} ^{N0-1}
361
+ \sum_{s = 0} ^k
362
+ (-1) ** (k-s) * binomial(k, s)
363
+ * binomial(-j/r, k)
364
+ * self._frobpow[s]
365
+ * self._y ** (-self._r * self._p * s)
366
+ = \sum_{s = 0} ^{N0 - 1}
367
+ \sum_{k = s} ^N0
368
+ (-1) ** (k-s) * binomial(k, s)
369
+ * binomial(-j/self._r, k)
370
+ * self._frobpow[s]
371
+ * self._y ** (-self._r*self._p*s)
372
+ = \sum_{s = 0} ^{N0-1}
373
+ D_{j, s}
374
+ * self._frobpow[s]
375
+ * self._y ** (-self._r * self._p * s)
376
+ = \sum_{s = 0} ^N0
377
+ \sum_{l = 0} ^(d*s)
378
+ D_{j, s} * self._frobpow[s][l]
379
+ * x ** (self._p ** l)
380
+ * y ** (-self._r * self._p ** s)
381
+
382
+ and:
383
+
384
+ .. MATH::
385
+
386
+ D_{j, s} = \sum_{k = s} ^N0 (-1) ** (k-s) * binomial(k, s) * binomial(-j/self._r, k) )
387
+
388
+ TESTS::
389
+
390
+ sage: p = 499
391
+ sage: x = PolynomialRing(GF(p), "x").gen()
392
+ sage: C = CyclicCover(3, x^4 + 4*x^3 + 9*x^2 + 3*x + 1)
393
+ sage: C._init_frob()
394
+ sage: C._frob_sparse(2, 0, 1)
395
+ [499]
396
+ sage: C._frob_sparse(2, 0, 2)
397
+ [499 0]
398
+ [ 0 0]
399
+ [ 0 0]
400
+ [ 0 0]
401
+ [ 0 0]
402
+ sage: C._frob_sparse(2, 1, 1)
403
+ [499]
404
+ sage: C._frob_sparse(2, 1, 2)
405
+ [ 82834998 41417000]
406
+ [ 0 124251000]
407
+ [ 0 124250002]
408
+ [ 0 41416501]
409
+ [ 0 41417000]
410
+ sage: C._frob_sparse(2, 2, 1)
411
+ [499]
412
+ """
413
+
414
+ def _extend_frobpow(power):
415
+ if power < len(self._frobpow_list):
416
+ pass
417
+ else:
418
+ frobpow = self._Zqx(self._frobpow_list[-1])
419
+ for k in range(len(self._frobpow_list), power + 1):
420
+ frobpow *= self._frobf
421
+ self._frobpow_list.extend([frobpow.list()])
422
+ assert power < len(self._frobpow_list)
423
+
424
+ _extend_frobpow(N0)
425
+ r = self._r
426
+ Dj = [
427
+ self._Zq(
428
+ sum(
429
+ [
430
+ (-1) ** (k - l) * binomial(k, l) * binomial(-ZZ(j) / r, k)
431
+ for k in range(l, N0)
432
+ ]
433
+ )
434
+ )
435
+ for l in range(N0)
436
+ ]
437
+ frobij = matrix(self._Zq, self._d * (N0 - 1) + 1, N0)
438
+ for s in range(N0):
439
+ for l in range(self._d * s + 1):
440
+ frobij[l, s] = self._p * Dj[s] * self._frobpow_list[s][l]
441
+ return frobij
442
+
443
+ def _horizontal_matrix_reduction(self, s):
444
+ r"""
445
+ Return the tuple of tuples that represents the horizontal matrix
446
+ reduction at pole order ``s``.
447
+
448
+ INPUT:
449
+
450
+ - ``s`` -- integer
451
+
452
+ OUTPUT:
453
+
454
+ A tuple of tuples ``( (D0, D1), (M0, M1) )``
455
+ where `MH_{e, s} = M0 + e * M1` and `DH_{e,s} = D0 + e * D1`
456
+
457
+ ALGORITHM:
458
+
459
+ Let `W_{e, s}` to be the Qq-vector space of differential forms
460
+ of the form:
461
+
462
+ .. MATH:: G x^e y^{-s} dx
463
+
464
+ where `\deg G \leq d - 1`.
465
+
466
+ Let `v = [G_0, ..., G_{d-1}]` represent G
467
+
468
+ There is a map:
469
+
470
+ `MH_{e, s} : W_{e, s} \to W_{e-1, s}`
471
+
472
+ and a function to:
473
+
474
+ `DH: \NN \times \NN \to Qq`
475
+
476
+ such that:
477
+
478
+ `G x^e y^{-s} dx \cong H x^{e - 1} y^{-s} dx`
479
+
480
+ where `H = DH(e, s)^{-1} * MH_{e,s} ( G )`
481
+
482
+ The matrix `MH_{e, s}` can be written as:
483
+
484
+ `MH_{e, s} = M0_{s} + e * M1_{s}`
485
+
486
+ similarly:
487
+
488
+ `DH_{e,s} = D0_{s} + e * D1_{s}`
489
+
490
+ TESTS::
491
+
492
+ sage: p = 4999
493
+ sage: x = PolynomialRing(GF(p), "x").gen()
494
+ sage: C = CyclicCover(3, x^4 + 4*x^3 + 9*x^2 + 3*x + 1)
495
+ sage: C._init_frob()
496
+ sage: C._horizontal_matrix_reduction(24995)
497
+ ((99968, 124925014996),
498
+ (
499
+ [ 0 0 0 0]
500
+ [ 99968 0 0 124924940023]
501
+ [ 0 99968 0 124924565143]
502
+ [ 0 0 99968 124924715095],
503
+ <BLANKLINE>
504
+ [ 0 0 0 3]
505
+ [124925014996 0 0 9]
506
+ [ 0 124925014996 0 27]
507
+ [ 0 0 124925014996 12]
508
+ ))
509
+ sage: C._horizontal_matrix_reduction(4999)
510
+ ((19984, 124925014996),
511
+ (
512
+ [ 0 0 0 0]
513
+ [ 19984 0 0 124925000011]
514
+ [ 0 19984 0 124924925071]
515
+ [ 0 0 19984 124924955047],
516
+ <BLANKLINE>
517
+ [ 0 0 0 3]
518
+ [124925014996 0 0 9]
519
+ [ 0 124925014996 0 27]
520
+ [ 0 0 124925014996 12]
521
+ ))
522
+ """
523
+
524
+ f_co = self._flift.list()
525
+ # DH_{e,s} = ((s -r)*d - e * r) * f_d
526
+ m1 = -1 * self._r * f_co[-1] # r is a, g_co[-1] is lambda
527
+ m0 = (s - self._r) * self._d * f_co[-1] # j is a*t + beta
528
+
529
+ M1 = matrix(
530
+ self._Zq,
531
+ self._d,
532
+ lambda m, n: m1
533
+ if m == n + 1
534
+ else self._r * f_co[m]
535
+ if n == self._d - 1
536
+ else 0,
537
+ )
538
+ M0 = matrix(
539
+ self._Zq,
540
+ self._d,
541
+ lambda m, n: m0
542
+ if m == n + 1
543
+ else (self._r - s) * m * f_co[m]
544
+ if n == self._d - 1
545
+ else 0,
546
+ )
547
+
548
+ return ((m0, m1), (M0, M1))
549
+
550
+ def _vertical_matrix_reduction(self, s0):
551
+ r"""
552
+ Return the tuple of tuples that represents the vertical matrix reduction.
553
+
554
+ OUTPUT:
555
+
556
+ A tuple of tuples ``( (D0, D1), (M0, M1) )``
557
+ where MV_t = M0 + t * M1 and DV_t = D0 + t * D1
558
+
559
+ TESTS::
560
+
561
+ sage: p = 4999
562
+ sage: x = PolynomialRing(GF(p), "x").gen()
563
+ sage: C = CyclicCover(3, x^4 + 4*x^3 + 9*x^2 + 3*x + 1)
564
+ sage: C._init_frob()
565
+ sage: C._vertical_matrix_reduction(1)
566
+ ((-2, 3),
567
+ (
568
+ [117410728377 65750007895 58235721278]
569
+ [ 67628579544 59175007105 15028573234]
570
+ [ 86414296088 0 27239288985],
571
+ <BLANKLINE>
572
+ [ 51660720493 75142866164 0]
573
+ [ 74203580341 2817857481 75142866164]
574
+ [108017870113 0 2817857481]
575
+ ))
576
+ sage: C._vertical_matrix_reduction(2)
577
+ ((-1, 3),
578
+ (
579
+ [92989296875 7514286617 58235721278]
580
+ [50721434658 60114292932 81717866955]
581
+ [80778581126 0 28178574812],
582
+ <BLANKLINE>
583
+ [ 51660720493 75142866164 0]
584
+ [ 74203580341 2817857481 75142866164]
585
+ [108017870113 0 2817857481]
586
+ ))
587
+ """
588
+
589
+ d = self._d
590
+ f_co = (
591
+ [0 for i in range(d - 2)] + self._flift.list() + [0 for i in range(d - 1)]
592
+ )
593
+ fd_co = (
594
+ [0 for i in range(d - 1)] + self._dflift.list() + [0 for i in range(d)]
595
+ )
596
+
597
+ rows = [f_co[d - 2 - i:-i - 1] for i in range(d - 1)]
598
+ rows += [fd_co[d - 1 - i:-i - 1] for i in range(d)]
599
+
600
+ m = matrix(rows).transpose().inverse()
601
+
602
+ a_foo = m[0:d, 0:d]
603
+ b_foo = m[d - 1:2 * d - 1, 0:d]
604
+ a_foo = matrix(d, d, lambda i, j: 1 if i == j and i != d - 1 else 0) * a_foo
605
+ foo = matrix(d, d, lambda i, j: j if i == j - 1 else 0)
606
+ bp_foo = foo * b_foo
607
+ A_vert = a_foo.submatrix(0, 0, d - 1, d - 1)
608
+ Bd_vert = bp_foo.submatrix(0, 0, d - 1, d - 1)
609
+ M1 = (s0 - self._r) * A_vert + self._r * Bd_vert
610
+ M2 = self._r * A_vert
611
+ m1 = s0 - self._r
612
+ m2 = self._r
613
+ return ((m1, m2), (M1, M2))
614
+
615
+ def _reduce_vector_horizontal(self, G, e, s, k=1):
616
+ r"""
617
+ INPUT:
618
+
619
+ - a vector -- `G \in W_{e, s}`
620
+
621
+ OUTPUT:
622
+
623
+ - a vector -- `H \in W_{e - k, s}` such that
624
+ `G x^e y^{-s} dx \cong H x^{e - k} y^{-s} dx`
625
+
626
+ TESTS::
627
+
628
+ sage: p = 4999
629
+ sage: x = PolynomialRing(GF(p), "x").gen()
630
+ sage: C = CyclicCover(3, x^4 + 4*x^3 + 9*x^2 + 3*x + 1)
631
+ sage: C._init_frob()
632
+ sage: C._initialize_fat_horizontal(p, 3)
633
+ sage: C._reduce_vector_horizontal((83283349998, 0, 0, 0), 2*p - 1, p, p)
634
+ (23734897071, 84632332850, 44254975407, 23684517017)
635
+ sage: C._reduce_vector_horizontal((98582524551, 3200841460, 6361495378, 98571346457), 2*p - 1, p, p)
636
+ (96813533420, 61680190736, 123292559950, 96786566978)
637
+ """
638
+ if self._sqrtp and k == self._p:
639
+ vect = self._reduce_vector_horizontal_BSGS(G, e, s)
640
+ else:
641
+ vect = self._reduce_vector_horizontal_plain(G, e, s, k)
642
+ return vect
643
+
644
+ def _reduce_vector_horizontal_BSGS(self, G, e, s):
645
+ r"""
646
+ INPUT:
647
+
648
+ - a vector -- `G \in W_{e, s}`
649
+
650
+ OUTPUT:
651
+
652
+ - a vector -- `H \in W_{e - p, s}` such that
653
+ `G x^e y^{-s} dx \cong H x^{e - p} y^{-s} dx`
654
+
655
+ TESTS::
656
+
657
+ sage: p = 4999
658
+ sage: x = PolynomialRing(GF(p), "x").gen()
659
+ sage: C = CyclicCover(3, x^4 + 4*x^3 + 9*x^2 + 3*x + 1)
660
+ sage: C._init_frob()
661
+ sage: C._initialize_fat_horizontal(p, 3)
662
+ sage: C._reduce_vector_horizontal_BSGS((0, 0, 0, 0), 2*p - 1, p)
663
+ (0, 0, 0, 0)
664
+ sage: C._reduce_vector_horizontal_BSGS((83283349998, 0, 0, 0), 2*p - 1, p)
665
+ (23734897071, 84632332850, 44254975407, 23684517017)
666
+ sage: C._reduce_vector_horizontal_BSGS((98582524551, 3200841460, 6361495378, 98571346457), 2*p - 1, p)
667
+ (96813533420, 61680190736, 123292559950, 96786566978)
668
+ """
669
+ if G == 0:
670
+ return G
671
+ if self._verbose > 2:
672
+ print(
673
+ "_reduce_vector_horizontal_BSGS(self, %s, %s, %s)"
674
+ % (vector(self._Qq, G), e, s)
675
+ )
676
+ assert (e + 1) % self._p == 0
677
+ (m0, m1), (M0, M1) = self._horizontal_matrix_reduction(s)
678
+ vect = vector(self._Zq, G)
679
+ # we do the first d reductions carefully
680
+ D = 1
681
+ for i in reversed(range(e - self._d + 1, e + 1)):
682
+ Mi = M0 + i * M1
683
+ Di = m0 + i * m1
684
+
685
+ vect = Mi * vect
686
+ D *= Di
687
+ assert Di % self._p == 0
688
+ iD = 1 / self._Zq0(D.lift() / self._p)
689
+ vect = vector(self._Zq0, [iD * ZZ(elt.lift() / self._p) for elt in vect])
690
+ # use BSGS
691
+
692
+ iDH, MH = self._horizontal_fat_s[s][(e + 1) / self._p - 1]
693
+ vect = iDH * (MH * vect.change_ring(self._Zq0))
694
+
695
+ # last reduction
696
+ i = e - self._p + 1
697
+ Mi = M0 + i * M1
698
+ Di = 1 / (m0 + i * m1)
699
+
700
+ vect = Di * (Mi * vect.change_ring(self._Zq))
701
+
702
+ if self._verbose > 2:
703
+ print(
704
+ "done _reduce_vector_horizontal_BSGS(self, %s, %s, %s)"
705
+ % (vector(self._Qq, G), e, s)
706
+ )
707
+ print("return %s\n" % (vector(self._Qq, vect),))
708
+ return vect
709
+
710
+ def _initialize_fat_horizontal(self, s, L):
711
+ """
712
+ Initialise reduction matrices for horizontal reductions for blocks from `s` to `L`.
713
+
714
+ TESTS::
715
+
716
+ sage: p = 4999
717
+ sage: x = PolynomialRing(GF(p), "x").gen()
718
+ sage: C = CyclicCover(3, x^4 + 4*x^3 + 9*x^2 + 3*x + 1)
719
+ sage: C._init_frob()
720
+ sage: C._initialize_fat_horizontal(p, 3)
721
+ sage: len(C._horizontal_fat_s[p])
722
+ 3
723
+ """
724
+ assert self._sqrtp
725
+ if s not in self._horizontal_fat_s:
726
+ N = self._N - 1 # padic precision of self._Zq0
727
+ d = self._d
728
+ L0 = min(L, N)
729
+ targets = [0] * (2 * L0)
730
+ for l in range(L0):
731
+ targets[2 * l] = self._p * l
732
+ targets[2 * l + 1] = self._p * (l + 1) - d - 1
733
+ (m0, m1), (M0, M1) = self._horizontal_matrix_reduction(s)
734
+ M0, M1 = (elt.change_ring(self._Zq0) for elt in [M0, M1])
735
+ D0, D1 = (matrix(self._Zq0, [elt]) for elt in [m0, m1])
736
+ MH = interval_products(M0, M1, targets)
737
+ DH = [elt[0, 0] for elt in interval_products(D0, D1, targets)]
738
+ if L > N: # Vandermonde interpolation
739
+ # f^{(r)}(0) p^r / r! for r = 0, ..., N-1,
740
+ MT = [None] * N
741
+ DT = [0] * N
742
+ for r in range(N):
743
+ MT[r] = matrix(self._Zq0, d, d)
744
+ for h in range(N):
745
+ v = self._vandermonde[r, h]
746
+ for i in range(d):
747
+ for j in range(d):
748
+ MT[r][i, j] += v * MH[h][i, j]
749
+ DT[r] += v * DH[h]
750
+ for k in range(N, L):
751
+ M = matrix(self._Zq0, d, d)
752
+ D = 0
753
+ k1pow = self._Zq0(1) # power of k + 1
754
+ for h in range(N):
755
+ for i in range(d):
756
+ for j in range(d):
757
+ M[i, j] += k1pow * MT[h][i, j]
758
+ D += k1pow * DT[h]
759
+ k1pow *= k + 1
760
+ MH.append(M)
761
+ DH.append(D)
762
+
763
+ iDH = [1 / elt for elt in DH]
764
+ self._horizontal_fat_s[s] = [(iDH[i], MH[i]) for i in range(L)]
765
+ assert len(self._horizontal_fat_s[s]) >= L
766
+
767
+ def _reduce_vector_horizontal_plain(self, G, e, s, k=1):
768
+ r"""
769
+ INPUT:
770
+
771
+ - a vector -- `G \in W_{e, s}`
772
+
773
+ OUTPUT:
774
+
775
+ - a vector -- `H \in W_{e - k, s}` such that
776
+ `G x^e y^{-s} dx \cong H x^{e - k} y^{-s} dx`
777
+
778
+ TESTS::
779
+
780
+ sage: p = 4999
781
+ sage: x = PolynomialRing(GF(p), "x").gen()
782
+ sage: C = CyclicCover(3, x^4 + 4*x^3 + 9*x^2 + 3*x + 1)
783
+ sage: C._init_frob()
784
+ sage: C._initialize_fat_horizontal(p, 3)
785
+ sage: C._reduce_vector_horizontal_plain((83283349998, 0, 0, 0), 2*p - 1, p, p)
786
+ (23734897071, 110671913892, 91161207284, 49524178051)
787
+ sage: C._reduce_vector_horizontal_plain((98582524551, 3200841460, 6361495378, 98571346457), 2*p - 1, p, p)
788
+ (96813533420, 65678590896, 12037075498, 66773575777)
789
+ sage: (C._reduce_vector_horizontal_plain((98582524551, 3200841460, 6361495378, 98571346457), 2*p - 1, p, p) - C._reduce_vector_horizontal_plain((98582524551, 3200841460, 6361495378, 98571346457), 2*p - 1, p, p)) % p^C._N0 == 0
790
+ True
791
+ """
792
+ if self._verbose > 2:
793
+ print(
794
+ "_reduce_vector_horizontal_plain(self, G = %s, e = %s, s = %s, k = %s)"
795
+ % (vector(self._Qq, G), e, s, k)
796
+ )
797
+ if G == 0:
798
+ return G
799
+ (m0, m1), (M0, M1) = self._horizontal_matrix_reduction(s)
800
+ vect = vector(self._Zq, G)
801
+ D = self._Zq(1)
802
+ assert k <= self._p, "more than p reductions at a time should be avoided!"
803
+ assert e - k + 1 >= 0
804
+ for i in reversed(range(e - k + 1, e + 1)):
805
+ Mi = M0 + i * M1
806
+ Di = m0 + i * m1
807
+
808
+ vect = Mi * vect
809
+ D *= Di
810
+ if self._plarge and Di % self._p == 0:
811
+ assert (i + self._d) % self._p == 0
812
+ vect = self._divide_vector(D, vect, self._Zq)
813
+ D = self._Zq(1)
814
+
815
+ vect = self._divide_vector(D, vect, self._Zq)
816
+
817
+ if self._verbose > 2:
818
+ print(
819
+ "done _reduce_vector_horizontal_plain(self, %s, %s, %s, %s)"
820
+ % (vector(self._Qq, G), e, s, k)
821
+ )
822
+ print("return %s\n" % (vector(self._Qq, vect),))
823
+ return vect
824
+
825
+ def _reduce_vector_vertical(self, G, s0, s, k=1):
826
+ r"""
827
+ Reduce the vector `G` representing an element of `W_{-1,rs + s0}` by `r k` steps.
828
+
829
+ INPUT:
830
+
831
+ - a vector -- `G \in W_{-1, r*s + s0}`
832
+
833
+ OUTPUT:
834
+
835
+ - a vector -- `H \in W_{-1, r*(s - k) + s0}` such that
836
+ `G y^{-(r*s + s0)} dx \cong H y^{-(r*(s -k) + s0)} dx`
837
+
838
+ TESTS::
839
+
840
+ sage: p = 4999
841
+ sage: x = PolynomialRing(GF(p),"x").gen()
842
+ sage: C = CyclicCover(3, x^4 + 4*x^3 + 9*x^2 + 3*x + 1)
843
+ sage: C._init_frob()
844
+ sage: C._reduce_vector_vertical((96683034459, 33074345103, 43132216686), 1, p // 3, p // 3)
845
+ (4364634303, 124117911400, 26239932330)
846
+ """
847
+
848
+ def _reduce_vector_vertical_plain(G, s0, s, k=1):
849
+ r"""
850
+ INPUT:
851
+
852
+ - a vector -- `G \in W_{-1, r*s + s0}`
853
+
854
+ OUTPUT:
855
+
856
+ - a vector -- `H \in W_{-1, r*(s - k) + s0}` such that
857
+ `G y^{-(r*s + s0)} dx \cong H y^{-(r*(s -k) + s0)} dx`
858
+ """
859
+ if self._verbose > 2:
860
+ print(
861
+ "_reduce_vector_vertical(self, G = %s, s0 = %s, s = %s, k = %s)"
862
+ % (vector(self._Qq, G), s0, s, k)
863
+ )
864
+
865
+ (m0, m1), (M0, M1) = self._vertical_matrix_reduction(s0)
866
+ vect = vector(self._Zq, G)
867
+ D = 1
868
+ assert k <= self._p, "more than p reductions at a time should be avoided!"
869
+ assert s - k >= 0
870
+ for i in reversed(range(s - k + 1, s + 1)):
871
+ Mi = M0 + i * M1
872
+ Di = m0 + i * m1
873
+ vect = Mi * vect
874
+ if self._plarge and Di % self._p != 0:
875
+ D *= Di
876
+ else:
877
+ vect = self._divide_vector(Di, vect, self._Zq)
878
+
879
+ vect = self._divide_vector(D, vect, self._Zq)
880
+
881
+ if self._verbose > 2:
882
+ print(
883
+ "done _reduce_vector_vertical(self, %s, %s, %s)"
884
+ % (vector(self._Qq, G), s, k)
885
+ )
886
+ print("return %s\n" % (vector(self._Qq, vect),))
887
+
888
+ return vect
889
+
890
+ G = vector(self._Zq, G)
891
+
892
+ if self._sqrtp:
893
+ self._initialize_fat_vertical(s0, s)
894
+ if k < self._p:
895
+ assert s - k == self._epsilon
896
+ MV = self._vertical_fat_s[s0][0]
897
+ elif k == self._p:
898
+ MV = self._vertical_fat_s[s0][s // self._p]
899
+
900
+ return MV * G
901
+ else:
902
+ return _reduce_vector_vertical_plain(G, s0, s, k)
903
+
904
+ def _initialize_fat_vertical(self, s0, max_upper_target):
905
+ """
906
+ Initialise reduction matrices for vertical reductions for blocks from `s0` to `s0 + max_upper_target`.
907
+
908
+ TESTS::
909
+
910
+ sage: p = 4999
911
+ sage: x = PolynomialRing(GF(p), "x").gen()
912
+ sage: C = CyclicCover(3, x^4 + 4*x^3 + 9*x^2 + 3*x + 1)
913
+ sage: C._init_frob()
914
+ sage: C._initialize_fat_vertical(1, p + p // 3)
915
+ sage: len(C._vertical_fat_s[1])
916
+ 2
917
+ """
918
+ L = floor((max_upper_target - self._epsilon) / self._p) + 1
919
+ if s0 not in self._vertical_fat_s:
920
+ (m0, m1), (M0, M1) = self._vertical_matrix_reduction(s0)
921
+ D0, D1 = (matrix(self._Zq, [y]) for y in [m0, m1])
922
+ targets = [0] * (2 * L)
923
+ for l in reversed(range(L)):
924
+ targets[2 * l] = max_upper_target - self._p * (L - l)
925
+ targets[2 * l + 1] = max_upper_target - self._p * (L - 1 - l)
926
+ if targets[0] < 0:
927
+ targets[0] = self._epsilon
928
+ MV = interval_products(M0, M1, targets)
929
+ DV = interval_products(D0, D1, targets)
930
+ for l in range(L):
931
+ D = DV[l][0, 0]
932
+ if D % self._p == 0:
933
+ iD = 1 / self._Zq(D.lift() / self._p)
934
+ MV[l] = matrix(
935
+ self._Zq,
936
+ [
937
+ [iD * ZZ(elt.lift() / self._p) for elt in row]
938
+ for row in MV[l].rows()
939
+ ],
940
+ )
941
+ else:
942
+ MV[l] *= 1 / D
943
+ self._vertical_fat_s[s0] = MV
944
+
945
+ assert len(self._vertical_fat_s[s0]) >= L
946
+
947
+ def _frob(self, i, j, N0):
948
+ r"""
949
+ Compute `Frob(x^i dx/y^j) / dx` in terms of the cohomology basis,
950
+ whose `x` and `y` exponents are constrained to be in a particular range.
951
+
952
+ INPUT:
953
+
954
+ - ``i``, ``j`` -- exponents of the basis differential
955
+ - ``N0`` -- desired `p`-adic precision for the Frobenius expansion
956
+
957
+ TESTS::
958
+
959
+ sage: p = 4999
960
+ sage: x = PolynomialRing(GF(p), "x").gen()
961
+ sage: C = CyclicCover(3, x^4 + 4*x^3 + 9*x^2 + 3*x + 1)
962
+ sage: C._init_frob()
963
+ sage: C._frob(2, 0, 1)
964
+ [3174 + O(4999)]
965
+ [1844 + O(4999)]
966
+ [4722 + O(4999)]
967
+ """
968
+ # a Matrix that represents the Frobenius expansion of
969
+ # x^i dx/y^j modulo p^(N0 + 1)
970
+ # the entry (l, s) corresponds to the coefficient associated to the monomial x ** (p * (i + 1 + l) -1) * y ** (p * (j + r*s))
971
+ assert N0 <= self._N0
972
+ frobij = self._frob_sparse(i, j, N0)
973
+ # recall
974
+ # Frob(x^i dx/y^j) / dx
975
+ # = p * x ** (p * (i+1) - 1) * y ** (j*p)
976
+ # * = \sum_{s = 0} ^{N0-1}
977
+ # \sum_{l = 0} ^(d*s)
978
+ # D_{j, s} * Frobpow[s][l] * x ** (p ** l) y ** (r * p ** s)
979
+ # H represents H(x) * y^(-p**s) s /dx
980
+ # the entry (l, s) of frobij
981
+ # corresponds to the monomial (p * (i + 1 + l) -1, p * -(j + r*s))
982
+ d = self._d
983
+ r = self._r
984
+ p = self._p
985
+ H = vector(self._Zq, d - 1)
986
+ k = (p * j) // r
987
+ s0 = (p * j) % r
988
+
989
+ for s in reversed(range(N0)):
990
+ if self._sqrtp:
991
+ # (i + 1) <= d
992
+ self._initialize_fat_horizontal(
993
+ p * j + p * r * s, d * s + (d - 2) + 1
994
+ ) # d * (s + 1) )
995
+ # G represents G(x) * x^(p ** l - 1) y^(-p(j + r*s)) /dx
996
+ G = vector(self._Zq, d)
997
+ for ell in reversed(range(1, d * s + (i + 1) + 1)):
998
+ if ell >= (i + 1):
999
+ G[0] += frobij[ell - (i + 1), s]
1000
+ G = self._reduce_vector_horizontal(G, p * ell - 1, p * j + p * r * s, p)
1001
+ assert G[0] == 0
1002
+ H += vector(G.list()[1:])
1003
+ if s > 0:
1004
+ # y^(-p(j + r*s)) --- > y^(-p(j + r*(s-1)))
1005
+ H = self._reduce_vector_vertical(H, s0, k + p * s, p)
1006
+ # H represents
1007
+ # H(x) y^-p*j = H(x) y^-(k*r + s0)
1008
+ # now we reduce the pole order to s0 + r*epsilon, where s0 = p *j % r
1009
+ while k > self._epsilon:
1010
+ steps = p if k - self._epsilon > p else k - self._epsilon
1011
+ H = self._reduce_vector_vertical(H, s0, k, steps)
1012
+ k -= steps
1013
+ assert k == self._epsilon
1014
+ H = [self._Qq(elt).add_bigoh(N0) for elt in H]
1015
+ return matrix(H).transpose()
1016
+
1017
+ @cached_method
1018
+ def frobenius_matrix(self, N=None):
1019
+ """
1020
+ Compute `p`-adic Frobenius matrix to precision `p^N`.
1021
+
1022
+ If `N` not supplied, a default value is selected, which is the minimum
1023
+ needed to recover the charpoly unambiguously.
1024
+
1025
+ EXAMPLES::
1026
+
1027
+ sage: p = 107
1028
+ sage: x = PolynomialRing(GF(p), "x").gen()
1029
+ sage: CyclicCover(2, x^5 + x).frobenius_matrix()
1030
+ [ O(107^2) 89*107 + O(107^2) O(107^2) O(107^2)]
1031
+ [ 89*107 + O(107^2) O(107^2) O(107^2) O(107^2)]
1032
+ [ O(107^2) O(107^2) O(107^2) 105 + 5*107 + O(107^2)]
1033
+ [ O(107^2) O(107^2) 89 + 53*107 + O(107^2) O(107^2)]
1034
+ sage: CyclicCover(2, 3*x^5 + x).frobenius_matrix()
1035
+ [ O(107^2) 14*107 + O(107^2) O(107^2) O(107^2)]
1036
+ [ 69*107 + O(107^2) O(107^2) O(107^2) O(107^2)]
1037
+ [ O(107^2) O(107^2) O(107^2) 61 + 58*107 + O(107^2)]
1038
+ [ O(107^2) O(107^2) 69 + 53*107 + O(107^2) O(107^2)]
1039
+ sage: CyclicCover(3, x^3 + x).frobenius_matrix()
1040
+ [ 0 0 O(107) O(107)]
1041
+ [ 0 0 52 + O(107) O(107)]
1042
+ [ O(107) 35 + O(107) 0 0]
1043
+ [44 + O(107) O(107) 0 0]
1044
+ sage: CyclicCover(3, 3*x^3 + x).frobenius_matrix()
1045
+ [ 0 0 O(107) O(107)]
1046
+ [ 0 0 79 + O(107) O(107)]
1047
+ [ O(107) 42 + O(107) 0 0]
1048
+ [30 + O(107) O(107) 0 0]
1049
+ """
1050
+
1051
+ def _frobenius_matrix_p(N0):
1052
+ r"""
1053
+ Compute the matrix that represents the p-power Frobenius
1054
+ """
1055
+ assert self._init_frobQ
1056
+
1057
+ m = matrix(self._Qq, (self._d - 1) * (self._r - 1))
1058
+
1059
+ # Want to build m, "slice by slice" using the output of _frob
1060
+ for j in range(1, self._r):
1061
+ s0 = (j * self._p) % self._r
1062
+ for i in range(self._d - 1):
1063
+ m[(s0 - 1) * (self._d - 1):s0 * (self._d - 1),
1064
+ i + (j - 1) * (self._d - 1),
1065
+ ] = self._frob(i, j + self._epsilon * self._r, N0)
1066
+ return m
1067
+
1068
+ self._init_frob(N)
1069
+ FrobP = _frobenius_matrix_p(self._N0)
1070
+ assert N == self._N0 or N is None
1071
+ if self._n == 1:
1072
+ return FrobP
1073
+ else:
1074
+ current = FrobP
1075
+ total = FrobP
1076
+ for i in range(self._n - 1):
1077
+ current = matrix(
1078
+ [[entry.frobenius() for entry in row] for row in current]
1079
+ )
1080
+ total = total * current
1081
+ total = matrix([[elt.add_bigoh(self._N0) for elt in row] for row in total])
1082
+ return total
1083
+
1084
+ @cached_method
1085
+ def frobenius_polynomial(self):
1086
+ r"""
1087
+ Return the characteristic polynomial of Frobenius.
1088
+
1089
+ EXAMPLES:
1090
+
1091
+ Hyperelliptic curves::
1092
+
1093
+ sage: p = 11
1094
+ sage: x = PolynomialRing(GF(p), "x").gen()
1095
+ sage: f = x^7 + 4*x^2 + 10*x + 4
1096
+ sage: CyclicCover(2, f).frobenius_polynomial() == \
1097
+ ....: HyperellipticCurve(f).frobenius_polynomial()
1098
+ True
1099
+ sage: f = 2*x^5 + 4*x^3 + x^2 + 2*x + 1
1100
+ sage: CyclicCover(2, f).frobenius_polynomial() == \
1101
+ ....: HyperellipticCurve(f).frobenius_polynomial()
1102
+ True
1103
+ sage: f = 2*x^6 + 4*x^4 + x^3 + 2*x^2 + x
1104
+ sage: CyclicCover(2, f).frobenius_polynomial() == \
1105
+ ....: HyperellipticCurve(f).frobenius_polynomial()
1106
+ True
1107
+ sage: p = 1117
1108
+ sage: x = PolynomialRing(GF(p), "x").gen()
1109
+ sage: f = x^9 + 4*x^2 + 10*x + 4
1110
+ sage: P1 = CyclicCover(2, f).frobenius_polynomial()
1111
+ sage: P2 = HyperellipticCurve(f).frobenius_polynomial()
1112
+ sage: P1 == P2 # long time
1113
+ True
1114
+ sage: f = 2*x^5 + 4*x^3 + x^2 + 2*x + 1
1115
+ sage: CyclicCover(2, f).frobenius_polynomial() == \
1116
+ ....: HyperellipticCurve(f).frobenius_polynomial()
1117
+ True
1118
+
1119
+ Superelliptic curves::
1120
+
1121
+ sage: p = 11
1122
+ sage: x = PolynomialRing(GF(p), "x").gen()
1123
+ sage: CyclicCover(3, x^4 + 4*x^3 + 9*x^2 + 3*x + 1).frobenius_polynomial()
1124
+ x^6 + 21*x^4 + 231*x^2 + 1331
1125
+ sage: CyclicCover(4, x^3 + x + 1).frobenius_polynomial()
1126
+ x^6 + 2*x^5 + 11*x^4 + 121*x^2 + 242*x + 1331
1127
+ sage: p = 4999
1128
+ sage: x = PolynomialRing(GF(p),"x").gen()
1129
+ sage: CyclicCover(4, x^3 - 1).frobenius_polynomial() == \
1130
+ ....: CyclicCover(3, x^4 + 1).frobenius_polynomial()
1131
+ True
1132
+ sage: CyclicCover(3, x^4 + 4*x^3 + 9*x^2 + 3*x + 1).frobenius_polynomial()
1133
+ x^6 + 180*x^5 + 20988*x^4 + 1854349*x^3 + 104919012*x^2 + 4498200180*x + 124925014999
1134
+ sage: CyclicCover(4, x^5 + x + 1).frobenius_polynomial()
1135
+ x^12 - 64*x^11 + 5018*x^10 - 488640*x^9 + 28119583*x^8 - 641791616*x^7
1136
+ + 124245485932*x^6 - 3208316288384*x^5 + 702708407289583*x^4 - 61043359329111360*x^3
1137
+ + 3133741752599645018*x^2 - 199800079984001599936*x + 15606259372500374970001
1138
+
1139
+ sage: h = PolynomialRing(GF(1129), 'x')([-1] + [0]*(5-1) + [1])
1140
+ sage: CyclicCover(11, h).frobenius_polynomial() # long time
1141
+ x^40 + 7337188909826596*x^30 + 20187877911930897108199045855206*x^20
1142
+ + 24687045654725446027864774006541463602997309796*x^10
1143
+ + 11320844849639649951608809973589776933203136765026963553258401
1144
+
1145
+ sage: h = PolynomialRing(GF(1009^2), 'x')([-1] + [0]*(5-1) + [1])
1146
+ sage: CyclicCover(3, h).frobenius_polynomial() # long time
1147
+ x^8 + 532*x^7 - 2877542*x^6 - 242628176*x^5 + 4390163797795*x^4 - 247015136050256*x^3
1148
+ - 2982540407204025062*x^2 + 561382189105547134612*x + 1074309286591662654798721
1149
+
1150
+ A non-monic example checking that :issue:`29015` is fixed::
1151
+
1152
+ sage: a = 3
1153
+ sage: K.<s> = GF(83^3);
1154
+ sage: R.<x> = PolynomialRing(K)
1155
+ sage: h = s*x^4 + x*3 + 8
1156
+ sage: C = CyclicCover(a, h)
1157
+ sage: C.frobenius_polynomial()
1158
+ x^6 + 1563486*x^4 + 893980969482*x^2 + 186940255267540403
1159
+
1160
+ Non-superelliptic curves::
1161
+
1162
+ sage: p = 13
1163
+ sage: x = PolynomialRing(GF(p), "x").gen()
1164
+ sage: C = CyclicCover(4, x^4 + 1)
1165
+ sage: C.frobenius_polynomial()
1166
+ x^6 - 6*x^5 + 3*x^4 + 60*x^3 + 39*x^2 - 1014*x + 2197
1167
+ sage: R.<t> = PowerSeriesRing(Integers())
1168
+ sage: C.projective_closure().zeta_series(2, t)
1169
+ 1 + 8*t + 102*t^2 + O(t^3)
1170
+ sage: C.frobenius_polynomial().reverse()(t)/((1-t)*(1-p*t)) + O(t^5)
1171
+ 1 + 8*t + 102*t^2 + 1384*t^3 + 18089*t^4 + O(t^5)
1172
+
1173
+ sage: x = PolynomialRing(GF(11), "x").gen()
1174
+ sage: CyclicCover(4, x^6 - 11*x^3 + 70*x^2 - x + 961).frobenius_polynomial() # long time
1175
+ x^14 + 14*x^12 + 287*x^10 + 3025*x^8 + 33275*x^6 + 381997*x^4 + 2254714*x^2 + 19487171
1176
+ sage: x = PolynomialRing(GF(4999), "x").gen()
1177
+ sage: CyclicCover(4, x^6 - 11*x^3 + 70*x^2 - x + 961).frobenius_polynomial() # long time
1178
+ x^14 - 4*x^13 - 2822*x^12 - 30032*x^11 + 37164411*x^10 - 152369520*x^9
1179
+ + 54217349361*x^8 - 1021791160888*x^7 + 271032529455639*x^6 - 3807714457169520*x^5
1180
+ + 4642764601604000589*x^4 - 18754988504199390032*x^3 - 8809934776794570547178*x^2
1181
+ - 62425037490001499880004*x + 78015690603129374475034999
1182
+
1183
+ sage: p = 11
1184
+ sage: x = PolynomialRing(GF(p), "x").gen()
1185
+ sage: CyclicCover(3, 5*x^3 - 5*x + 13).frobenius_polynomial()
1186
+ x^2 + 11
1187
+ sage: CyclicCover(3, x^6 + x^4 - x^3 + 2*x^2 - x - 1).frobenius_polynomial()
1188
+ x^8 + 32*x^6 + 462*x^4 + 3872*x^2 + 14641
1189
+ sage: p = 4999
1190
+ sage: x = PolynomialRing(GF(p), "x").gen()
1191
+ sage: CyclicCover(3, 5*x^3 - 5*x + 13).frobenius_polynomial()
1192
+ x^2 - 47*x + 4999
1193
+ sage: CyclicCover(3, x^6 + x^4 - x^3 + 2*x^2 - x - 1).frobenius_polynomial()
1194
+ x^8 + 122*x^7 + 4594*x^6 - 639110*x^5 - 82959649*x^4 - 3194910890*x^3
1195
+ + 114804064594*x^2 + 15240851829878*x + 624500149980001
1196
+
1197
+ sage: p = 11
1198
+ sage: x = PolynomialRing(GF(p), "x").gen()
1199
+ sage: CyclicCover(5, x^5 + x).frobenius_polynomial() # long time
1200
+ x^12 + 4*x^11 + 22*x^10 + 108*x^9 + 503*x^8 + 1848*x^7 + 5588*x^6 + 20328*x^5
1201
+ + 60863*x^4 + 143748*x^3 + 322102*x^2 + 644204*x + 1771561
1202
+ sage: CyclicCover(5, 2*x^5 + x).frobenius_polynomial() # long time
1203
+ x^12 - 9*x^11 + 42*x^10 - 108*x^9 - 47*x^8 + 1782*x^7 - 8327*x^6 + 19602*x^5
1204
+ - 5687*x^4 - 143748*x^3 + 614922*x^2 - 1449459*x + 1771561
1205
+ sage: p = 49999
1206
+ sage: x = PolynomialRing(GF(p), "x").gen()
1207
+ sage: CyclicCover(5, x^5 + x).frobenius_polynomial() # long time
1208
+ x^12 + 299994*x^10 + 37498500015*x^8 + 2499850002999980*x^6
1209
+ + 93742500224997000015*x^4 + 1874812507499850001499994*x^2
1210
+ + 15623125093747500037499700001
1211
+ sage: CyclicCover(5, 2*x^5 + x).frobenius_polynomial() # long time
1212
+ x^12 + 299994*x^10 + 37498500015*x^8 + 2499850002999980*x^6
1213
+ + 93742500224997000015*x^4 + 1874812507499850001499994*x^2
1214
+ + 15623125093747500037499700001
1215
+
1216
+
1217
+ TESTS::
1218
+
1219
+ sage: for _ in range(5): # long time
1220
+ ....: fail = False
1221
+ ....: p = random_prime(500, lbound=5)
1222
+ ....: for i in range(1, 4):
1223
+ ....: F = GF((p, i))
1224
+ ....: Fx = PolynomialRing(F, 'x')
1225
+ ....: b = F.random_element()
1226
+ ....: while b == 0:
1227
+ ....: b = F.random_element()
1228
+ ....: E = EllipticCurve(F, [0, b])
1229
+ ....: C1 = CyclicCover(3, Fx([-b, 0, 1]))
1230
+ ....: C2 = CyclicCover(2, Fx([b, 0, 0, 1]))
1231
+ ....: frob = [elt.frobenius_polynomial() for elt in [E, C1, C2]]
1232
+ ....: if len(set(frob)) != 1:
1233
+ ....: E
1234
+ ....: C1
1235
+ ....: C2
1236
+ ....: frob
1237
+ ....: fail = True
1238
+ ....: break
1239
+ ....: if fail:
1240
+ ....: break
1241
+ ....: else:
1242
+ ....: True
1243
+ True
1244
+ """
1245
+ self._init_frob()
1246
+ F = self.frobenius_matrix(self._N0)
1247
+
1248
+ def _denominator():
1249
+ R = PolynomialRing(ZZ, "T")
1250
+ T = R.gen()
1251
+ denom = R(1)
1252
+ lc = self._f.list()[-1]
1253
+ if lc == 1: # MONIC
1254
+ for i in range(2, self._delta + 1):
1255
+ if self._delta % i == 0:
1256
+ phi = euler_phi(i)
1257
+ G = IntegerModRing(i)
1258
+ ki = G(self._q).multiplicative_order()
1259
+ denom = denom * (T ** ki - 1) ** (phi // ki)
1260
+ return denom
1261
+ else: # Non-monic
1262
+ x = PolynomialRing(self._Fq, "x").gen()
1263
+ f = x ** self._delta - lc
1264
+ L = f.splitting_field("a")
1265
+ roots = [r for r, _ in f.change_ring(L).roots()]
1266
+ roots_dict = {r: i for i, r in enumerate(roots)}
1267
+ rootsfrob = [L.frobenius_endomorphism(self._Fq.degree())(r) for r in roots]
1268
+ m = zero_matrix(len(roots))
1269
+ for i, r in enumerate(roots):
1270
+ m[i, roots_dict[rootsfrob[i]]] = 1
1271
+ return R(R(m.characteristic_polynomial()) // (T - 1))
1272
+
1273
+ denom = _denominator()
1274
+ R = PolynomialRing(ZZ, "x")
1275
+
1276
+ if self._nodenominators:
1277
+ min_val = 0
1278
+ else:
1279
+ # are there any denominators in F?
1280
+ min_val = min(self._Qq(elt).valuation() for row in F.rows() for elt in row)
1281
+
1282
+ if min_val >= 0:
1283
+ prec = _N0_nodenominators(self._p, self._genus, self._n)
1284
+ charpoly_prec = [prec + i for i in reversed(range(1, self._genus + 1))] + [
1285
+ prec
1286
+ ] * (self._genus + 1)
1287
+ cp = charpoly_frobenius(F, charpoly_prec, self._p, 1, self._n, denom.list())
1288
+ return R(cp)
1289
+ else:
1290
+ cp = F.charpoly().reverse()
1291
+ denom = denom.reverse()
1292
+ PS = PowerSeriesRing(self._Zp, "T")
1293
+ cp = PS(cp) / PS(denom)
1294
+ cp = cp.padded_list(self._genus + 1)
1295
+ cpZZ = [None for _ in range(2 * self._genus + 1)]
1296
+ cpZZ[0] = 1
1297
+ cpZZ[-1] = self._p ** self._genus
1298
+ for i in range(1, self._genus + 1):
1299
+ cmod = cp[i]
1300
+ bound = binomial(2 * self._genus, i) * self._p ** (i * self._n * 0.5)
1301
+ localmod = self._p ** (ceil(log(bound, self._p)))
1302
+ c = cmod.lift() % localmod
1303
+ if c > bound:
1304
+ c = -(-cmod.lift() % localmod)
1305
+ cpZZ[i] = c
1306
+ if i != self._genus + 1:
1307
+ cpZZ[2 * self._genus - i] = c * self._p ** (self._genus - i)
1308
+ cpZZ.reverse()
1309
+ return R(cpZZ)