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,592 @@
1
+ # sage_setup: distribution = sagemath-schemes
2
+ r"""
3
+ Testing whether elliptic curves over number fields are `\QQ`-curves
4
+
5
+ AUTHORS:
6
+
7
+ - John Cremona (February 2021)
8
+
9
+ The code here implements the algorithm of Cremona and Najman presented
10
+ in [CrNa2020]_.
11
+ """
12
+ ##############################################################################
13
+ # Copyright (C) 2020-2021 John Cremona <john.cremona@gmail.com>
14
+ #
15
+ # Distributed under the terms of the GNU General Public License (GPL)
16
+ #
17
+ # This code is distributed in the hope that it will be useful,
18
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
19
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20
+ # General Public License for more details.
21
+ #
22
+ # The full text of the GPL is available at:
23
+ #
24
+ # https://www.gnu.org/licenses/
25
+ ##############################################################################
26
+ from sage.rings.rational_field import QQ
27
+ from sage.rings.polynomial.polynomial_ring import polygen
28
+
29
+
30
+ def is_Q_curve(E, maxp=100, certificate=False, verbose=False):
31
+ r"""
32
+ Return whether ``E`` is a `\QQ`-curve, with optional certificate.
33
+
34
+ INPUT:
35
+
36
+ - ``E`` -- elliptic curve over a number field
37
+
38
+ - ``maxp`` -- integer (default: 100); bound on primes used for checking
39
+ necessary local conditions. The result will not depend on this,
40
+ but using a larger value may return ``False`` faster.
41
+
42
+ - ``certificate`` -- boolean (default: ``False``); if ``True`` then a
43
+ second value is returned giving a certificate for the
44
+ `\QQ`-curve property
45
+
46
+ OUTPUT:
47
+
48
+ If ``certificate`` is ``False``: either ``True`` (if `E` is a
49
+ `\QQ`-curve), or ``False``.
50
+
51
+ If ``certificate`` is ``True``: a tuple consisting of a boolean
52
+ flag as before and a certificate, defined as follows:
53
+
54
+ - when the flag is ``True``, so `E` is a `\QQ`-curve:
55
+
56
+ - either {'CM':`D`} where `D` is a negative discriminant, when
57
+ `E` has potential CM with discriminant `D`;
58
+
59
+ - otherwise {'CM': `0`, 'core_poly': `f`, 'rho': `\rho`, 'r':
60
+ `r`, 'N': `N`}, when `E` is a non-CM `\QQ`-curve, where the
61
+ core polynomial `f` is an irreducible monic polynomial over
62
+ `QQ` of degree `2^\rho`, all of whose roots are
63
+ `j`-invariants of curves isogenous to `E`, the core level
64
+ `N` is a square-free integer with `r` prime factors which is
65
+ the LCM of the degrees of the isogenies between these
66
+ conjugates. For example, if there exists a curve `E'`
67
+ isogenous to `E` with `j(E')=j\in\QQ`, then the certificate
68
+ is {'CM':0, 'r':0, 'rho':0, 'core_poly': x-j, 'N':1}.
69
+
70
+ - when the flag is ``False``, so `E` is not a `\QQ`-curve, the
71
+ certificate is a prime `p` such that the reductions of `E` at
72
+ the primes dividing `p` are inconsistent with the property of
73
+ being a `\QQ`-curve. See the ALGORITHM section for details.
74
+
75
+ ALGORITHM:
76
+
77
+ See [CrNa2020]_ for details.
78
+
79
+ 1. If `E` has rational `j`-invariant, or has CM, then return
80
+ ``True``.
81
+
82
+ 2. Replace `E` by a curve defined over `K=\QQ(j(E))`. Let `N` be
83
+ the conductor norm.
84
+
85
+ 3. For all primes `p\mid N` check that the valuations of `j` at
86
+ all `P\mid p` are either all negative or all nonnegative; if not,
87
+ return ``False``.
88
+
89
+ 4. For `p\le maxp`, `p\not\mid N`, check that either `E` is
90
+ ordinary mod `P` for all `P\mid p`, or `E` is supersingular mod
91
+ `P` for all `P\mid p`; if neither, return ``False``. If all are
92
+ ordinary, check that the integers `a_P(E)^2-4N(P)` have the same
93
+ square-free part; if not, return ``False``.
94
+
95
+ 5. Compute the `K`-isogeny class of `E` using the "heuristic"
96
+ option (which is faster, but not guaranteed to be complete).
97
+ Check whether the set of `j`-invariants of curves in the class of
98
+ `2`-power degree contains a complete Galois orbit. If so, return
99
+ ``True``.
100
+
101
+ 6. Otherwise repeat step 4 for more primes, and if still
102
+ undecided, repeat Step 5 without the "heuristic" option, to get
103
+ the complete `K`-isogeny class (which will probably be no bigger
104
+ than before). Now return ``True`` if the set of `j`-invariants of
105
+ curves in the class contains a complete Galois orbit, otherwise
106
+ return ``False``.
107
+
108
+ EXAMPLES:
109
+
110
+ A non-CM curve over `\QQ` and a CM curve over `\QQ` are both
111
+ trivially `\QQ`-curves::
112
+
113
+ sage: from sage.schemes.elliptic_curves.Qcurves import is_Q_curve
114
+ sage: E = EllipticCurve([1,2,3,4,5])
115
+ sage: flag, cert = is_Q_curve(E, certificate=True)
116
+ sage: flag
117
+ True
118
+ sage: cert
119
+ {'CM': 0, 'N': 1, 'core_poly': x, 'r': 0, 'rho': 0}
120
+
121
+ sage: E = EllipticCurve(j=8000)
122
+ sage: flag, cert = is_Q_curve(E, certificate=True)
123
+ sage: flag
124
+ True
125
+ sage: cert
126
+ {'CM': -8}
127
+
128
+ A non-`\QQ`-curve over a quartic field. The local data at bad
129
+ primes above `3` is inconsistent::
130
+
131
+ sage: from sage.schemes.elliptic_curves.Qcurves import is_Q_curve
132
+ sage: R.<x> = PolynomialRing(QQ)
133
+ sage: K.<a> = NumberField(R([3, 0, -5, 0, 1])) # needs sage.rings.number_field
134
+ sage: E = EllipticCurve([K([-3,-4,1,1]), K([4,-1,-1,0]), K([-2,0,1,0]), # needs sage.rings.number_field
135
+ ....: K([-621,778,138,-178]), K([9509,2046,-24728,10380])])
136
+ sage: is_Q_curve(E, certificate=True, verbose=True) # needs sage.rings.number_field
137
+ Checking whether Elliptic Curve defined by y^2 + (a^3+a^2-4*a-3)*x*y + (a^2-2)*y = x^3 + (-a^2-a+4)*x^2 + (-178*a^3+138*a^2+778*a-621)*x + (10380*a^3-24728*a^2+2046*a+9509) over Number Field in a with defining polynomial x^4 - 5*x^2 + 3 is a Q-curve
138
+ No: inconsistency at the 2 primes dividing 3
139
+ - potentially multiplicative: [True, False]
140
+ (False, 3)
141
+
142
+ A non-`\QQ`-curve over a quadratic field. The local data at bad
143
+ primes is consistent, but the local test at good primes above `13`
144
+ is not::
145
+
146
+ sage: K.<a> = NumberField(R([-10, 0, 1])) # needs sage.rings.number_field
147
+ sage: E = EllipticCurve([K([0,1]), K([-1,-1]), K([0,0]), # needs sage.rings.number_field
148
+ ....: K([-236,40]), K([-1840,464])])
149
+ sage: is_Q_curve(E, certificate=True, verbose=True) # needs sage.rings.number_field
150
+ Checking whether Elliptic Curve defined by y^2 + a*x*y = x^3 + (-a-1)*x^2 + (40*a-236)*x + (464*a-1840) over Number Field in a with defining polynomial x^2 - 10 is a Q-curve
151
+ Applying local tests at good primes above p<=100
152
+ No: inconsistency at the 2 ordinary primes dividing 13
153
+ - Frobenius discriminants mod squares: [-1, -3]
154
+ No: local test at p=13 failed
155
+ (False, 13)
156
+
157
+ A quadratic `\QQ`-curve with CM discriminant `-15` (`j`-invariant not in `\QQ`)::
158
+
159
+ sage: from sage.schemes.elliptic_curves.Qcurves import is_Q_curve
160
+ sage: R.<x> = PolynomialRing(QQ)
161
+ sage: K.<a> = NumberField(R([-1, -1, 1])) # needs sage.rings.number_field
162
+ sage: E = EllipticCurve([K([1,0]), K([-1,0]), K([0,1]), K([0,-2]), K([0,1])]) # needs sage.rings.number_field
163
+ sage: is_Q_curve(E, certificate=True, verbose=True) # needs sage.rings.number_field
164
+ Checking whether Elliptic Curve defined by y^2 + x*y + a*y = x^3 + (-1)*x^2 + (-2*a)*x + a over Number Field in a with defining polynomial x^2 - x - 1 is a Q-curve
165
+ Yes: E is CM (discriminant -15)
166
+ (True, {'CM': -15})
167
+
168
+ An example over `\QQ(\sqrt{2},\sqrt{3})`. The `j`-invariant is in
169
+ `\QQ(\sqrt{6})`, so computations will be done over that field, and
170
+ in fact there is an isogenous curve with rational `j`, so we have
171
+ a so-called rational `\QQ`-curve::
172
+
173
+ sage: # needs sage.rings.number_field
174
+ sage: K.<a> = NumberField(R([1, 0, -4, 0, 1]))
175
+ sage: E = EllipticCurve([K([-2,-4,1,1]), K([0,1,0,0]), K([0,1,0,0]),
176
+ ....: K([-4780,9170,1265,-2463]),
177
+ ....: K([163923,-316598,-43876,84852])])
178
+ sage: flag, cert = is_Q_curve(E, certificate=True)
179
+ sage: flag
180
+ True
181
+ sage: cert
182
+ {'CM': 0, 'N': 1, 'core_degs': [1], 'core_poly': x - 85184/3, 'r': 0, 'rho': 0}
183
+
184
+ Over the same field, a so-called strict `\QQ`-curve which is not
185
+ isogenous to one with rational `j`, but whose core field is
186
+ quadratic. In fact the isogeny class over `K` consists of `6`
187
+ curves, four with conjugate quartic `j`-invariants and `2` with
188
+ quadratic conjugate `j`-invariants in `\QQ(\sqrt{3})` (but which
189
+ are not base-changes from the quadratic subfield)::
190
+
191
+ sage: # needs sage.rings.number_field
192
+ sage: E = EllipticCurve([K([0,-3,0,1]), K([1,4,0,-1]), K([0,0,0,0]),
193
+ ....: K([-2,-16,0,4]), K([-19,-32,4,8])])
194
+ sage: flag, cert = is_Q_curve(E, certificate=True)
195
+ sage: flag
196
+ True
197
+ sage: cert
198
+ {'CM': 0,
199
+ 'N': 2,
200
+ 'core_degs': [1, 2],
201
+ 'core_poly': x^2 - 840064*x + 1593413632,
202
+ 'r': 1,
203
+ 'rho': 1}
204
+
205
+ TESTS::
206
+
207
+ sage: E = EllipticCurve([GF(5)(t) for t in [2,3,5,7,11]])
208
+ sage: is_Q_curve(E)
209
+ Traceback (most recent call last):
210
+ ...
211
+ TypeError: Elliptic Curve defined by ... must be an elliptic curve
212
+ defined over a number field
213
+ """
214
+ from sage.rings.number_field.number_field_base import NumberField
215
+
216
+ if verbose:
217
+ print(f"Checking whether {E} is a Q-curve")
218
+
219
+ try:
220
+ assert isinstance(E.base_field(), NumberField)
221
+ except (AttributeError, AssertionError):
222
+ raise TypeError(f"{E} must be an elliptic curve defined over a number field")
223
+
224
+ from sage.rings.integer_ring import ZZ
225
+ from sage.arith.functions import lcm
226
+ from sage.libs.pari import pari
227
+ from sage.rings.number_field.number_field import NumberField
228
+ from sage.schemes.elliptic_curves.constructor import EllipticCurve
229
+ from sage.schemes.elliptic_curves.cm import cm_j_invariants_and_orders, is_cm_j_invariant
230
+
231
+ # Step 1
232
+
233
+ # all curves with rational j-invariant are Q-curves:
234
+ jE = E.j_invariant()
235
+ if jE in QQ:
236
+ if verbose:
237
+ print("Yes: j(E) is in QQ")
238
+ if certificate:
239
+ # test for CM
240
+ for d, f, j in cm_j_invariants_and_orders(QQ):
241
+ if jE == j:
242
+ return True, {'CM': d * f**2}
243
+ # else not CM
244
+ return True, {'CM': ZZ(0), 'r': ZZ(0), 'rho': ZZ(0), 'N': ZZ(1), 'core_poly': polygen(QQ)}
245
+ else:
246
+ return True
247
+
248
+ # CM curves are Q-curves:
249
+ flag, df = is_cm_j_invariant(jE)
250
+ if flag:
251
+ d, f = df
252
+ D = d * f**2
253
+ if verbose:
254
+ print("Yes: E is CM (discriminant {})".format(D))
255
+ if certificate:
256
+ return True, {'CM': D}
257
+ else:
258
+ return True
259
+
260
+ # Step 2: replace E by a curve defined over Q(j(E)):
261
+
262
+ K = E.base_field()
263
+ jpoly = jE.minpoly()
264
+ if jpoly.degree() < K.degree():
265
+ if verbose:
266
+ print("switching to smaller base field: j's minpoly is {}".format(jpoly))
267
+ f = pari(jpoly).polredbest().sage({'x': jpoly.parent().gen()})
268
+ K2 = NumberField(f, 'b')
269
+ jE = jpoly.roots(K2)[0][0]
270
+ if verbose:
271
+ print("New j is {} over {}, with minpoly {}".format(jE, K2, jE.minpoly()))
272
+ # assert jE.minpoly() == jpoly
273
+ E = EllipticCurve(j=jE)
274
+ K = K2
275
+ if verbose:
276
+ print("New test curve is {}".format(E))
277
+
278
+ # Step 3: check primes of bad reduction
279
+
280
+ NN = E.conductor().norm()
281
+ for p in NN.support():
282
+ Plist = K.primes_above(p)
283
+ if len(Plist) < 2:
284
+ continue
285
+ # pot_mult = potential multiplicative reduction
286
+ pot_mult = [jE.valuation(P) < 0 for P in Plist]
287
+ consistent = all(pot_mult) or not any(pot_mult)
288
+ if not consistent:
289
+ if verbose:
290
+ print(f"No: inconsistency at the {len(Plist)} primes dividing {p}")
291
+ print(" - potentially multiplicative: {}".format(pot_mult))
292
+ if certificate:
293
+ return False, p
294
+ else:
295
+ return False
296
+
297
+ # Step 4 check: primes P of good reduction above p<=B:
298
+
299
+ if verbose:
300
+ print("Applying local tests at good primes above p<={}".format(maxp))
301
+
302
+ res4, p = Step4Test(E, B=maxp, oldB=0, verbose=verbose)
303
+ if not res4:
304
+ if verbose:
305
+ print("No: local test at p={} failed".format(p))
306
+ if certificate:
307
+ return False, p
308
+ else:
309
+ return False
310
+
311
+ if verbose:
312
+ print("...all local tests pass for p<={}".format(maxp))
313
+
314
+ # Step 5: compute the (partial) K-isogeny class of E and test the
315
+ # set of j-invariants in the class:
316
+
317
+ C = E.isogeny_class(algorithm='heuristic', minimal_models=False)
318
+ jC = [E2.j_invariant() for E2 in C]
319
+ centrejpols = conjugacy_test(jC, verbose=verbose)
320
+ if centrejpols:
321
+ if verbose:
322
+ print("Yes: the isogeny class contains a complete conjugacy class of j-invariants")
323
+ if certificate:
324
+ for f in centrejpols:
325
+ rho = f.degree().valuation(2)
326
+ centre_indices = [i for i, j in enumerate(jC) if f(j) == 0]
327
+ M = C.matrix()
328
+ core_degs = [M[centre_indices[0], i] for i in centre_indices]
329
+ level = lcm(core_degs)
330
+ if level.is_squarefree():
331
+ r = len(level.prime_divisors())
332
+ cert = {'CM': ZZ(0), 'core_poly': f, 'rho': rho,
333
+ 'r': r, 'N': level, 'core_degs': core_degs}
334
+ return True, cert
335
+ print("No central curve found")
336
+ else:
337
+ return True
338
+
339
+ # Now we are undecided. This can happen if either (1) E is not a
340
+ # Q-curve but we did not use enough primes in Step 4 to detect
341
+ # this, or (2) E is a Q-curve but in Step 5 we did not compute the
342
+ # complete isogeny class. Case (2) is most unlikely since the
343
+ # heuristic bound used in computing isogeny classes means that we
344
+ # have all isogenous curves linked to E by an isogeny of degree
345
+ # supported on primes<1000.
346
+
347
+ # We first rerun Step 4 with a larger bound.
348
+
349
+ xmaxp = 10 * maxp
350
+ if verbose:
351
+ print("Undecided after first round, so we apply more local tests, up to {}".format(xmaxp))
352
+
353
+ res4, p = Step4Test(E, B=xmaxp, oldB=maxp, verbose=verbose)
354
+ if not res4:
355
+ if verbose:
356
+ print("No: local test at p={} failed".format(p))
357
+ if certificate:
358
+ return False, p
359
+ else:
360
+ return False
361
+
362
+ # Now we rerun Step 5 using a rigorous computation of the complete
363
+ # isogeny class. This will probably contain no more curves than
364
+ # before, in which case -- since we already tested that the set of
365
+ # j-invariants does not contain a complete Galois conjugacy class
366
+ # -- we can deduce that E is not a Q-curve.
367
+
368
+ if verbose:
369
+ print("...all local tests pass for p<={}".format(xmaxp))
370
+ print("We now compute the complete isogeny class...")
371
+
372
+ Cfull = E.isogeny_class(minimal_models=False)
373
+ jCfull = [E2.j_invariant() for E2 in Cfull]
374
+
375
+ if len(jC) == len(jCfull):
376
+ if verbose:
377
+ print("...and find that we already had the complete class:so No")
378
+ if certificate:
379
+ return False, 0
380
+ else:
381
+ return False
382
+ if verbose:
383
+ print("...and find that the class contains {} curves, not just the {} we computed originally".format(len(jCfull), len(jC)))
384
+ centrejpols = conjugacy_test(jCfull, verbose=verbose)
385
+ if cert:
386
+ if verbose:
387
+ print("Yes: the isogeny class contains a complete conjugacy class of j-invariants")
388
+ if certificate:
389
+ return True, centrejpols
390
+ else:
391
+ return True
392
+ if verbose:
393
+ print("No: the isogeny class does *not* contain a complete conjugacy class of j-invariants")
394
+ if certificate:
395
+ return False, 0
396
+ else:
397
+ return False
398
+
399
+
400
+ def Step4Test(E, B, oldB=0, verbose=False):
401
+ r"""
402
+ Apply local Q-curve test to E at all primes up to B.
403
+
404
+ INPUT:
405
+
406
+ - ``E`` -- elliptic curve defined over a number field
407
+
408
+ - ``B`` -- integer; upper bound on primes to test
409
+
410
+ - ``oldB`` -- integer (default: 0); lower bound on primes to test
411
+
412
+ - ``verbose`` -- boolean (default: ``False``); verbosity flag
413
+
414
+ OUTPUT:
415
+
416
+ Either (``False``, `p`), if the local test at `p` proves that `E`
417
+ is not a `\QQ`-curve, or (``True``, `0`) if all local tests at
418
+ primes between ``oldB`` and ``B`` fail to prove that `E` is not a
419
+ `\QQ`-curve.
420
+
421
+ ALGORITHM (see [CrNa2020]_ for details):
422
+
423
+ This local test at `p` only applies if `E` has good reduction at
424
+ all of the primes lying above `p` in the base field `K` of `E`. It
425
+ tests whether (1) `E` is either ordinary at all `P\mid p`, or
426
+ supersingular at all; (2) if ordinary at all, it tests that the
427
+ squarefree part of `a_P^2-4N(P)` is the same for all `P\mid p`.
428
+
429
+ EXAMPLES:
430
+
431
+ A non-`\QQ`-curve over a quartic field (with LMFDB label
432
+ '4.4.8112.1-12.1-a1') fails this test at `p=13`::
433
+
434
+ sage: from sage.schemes.elliptic_curves.Qcurves import Step4Test
435
+ sage: R.<x> = PolynomialRing(QQ)
436
+ sage: K.<a> = NumberField(R([3, 0, -5, 0, 1])) # needs sage.rings.number_field
437
+ sage: E = EllipticCurve([K([-3,-4,1,1]), K([4,-1,-1,0]), K([-2,0,1,0]), # needs sage.rings.number_field
438
+ ....: K([-621,778,138,-178]), K([9509,2046,-24728,10380])])
439
+ sage: Step4Test(E, 100, verbose=True) # needs sage.rings.number_field
440
+ No: inconsistency at the 2 ordinary primes dividing 13
441
+ - Frobenius discriminants mod squares: [-3, -1]
442
+ (False, 13)
443
+
444
+ A `\QQ`-curve over a sextic field (with LMFDB label
445
+ '6.6.1259712.1-64.1-a6') passes this test for all `p<100`::
446
+
447
+ sage: from sage.schemes.elliptic_curves.Qcurves import Step4Test
448
+ sage: R.<x> = PolynomialRing(QQ)
449
+ sage: K.<a> = NumberField(R([-3, 0, 9, 0, -6, 0, 1])) # needs sage.rings.number_field
450
+ sage: E = EllipticCurve([K([1,-3,0,1,0,0]), K([5,-3,-6,1,1,0]), # needs sage.rings.number_field
451
+ ....: K([1,-3,0,1,0,0]), K([-139,-129,331,277,-76,-63]),
452
+ ....: K([2466,1898,-5916,-4582,1361,1055])])
453
+ sage: Step4Test(E, 100, verbose=True) # needs sage.rings.number_field
454
+ (True, 0)
455
+ """
456
+ from sage.arith.misc import primes
457
+ K = E.base_field()
458
+ NN = E.conductor().norm()
459
+ for p in primes(B):
460
+ if p <= oldB or p.divides(NN):
461
+ continue
462
+ Plist = K.primes_above(p)
463
+ if len(Plist) < 2:
464
+ continue
465
+
466
+ EmodP = [E.reduction(P) for P in Plist]
467
+
468
+ # (a) Check all are ordinary or all supersingular:
469
+ ordinary = [Ei.is_ordinary() for Ei in EmodP]
470
+ consistent = all(ordinary) or not any(ordinary)
471
+ if not consistent:
472
+ if verbose:
473
+ print(f"No: inconsistency at the {len(Plist)} primes dividing {p} ")
474
+ print(" - ordinary: {}".format(ordinary))
475
+ return False, p
476
+
477
+ # (b) Skip if all are supersingular:
478
+ if not ordinary[0]:
479
+ continue
480
+
481
+ # else compare a_P^2-4*N(P) which should have the same squarefree part:
482
+
483
+ discs = [(Ei.trace_of_frobenius()**2 - 4 * P.norm()).squarefree_part() for P, Ei in zip(Plist, EmodP)]
484
+ if any(d != discs[0] for d in discs[1:]):
485
+ if verbose:
486
+ print("No: inconsistency at the {} ordinary primes dividing {} ".format(len(Plist), p))
487
+ print(" - Frobenius discriminants mod squares: {}".format(discs))
488
+ return False, p
489
+ # Now we have failed to prove that E is not a Q-curve
490
+ return True, 0
491
+
492
+
493
+ def conjugacy_test(jlist, verbose=False):
494
+ r"""
495
+ Test whether a list of algebraic numbers contains a complete
496
+ conjugacy class of 2-power degree.
497
+
498
+ INPUT:
499
+
500
+ - ``jlist`` -- list of algebraic numbers in the same field
501
+
502
+ - ``verbose`` -- boolean (default: ``False``); verbosity flag
503
+
504
+ OUTPUT:
505
+
506
+ A possibly empty list of irreducible polynomials over `\QQ` of
507
+ 2-power degree all of whose roots are in the list.
508
+
509
+ EXAMPLES::
510
+
511
+ sage: # needs sage.rings.number_field
512
+ sage: from sage.schemes.elliptic_curves.Qcurves import conjugacy_test
513
+ sage: conjugacy_test([3])
514
+ [x - 3]
515
+ sage: K.<a> = QuadraticField(2)
516
+ sage: conjugacy_test([K(3), a])
517
+ [x - 3]
518
+ sage: conjugacy_test([K(3), 3 + a])
519
+ [x - 3]
520
+ sage: conjugacy_test([3 + a])
521
+ []
522
+ sage: conjugacy_test([3 + a, 3 - a])
523
+ [x^2 - 6*x + 7]
524
+ sage: x = polygen(QQ)
525
+ sage: f = x^3 - 3
526
+ sage: K.<a> = f.splitting_field()
527
+ sage: js = f.roots(K, multiplicities=False)
528
+ sage: conjugacy_test(js)
529
+ []
530
+ sage: f = x^4 - 3
531
+ sage: K.<a> = NumberField(f)
532
+ sage: js = f.roots(K, multiplicities=False)
533
+ sage: conjugacy_test(js)
534
+ []
535
+ sage: K.<a> = f.splitting_field()
536
+ sage: js = f.roots(K, multiplicities=False)
537
+ sage: conjugacy_test(js)
538
+ [x^4 - 3]
539
+ """
540
+ from sage.sets.set import Set
541
+
542
+ # First test to see if the list contains a rational
543
+
544
+ jQ = next((j for j in jlist if j in QQ), None)
545
+ if jQ:
546
+ if verbose:
547
+ print("Yes: an isogenous curve has rational j-invariant {}".format(jQ))
548
+ x = polygen(QQ)
549
+ return [x - jQ]
550
+
551
+ # If the degree d is odd then we know that none of the
552
+ # j-invariants in the class have 2-power degree, so we can exit.
553
+
554
+ K = jlist[0].parent()
555
+ if K.degree() % 2:
556
+ if verbose:
557
+ print("Odd-degree case: no rational j-invariant in the class {}".format(jlist))
558
+ return []
559
+
560
+ # If K has no quadratic subfields we can similarly conclude right
561
+ # away. This is one way of determining this.
562
+
563
+ if K(1).descend_mod_power(QQ, 2) == [1]:
564
+ if verbose:
565
+ print("No-quadratic-subfield case: no rational j-invariant in the class {}".format(jlist))
566
+ return []
567
+
568
+ # compute the minimum polynomials of the j-invariants in the class
569
+ pols = (j.minpoly() for j in jlist)
570
+
571
+ # pick out those of 2-power degree
572
+ pols = [f for f in pols if f.degree().prime_to_m_part(2) == 1]
573
+
574
+ # If none, there is nothing to do
575
+ if not pols:
576
+ return []
577
+
578
+ # see if there's a poly of degree d appearing d times. NB There
579
+ # may be more than one of these, possibly including some conjugacy
580
+ # classes defined over the core field but not central, so we
581
+ # return all those with the minimal degree.
582
+
583
+ mindeg = min(f.degree() for f in pols)
584
+ minpols = [f for f in pols if f.degree() == mindeg]
585
+ centrepols = list(Set([f for f in pols if f.degree() == minpols.count(f)]))
586
+ if centrepols:
587
+ if verbose:
588
+ print("Yes: the isogeny class contains all j-invariants with min poly {}".format(centrepols))
589
+ return centrepols
590
+ if verbose:
591
+ print("No complete conjugacy class of 2-power size found in {}".format(jlist))
592
+ return []
@@ -0,0 +1,94 @@
1
+ # sage_setup: distribution = sagemath-schemes
2
+ r"""
3
+ Addition formula for elliptic curves over rings
4
+ """
5
+
6
+
7
+ def _add(E, P, Q):
8
+ r"""
9
+ Addition formulas for elliptic curves over general rings
10
+ with trivial Picard group.
11
+
12
+ This function returns a generator which yields tuples of projective
13
+ coordinates. Some linear combination of those coordinate tuples is
14
+ guaranteed to form a valid projective point.
15
+
16
+ .. NOTE::
17
+
18
+ This function is for internal use. To add two elliptic-curve
19
+ points, users should simply use the `+` operator.
20
+
21
+ REFERENCES:
22
+
23
+ These formulas were derived by Bosma and Lenstra [BL1995]_,
24
+ with corrections by Best [Best2021]_ (Appendix A).
25
+
26
+ EXAMPLES::
27
+
28
+ sage: from sage.schemes.elliptic_curves.addition_formulas_ring import _add
29
+ sage: M = Zmod(13*17*19)
30
+ sage: R.<U,V> = M[]
31
+ sage: S.<u,v> = R.quotient(U*V - 17)
32
+ sage: E = EllipticCurve(S, [1,2,3,4,5])
33
+ sage: P = E(817, 13, 19)
34
+ sage: Q = E(425, 123, 17)
35
+ sage: PQ1, PQ2 = _add(E, P, Q)
36
+ sage: PQ1
37
+ (1188, 1674, 540)
38
+ sage: PQ2
39
+ (582, 2347, 1028)
40
+ sage: E(PQ1) == E(PQ2)
41
+ True
42
+
43
+ TESTS:
44
+
45
+ We ensure that these formulas return the same result as the ones over a field::
46
+
47
+ sage: from sage.schemes.elliptic_curves.addition_formulas_ring import _add
48
+ sage: F = GF(2^127-1)
49
+ sage: E = EllipticCurve(j=F.random_element())
50
+ sage: E = choice(E.twists())
51
+ sage: P = E.random_point()
52
+ sage: Q = E.random_point()
53
+ sage: PQ1, PQ2 = _add(E, P, Q)
54
+ sage: assert E(*PQ1) == P + Q
55
+ sage: assert E(*PQ2) == P + Q
56
+ """
57
+ a1, a2, a3, a4, a6 = E.a_invariants()
58
+ b2, b4, b6, b8 = E.b_invariants()
59
+
60
+ if P not in E:
61
+ raise ValueError('P must be in E')
62
+ if Q not in E:
63
+ raise ValueError('Q must be in E')
64
+ X1, Y1, Z1 = P
65
+ X2, Y2, Z2 = Q
66
+
67
+ # TODO: I've made a half-hearted attempt at simplifying the formulas
68
+ # by caching common subexpressions. This could almost certainly be
69
+ # sped up significantly with some more serious optimization effort.
70
+
71
+ XYdif = X1*Y2 - X2*Y1
72
+ XYsum = X1*Y2 + X2*Y1
73
+ XZdif = X1*Z2 - X2*Z1
74
+ XZsum = X1*Z2 + X2*Z1
75
+ YZdif = Y1*Z2 - Y2*Z1
76
+ YZsum = Y1*Z2 + Y2*Z1
77
+
78
+ a1sq, a2sq, a3sq, a4sq = (a**2 for a in (a1, a2, a3, a4))
79
+
80
+ X31 = XYdif*YZsum+XZdif*Y1*Y2+a1*X1*X2*YZdif+a1*XYdif*XZsum-a2*X1*X2*XZdif+a3*XYdif*Z1*Z2+a3*XZdif*YZsum-a4*XZsum*XZdif-3*a6*XZdif*Z1*Z2
81
+
82
+ Y31 = -3*X1*X2*XYdif-Y1*Y2*YZdif-2*a1*XZdif*Y1*Y2+(a1sq+3*a2)*X1*X2*YZdif-(a1sq+a2)*XYsum*XZdif+(a1*a2-3*a3)*X1*X2*XZdif-(2*a1*a3+a4)*XYdif*Z1*Z2+a4*XZsum*YZdif+(a1*a4-a2*a3)*XZsum*XZdif+(a3sq+3*a6)*YZdif*Z1*Z2+(3*a1*a6-a3*a4)*XZdif*Z1*Z2
83
+
84
+ Z31 = 3*X1*X2*XZdif-YZsum*YZdif+a1*XYdif*Z1*Z2-a1*XZdif*YZsum+a2*XZsum*XZdif-a3*YZdif*Z1*Z2+a4*XZdif*Z1*Z2
85
+
86
+ yield (X31, Y31, Z31)
87
+
88
+ X32 = Y1*Y2*XYsum+a1*(2*X1*Y2+X2*Y1)*X2*Y1+a1sq*X1*X2**2*Y1-a2*X1*X2*XYsum-a1*a2*X1**2*X2**2+a3*X2*Y1*(YZsum+Y2*Z1)+a1*a3*X1*X2*YZdif-a1*a3*XYsum*XZdif-a4*X1*X2*YZsum-a4*XYsum*XZsum-a1sq*a3*X1**2*X2*Z2-a1*a4*X1*X2*(X1*Z2+XZsum)-a2*a3*X1*X2**2*Z1-a3sq*X1*Z2*(Y2*Z1+YZsum)-3*a6*XYsum*Z1*Z2-3*a6*XZsum*YZsum-a1*a3sq*X1*Z2*(XZsum+X2*Z1)-3*a1*a6*X1*Z2*(XZsum+X2*Z1)-a3*a4*(X1*Z2+XZsum)*X2*Z1-b8*YZsum*Z1*Z2-a1*b8*X1*Z1*Z2**2-a3**3*XZsum*Z1*Z2-3*a3*a6*(XZsum+X2*Z1)*Z1*Z2-a3*b8*Z1**2*Z2**2
89
+
90
+ Y32 = Y1**2*Y2**2+a1*X2*Y1**2*Y2+(a1*a2-3*a3)*X1*X2**2*Y1+a3*Y1**2*Y2*Z2-(a2sq-3*a4)*X1**2*X2**2+(a1*a4-a2*a3)*(2*X1*Z2+X2*Z1)*X2*Y1+(a1sq*a4-2*a1*a2*a3+3*a3sq)*X1**2*X2*Z2-(a2*a4-9*a6)*X1*X2*XZsum+(3*a1*a6-a3*a4)*(XZsum+X2*Z1)*Y1*Z2+(3*a1sq*a6-2*a1*a3*a4+a2*a3sq+3*a2*a6-a4sq)*X1*Z2*(XZsum+X2*Z1)+(3*a2*a6-a4sq)*X2*Z1*(2*X1*Z2+Z1*X2)+(a1**3*a6-a1sq*a3*a4+a1*a2*a3sq-a1*a4sq+4*a1*a2*a6-a3**3-3*a3*a6)*Y1*Z1*Z2**2+(a1**4*a6-a1**3*a3*a4+5*a1sq*a2*a6+a1sq*a2*a3sq-a1*a2*a3*a4-a1*a3**3-3*a1*a3*a6-a1sq*a4sq+a2sq*a3sq-a2*a4sq+4*a2sq*a6-a3**2*a4-3*a4*a6)*X1*Z1*Z2**2+(a1sq*a2*a6-a1*a2*a3*a4+3*a1*a3*a6+a2sq*a3sq-a2*a4sq+4*a2sq*a6-2*a3sq*a4-3*a4*a6)*X2*Z1**2*Z2+(a1**3*a3*a6-a1sq*a3sq*a4+a1sq*a4*a6+a1*a2*a3**3+4*a1*a2*a3*a6-2*a1*a3*a4sq+a2*a3sq*a4+4*a2*a4*a6-a3**4-6*a3**2*a6-a4**3-9*a6**2)*Z1**2*Z2**2
91
+
92
+ Z32 = 3*X1*X2*XYsum+Y1*Y2*YZsum+3*a1*X1**2*X2**2+a1*(2*X1*Y2+Y1*X2)*Y1*Z2+a1sq*X1*Z2*(2*X2*Y1+X1*Y2)+a2*X1*X2*YZsum+a2*XYsum*XZsum+a1**3*X1**2*X2*Z2+a1*a2*X1*X2*(2*X1*Z2+X2*Z1)+3*a3*X1*X2**2*Z1+a3*Y1*Z2*(YZsum+Y2*Z1)+2*a1*a3*X1*Z2*YZsum+2*a1*a3*X2*Y1*Z1*Z2+a4*XYsum*Z1*Z2+a4*XZsum*YZsum+(a1sq*a3+a1*a4)*X1*Z2*(XZsum+X2*Z1)+a2*a3*X2*Z1*(2*X1*Z2+X2*Z1)+a3sq*Y1*Z1*Z2**2+(a3sq+3*a6)*YZsum*Z1*Z2+a1*a3sq*(2*X1*Z2+X2*Z1)*Z1*Z2+3*a1*a6*X1*Z1*Z2**2+a3*a4*(XZsum+X2*Z1)*Z1*Z2+(a3**3+3*a3*a6)*Z1**2*Z2**2
93
+
94
+ yield (X32, Y32, Z32)