passagemath-schemes 10.6.47__cp312-cp312-macosx_13_0_arm64.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (311) 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.47.dist-info/METADATA +204 -0
  7. passagemath_schemes-10.6.47.dist-info/METADATA.bak +205 -0
  8. passagemath_schemes-10.6.47.dist-info/RECORD +311 -0
  9. passagemath_schemes-10.6.47.dist-info/WHEEL +6 -0
  10. passagemath_schemes-10.6.47.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-312-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-312-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-312-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-312-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-312-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-312-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-312-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-312-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_nf.py +1241 -0
  154. sage/modular/modsym/relation_matrix.py +591 -0
  155. sage/modular/modsym/relation_matrix_pyx.cpython-312-darwin.so +0 -0
  156. sage/modular/modsym/relation_matrix_pyx.pyx +108 -0
  157. sage/modular/modsym/space.py +2468 -0
  158. sage/modular/modsym/subspace.py +455 -0
  159. sage/modular/modsym/tests.py +375 -0
  160. sage/modular/multiple_zeta.py +2632 -0
  161. sage/modular/multiple_zeta_F_algebra.py +786 -0
  162. sage/modular/overconvergent/all.py +6 -0
  163. sage/modular/overconvergent/genus0.py +1878 -0
  164. sage/modular/overconvergent/hecke_series.py +1187 -0
  165. sage/modular/overconvergent/weightspace.py +778 -0
  166. sage/modular/pollack_stevens/all.py +4 -0
  167. sage/modular/pollack_stevens/distributions.py +874 -0
  168. sage/modular/pollack_stevens/fund_domain.py +1572 -0
  169. sage/modular/pollack_stevens/manin_map.py +859 -0
  170. sage/modular/pollack_stevens/modsym.py +1593 -0
  171. sage/modular/pollack_stevens/padic_lseries.py +417 -0
  172. sage/modular/pollack_stevens/sigma0.py +534 -0
  173. sage/modular/pollack_stevens/space.py +1076 -0
  174. sage/modular/quasimodform/all.py +3 -0
  175. sage/modular/quasimodform/element.py +845 -0
  176. sage/modular/quasimodform/ring.py +828 -0
  177. sage/modular/quatalg/all.py +3 -0
  178. sage/modular/quatalg/brandt.py +1642 -0
  179. sage/modular/ssmod/all.py +8 -0
  180. sage/modular/ssmod/ssmod.py +827 -0
  181. sage/rings/all__sagemath_schemes.py +1 -0
  182. sage/rings/polynomial/all__sagemath_schemes.py +1 -0
  183. sage/rings/polynomial/binary_form_reduce.py +585 -0
  184. sage/schemes/all.py +41 -0
  185. sage/schemes/berkovich/all.py +6 -0
  186. sage/schemes/berkovich/berkovich_cp_element.py +2582 -0
  187. sage/schemes/berkovich/berkovich_space.py +748 -0
  188. sage/schemes/curves/affine_curve.py +2928 -0
  189. sage/schemes/curves/all.py +33 -0
  190. sage/schemes/curves/closed_point.py +434 -0
  191. sage/schemes/curves/constructor.py +381 -0
  192. sage/schemes/curves/curve.py +542 -0
  193. sage/schemes/curves/plane_curve_arrangement.py +1283 -0
  194. sage/schemes/curves/point.py +463 -0
  195. sage/schemes/curves/projective_curve.py +3026 -0
  196. sage/schemes/curves/zariski_vankampen.py +1932 -0
  197. sage/schemes/cyclic_covers/all.py +2 -0
  198. sage/schemes/cyclic_covers/charpoly_frobenius.py +320 -0
  199. sage/schemes/cyclic_covers/constructor.py +137 -0
  200. sage/schemes/cyclic_covers/cycliccover_finite_field.py +1309 -0
  201. sage/schemes/cyclic_covers/cycliccover_generic.py +310 -0
  202. sage/schemes/elliptic_curves/BSD.py +1036 -0
  203. sage/schemes/elliptic_curves/Qcurves.py +592 -0
  204. sage/schemes/elliptic_curves/addition_formulas_ring.py +94 -0
  205. sage/schemes/elliptic_curves/all.py +49 -0
  206. sage/schemes/elliptic_curves/cardinality.py +609 -0
  207. sage/schemes/elliptic_curves/cm.py +1102 -0
  208. sage/schemes/elliptic_curves/constructor.py +1552 -0
  209. sage/schemes/elliptic_curves/ec_database.py +175 -0
  210. sage/schemes/elliptic_curves/ell_curve_isogeny.py +3972 -0
  211. sage/schemes/elliptic_curves/ell_egros.py +459 -0
  212. sage/schemes/elliptic_curves/ell_field.py +2836 -0
  213. sage/schemes/elliptic_curves/ell_finite_field.py +3359 -0
  214. sage/schemes/elliptic_curves/ell_generic.py +3760 -0
  215. sage/schemes/elliptic_curves/ell_local_data.py +1207 -0
  216. sage/schemes/elliptic_curves/ell_modular_symbols.py +775 -0
  217. sage/schemes/elliptic_curves/ell_number_field.py +4220 -0
  218. sage/schemes/elliptic_curves/ell_padic_field.py +107 -0
  219. sage/schemes/elliptic_curves/ell_point.py +4787 -0
  220. sage/schemes/elliptic_curves/ell_rational_field.py +7368 -0
  221. sage/schemes/elliptic_curves/ell_tate_curve.py +671 -0
  222. sage/schemes/elliptic_curves/ell_torsion.py +436 -0
  223. sage/schemes/elliptic_curves/ell_wp.py +352 -0
  224. sage/schemes/elliptic_curves/formal_group.py +760 -0
  225. sage/schemes/elliptic_curves/gal_reps.py +1459 -0
  226. sage/schemes/elliptic_curves/gal_reps_number_field.py +1669 -0
  227. sage/schemes/elliptic_curves/gp_simon.py +152 -0
  228. sage/schemes/elliptic_curves/heegner.py +7335 -0
  229. sage/schemes/elliptic_curves/height.py +2109 -0
  230. sage/schemes/elliptic_curves/hom.py +1406 -0
  231. sage/schemes/elliptic_curves/hom_composite.py +934 -0
  232. sage/schemes/elliptic_curves/hom_frobenius.py +522 -0
  233. sage/schemes/elliptic_curves/hom_scalar.py +531 -0
  234. sage/schemes/elliptic_curves/hom_sum.py +682 -0
  235. sage/schemes/elliptic_curves/hom_velusqrt.py +1290 -0
  236. sage/schemes/elliptic_curves/homset.py +271 -0
  237. sage/schemes/elliptic_curves/isogeny_class.py +1521 -0
  238. sage/schemes/elliptic_curves/isogeny_small_degree.py +2797 -0
  239. sage/schemes/elliptic_curves/jacobian.py +237 -0
  240. sage/schemes/elliptic_curves/kodaira_symbol.py +344 -0
  241. sage/schemes/elliptic_curves/kraus.py +1014 -0
  242. sage/schemes/elliptic_curves/lseries_ell.py +943 -0
  243. sage/schemes/elliptic_curves/mod5family.py +105 -0
  244. sage/schemes/elliptic_curves/mod_poly.py +197 -0
  245. sage/schemes/elliptic_curves/mod_sym_num.cpython-312-darwin.so +0 -0
  246. sage/schemes/elliptic_curves/mod_sym_num.pyx +3796 -0
  247. sage/schemes/elliptic_curves/modular_parametrization.py +305 -0
  248. sage/schemes/elliptic_curves/padic_lseries.py +1793 -0
  249. sage/schemes/elliptic_curves/padics.py +1816 -0
  250. sage/schemes/elliptic_curves/period_lattice.py +2234 -0
  251. sage/schemes/elliptic_curves/period_lattice_region.cpython-312-darwin.so +0 -0
  252. sage/schemes/elliptic_curves/period_lattice_region.pyx +722 -0
  253. sage/schemes/elliptic_curves/saturation.py +715 -0
  254. sage/schemes/elliptic_curves/sha_tate.py +1158 -0
  255. sage/schemes/elliptic_curves/weierstrass_morphism.py +1117 -0
  256. sage/schemes/elliptic_curves/weierstrass_transform.py +200 -0
  257. sage/schemes/hyperelliptic_curves/all.py +6 -0
  258. sage/schemes/hyperelliptic_curves/constructor.py +291 -0
  259. sage/schemes/hyperelliptic_curves/hyperelliptic_finite_field.py +1914 -0
  260. sage/schemes/hyperelliptic_curves/hyperelliptic_g2.py +192 -0
  261. sage/schemes/hyperelliptic_curves/hyperelliptic_generic.py +954 -0
  262. sage/schemes/hyperelliptic_curves/hyperelliptic_padic_field.py +1332 -0
  263. sage/schemes/hyperelliptic_curves/hyperelliptic_rational_field.py +84 -0
  264. sage/schemes/hyperelliptic_curves/invariants.py +410 -0
  265. sage/schemes/hyperelliptic_curves/jacobian_endomorphism_utils.py +315 -0
  266. sage/schemes/hyperelliptic_curves/jacobian_g2.py +32 -0
  267. sage/schemes/hyperelliptic_curves/jacobian_generic.py +419 -0
  268. sage/schemes/hyperelliptic_curves/jacobian_homset.py +186 -0
  269. sage/schemes/hyperelliptic_curves/jacobian_morphism.py +875 -0
  270. sage/schemes/hyperelliptic_curves/kummer_surface.py +99 -0
  271. sage/schemes/hyperelliptic_curves/mestre.py +302 -0
  272. sage/schemes/hyperelliptic_curves/monsky_washnitzer.py +3871 -0
  273. sage/schemes/jacobians/abstract_jacobian.py +277 -0
  274. sage/schemes/jacobians/all.py +2 -0
  275. sage/schemes/overview.py +161 -0
  276. sage/schemes/plane_conics/all.py +22 -0
  277. sage/schemes/plane_conics/con_field.py +1296 -0
  278. sage/schemes/plane_conics/con_finite_field.py +158 -0
  279. sage/schemes/plane_conics/con_number_field.py +456 -0
  280. sage/schemes/plane_conics/con_rational_field.py +406 -0
  281. sage/schemes/plane_conics/con_rational_function_field.py +580 -0
  282. sage/schemes/plane_conics/constructor.py +249 -0
  283. sage/schemes/plane_quartics/all.py +2 -0
  284. sage/schemes/plane_quartics/quartic_constructor.py +71 -0
  285. sage/schemes/plane_quartics/quartic_generic.py +73 -0
  286. sage/schemes/riemann_surfaces/all.py +1 -0
  287. sage/schemes/riemann_surfaces/riemann_surface.py +4117 -0
  288. sage_wheels/share/cremona/cremona_mini.db +0 -0
  289. sage_wheels/share/ellcurves/rank0 +30427 -0
  290. sage_wheels/share/ellcurves/rank1 +31871 -0
  291. sage_wheels/share/ellcurves/rank10 +6 -0
  292. sage_wheels/share/ellcurves/rank11 +6 -0
  293. sage_wheels/share/ellcurves/rank12 +1 -0
  294. sage_wheels/share/ellcurves/rank14 +1 -0
  295. sage_wheels/share/ellcurves/rank15 +1 -0
  296. sage_wheels/share/ellcurves/rank17 +1 -0
  297. sage_wheels/share/ellcurves/rank19 +1 -0
  298. sage_wheels/share/ellcurves/rank2 +2388 -0
  299. sage_wheels/share/ellcurves/rank20 +1 -0
  300. sage_wheels/share/ellcurves/rank21 +1 -0
  301. sage_wheels/share/ellcurves/rank22 +1 -0
  302. sage_wheels/share/ellcurves/rank23 +1 -0
  303. sage_wheels/share/ellcurves/rank24 +1 -0
  304. sage_wheels/share/ellcurves/rank28 +1 -0
  305. sage_wheels/share/ellcurves/rank3 +836 -0
  306. sage_wheels/share/ellcurves/rank4 +10 -0
  307. sage_wheels/share/ellcurves/rank5 +5 -0
  308. sage_wheels/share/ellcurves/rank6 +5 -0
  309. sage_wheels/share/ellcurves/rank7 +5 -0
  310. sage_wheels/share/ellcurves/rank8 +6 -0
  311. sage_wheels/share/ellcurves/rank9 +7 -0
@@ -0,0 +1,682 @@
1
+ # sage_setup: distribution = sagemath-schemes
2
+ r"""
3
+ Sums of morphisms of elliptic curves
4
+
5
+ The set `\mathrm{Hom}(E,E')` of morphisms between two elliptic curves
6
+ forms an abelian group under pointwise addition. An important special
7
+ case is the endomorphism ring `\mathrm{End}(E) = \mathrm{Hom}(E,E)`.
8
+ However, it is not immediately obvious how to compute some properties
9
+ of the sum `\varphi+\psi` of two isogenies, even when both are given
10
+ explicitly. This class provides functionality for representing sums of
11
+ elliptic-curve morphisms (in particular, isogenies and endomorphisms)
12
+ formally, and explicitly computing important properties (such as the
13
+ degree or the kernel polynomial) from the formal representation.
14
+
15
+ EXAMPLES::
16
+
17
+ sage: E = EllipticCurve(GF(101), [5,5])
18
+ sage: phi = E.isogenies_prime_degree(7)[0]
19
+ sage: phi + phi
20
+ Sum morphism:
21
+ From: Elliptic Curve defined by y^2 = x^3 + 5*x + 5 over Finite Field of size 101
22
+ To: Elliptic Curve defined by y^2 = x^3 + 12*x + 98 over Finite Field of size 101
23
+ Via: (Isogeny of degree 7
24
+ from Elliptic Curve defined by y^2 = x^3 + 5*x + 5 over Finite Field of size 101
25
+ to Elliptic Curve defined by y^2 = x^3 + 12*x + 98 over Finite Field of size 101,
26
+ Isogeny of degree 7
27
+ from Elliptic Curve defined by y^2 = x^3 + 5*x + 5 over Finite Field of size 101
28
+ to Elliptic Curve defined by y^2 = x^3 + 12*x + 98 over Finite Field of size 101)
29
+ sage: phi + phi == phi * E.scalar_multiplication(2) # needs sage.symbolic
30
+ True
31
+ sage: phi + phi + phi == phi * E.scalar_multiplication(3) # needs sage.symbolic
32
+ True
33
+
34
+ An example of computing with a supersingular endomorphism ring::
35
+
36
+ sage: # needs sage.symbolic
37
+ sage: E = EllipticCurve(GF(419^2), [1,0])
38
+ sage: i = E.automorphisms()[-1]
39
+ sage: j = E.frobenius_isogeny()
40
+ sage: i * j == - j * i # i,j anticommute
41
+ True
42
+ sage: (i + j) * i == i^2 - i*j # distributive law
43
+ True
44
+ sage: (j - E.scalar_multiplication(1)).degree() # point counting!
45
+ 420
46
+
47
+ AUTHORS:
48
+
49
+ - Lorenz Panny (2023)
50
+ """
51
+
52
+ from sage.misc.cachefunc import cached_method
53
+ from sage.structure.sequence import Sequence
54
+
55
+ from sage.arith.misc import gcd
56
+
57
+ from sage.rings.integer_ring import ZZ
58
+ from sage.rings.polynomial.polynomial_ring import polygen
59
+
60
+ from sage.sets.primes import Primes
61
+
62
+ from sage.schemes.elliptic_curves.ell_field import point_of_order
63
+ from sage.groups.generic import discrete_log, order_from_multiple
64
+
65
+ from sage.schemes.elliptic_curves.hom import EllipticCurveHom, compare_via_evaluation
66
+
67
+
68
+ class EllipticCurveHom_sum(EllipticCurveHom):
69
+
70
+ _degree = None
71
+ _phis = None
72
+
73
+ def __init__(self, phis, domain=None, codomain=None):
74
+ r"""
75
+ Construct a sum morphism of elliptic curves from its summands.
76
+ (For empty sums, the domain and codomain curves must be given.)
77
+
78
+ EXAMPLES::
79
+
80
+ sage: from sage.schemes.elliptic_curves.hom_sum import EllipticCurveHom_sum
81
+ sage: E = EllipticCurve(GF(101), [5,5])
82
+ sage: phi = E.isogenies_prime_degree(7)[0]
83
+ sage: EllipticCurveHom_sum([phi, phi])
84
+ Sum morphism:
85
+ From: Elliptic Curve defined by y^2 = x^3 + 5*x + 5 over Finite Field of size 101
86
+ To: Elliptic Curve defined by y^2 = x^3 + 12*x + 98 over Finite Field of size 101
87
+ Via: (Isogeny of degree 7 from Elliptic Curve defined by y^2 = x^3 + 5*x + 5 over Finite Field of size 101 to Elliptic Curve defined by y^2 = x^3 + 12*x + 98 over Finite Field of size 101, Isogeny of degree 7 from Elliptic Curve defined by y^2 = x^3 + 5*x + 5 over Finite Field of size 101 to Elliptic Curve defined by y^2 = x^3 + 12*x + 98 over Finite Field of size 101)
88
+
89
+ The zero morphism can be constructed even between non-isogenous curves::
90
+
91
+ sage: E1 = EllipticCurve(GF(101), [5,5])
92
+ sage: E2 = EllipticCurve(GF(101), [7,7])
93
+ sage: E1.is_isogenous(E2)
94
+ False
95
+ sage: EllipticCurveHom_sum([], E1, E2)
96
+ Sum morphism:
97
+ From: Elliptic Curve defined by y^2 = x^3 + 5*x + 5 over Finite Field of size 101
98
+ To: Elliptic Curve defined by y^2 = x^3 + 7*x + 7 over Finite Field of size 101
99
+ Via: ()
100
+ """
101
+ phis = tuple(phis)
102
+
103
+ if not phis and (domain is None or codomain is None):
104
+ raise ValueError('need either phis or both domain and codomain')
105
+
106
+ for phi in phis:
107
+ if not isinstance(phi, EllipticCurveHom):
108
+ raise ValueError(f'not an elliptic-curve morphism: {phi}')
109
+
110
+ if domain is None:
111
+ domain = phis[0].domain()
112
+ if codomain is None:
113
+ codomain = phis[0].codomain()
114
+ for phi in phis:
115
+ if phi.domain() != domain:
116
+ raise ValueError(f'summand {phi} has incorrect domain (need {domain})')
117
+ if phi.codomain() != codomain:
118
+ raise ValueError(f'summand {phi} has incorrect codomain (need {codomain})')
119
+
120
+ self._phis = phis
121
+ self._domain = domain
122
+ self._codomain = codomain
123
+
124
+ # We temporarily overwrite the _degree attribute here to prevent the
125
+ # EllipticCurveHom constructor from attempting to compute the degree.
126
+ self._degree = 0
127
+ EllipticCurveHom.__init__(self, self._domain, self._codomain)
128
+ self._degree = None
129
+
130
+ def _call_(self, P):
131
+ r"""
132
+ Evaluate this sum morphism at a point.
133
+
134
+ EXAMPLES::
135
+
136
+ sage: E = EllipticCurve(GF(101), [5,5])
137
+ sage: phi = E.isogenies_prime_degree(7)[0]
138
+ sage: P = E.lift_x(0)
139
+ sage: (phi + phi)(P)
140
+ (72 : 56 : 1)
141
+ sage: (phi - phi)(P)
142
+ (0 : 1 : 0)
143
+ """
144
+ return sum((phi(P) for phi in self._phis), self._codomain(0))
145
+
146
+ def _eval(self, P):
147
+ r"""
148
+ Less strict evaluation method for internal use.
149
+
150
+ In particular, this can be used to evaluate ``self`` at a
151
+ point defined over an extension field.
152
+
153
+ INPUT: a sequence of 3 coordinates defining a point on ``self``
154
+
155
+ OUTPUT: the result of evaluating ``self`` at the given point
156
+
157
+ EXAMPLES::
158
+
159
+ sage: E = EllipticCurve(GF(101), [5,5])
160
+ sage: phi = E.isogenies_prime_degree(7)[0]
161
+ sage: P = E.change_ring(GF(101^2)).lift_x(1)
162
+ sage: (phi + phi)._eval(P)
163
+ (11 : 15*z2 + 71 : 1)
164
+ sage: (phi - phi)._eval(P)
165
+ (0 : 1 : 0)
166
+ """
167
+ if self._domain.defining_polynomial()(*P):
168
+ raise ValueError(f'{P} not on {self._domain}')
169
+ k = Sequence(P).universe()
170
+ return sum((phi._eval(P) for phi in self._phis), self._codomain.base_extend(k)(0))
171
+
172
+ def _repr_(self):
173
+ r"""
174
+ Return basic facts about this sum morphism as a string.
175
+
176
+ EXAMPLES::
177
+
178
+ sage: E = EllipticCurve(GF(101), [5,5])
179
+ sage: phi = E.isogenies_prime_degree(7)[0]
180
+ sage: phi + phi # indirect doctest
181
+ Sum morphism:
182
+ From: Elliptic Curve defined by y^2 = x^3 + 5*x + 5 over Finite Field of size 101
183
+ To: Elliptic Curve defined by y^2 = x^3 + 12*x + 98 over Finite Field of size 101
184
+ Via: (Isogeny of degree 7 from Elliptic Curve defined by y^2 = x^3 + 5*x + 5 over Finite Field of size 101 to Elliptic Curve defined by y^2 = x^3 + 12*x + 98 over Finite Field of size 101, Isogeny of degree 7 from Elliptic Curve defined by y^2 = x^3 + 5*x + 5 over Finite Field of size 101 to Elliptic Curve defined by y^2 = x^3 + 12*x + 98 over Finite Field of size 101)
185
+ """
186
+ return f'Sum morphism:' \
187
+ f'\n From: {self._domain}' \
188
+ f'\n To: {self._codomain}' \
189
+ f'\n Via: {self._phis}'
190
+
191
+ def summands(self):
192
+ r"""
193
+ Return the individual summands making up this sum morphism.
194
+
195
+ EXAMPLES::
196
+
197
+ sage: E = EllipticCurve(j=5)
198
+ sage: m2 = E.scalar_multiplication(2)
199
+ sage: m3 = E.scalar_multiplication(3)
200
+ sage: m2 + m3
201
+ Sum morphism:
202
+ From: Elliptic Curve defined by y^2 + x*y = x^3 + x^2 + 180*x + 17255 over Rational Field
203
+ To: Elliptic Curve defined by y^2 + x*y = x^3 + x^2 + 180*x + 17255 over Rational Field
204
+ Via: (Scalar-multiplication endomorphism [2] of Elliptic Curve defined by y^2 + x*y = x^3 + x^2 + 180*x + 17255 over Rational Field, Scalar-multiplication endomorphism [3] of Elliptic Curve defined by y^2 + x*y = x^3 + x^2 + 180*x + 17255 over Rational Field)
205
+ """
206
+ return self._phis
207
+
208
+ @cached_method
209
+ def to_isogeny_chain(self):
210
+ r"""
211
+ Convert this formal sum of elliptic-curve morphisms into a
212
+ :class:`~sage.schemes.elliptic_curves.hom_composite.EllipticCurveHom_composite`
213
+ object representing the same morphism.
214
+
215
+ EXAMPLES::
216
+
217
+ sage: E = EllipticCurve(GF(101), [5,5])
218
+ sage: phi = E.isogenies_prime_degree(7)[0]
219
+ sage: (phi + phi).to_isogeny_chain()
220
+ Composite morphism of degree 28 = 4*1*7:
221
+ From: Elliptic Curve defined by y^2 = x^3 + 5*x + 5 over Finite Field of size 101
222
+ To: Elliptic Curve defined by y^2 = x^3 + 12*x + 98 over Finite Field of size 101
223
+
224
+ ::
225
+
226
+ sage: p = 419
227
+ sage: E = EllipticCurve(GF(p^2), [1,0])
228
+ sage: iota = E.automorphisms()[2] # sqrt(-1)
229
+ sage: pi = E.frobenius_isogeny() # sqrt(-p)
230
+ sage: endo = iota + pi
231
+ sage: endo.degree()
232
+ 420
233
+ sage: endo.to_isogeny_chain()
234
+ Composite morphism of degree 420 = 4*1*3*5*7:
235
+ From: Elliptic Curve defined by y^2 = x^3 + x over Finite Field in z2 of size 419^2
236
+ To: Elliptic Curve defined by y^2 = x^3 + x over Finite Field in z2 of size 419^2
237
+
238
+ The decomposition is impossible for the constant zero map::
239
+
240
+ sage: endo = iota*pi + pi*iota
241
+ sage: endo.degree()
242
+ 0
243
+ sage: endo.to_isogeny_chain()
244
+ Traceback (most recent call last):
245
+ ...
246
+ ValueError: zero morphism cannot be written as a composition of isogenies
247
+
248
+ Isomorphisms are supported as well::
249
+
250
+ sage: E = EllipticCurve(j=5); E
251
+ Elliptic Curve defined by y^2 + x*y = x^3 + x^2 + 180*x + 17255 over Rational Field
252
+ sage: m2 = E.scalar_multiplication(2)
253
+ sage: m3 = E.scalar_multiplication(3)
254
+ sage: (m2 - m3).to_isogeny_chain()
255
+ Composite morphism of degree 1 = 1^2:
256
+ From: Elliptic Curve defined by y^2 + x*y = x^3 + x^2 + 180*x + 17255 over Rational Field
257
+ To: Elliptic Curve defined by y^2 + x*y = x^3 + x^2 + 180*x + 17255 over Rational Field
258
+ sage: (m2 - m3).rational_maps()
259
+ (x, -x - y)
260
+ """
261
+ deg = self.degree()
262
+ if deg.is_zero():
263
+ raise ValueError('zero morphism cannot be written as a composition of isogenies')
264
+
265
+ p = self.base_ring().characteristic()
266
+ insep = self.inseparable_degree().valuation(p) if p else 0
267
+
268
+ scalar = 1 #TODO Can we detect scalar factors earlier to save some extensions below?
269
+
270
+ ker = []
271
+ for l,m in deg.factor():
272
+ if l == p: # possibly inseparable
273
+ if insep < m:
274
+ # kernel of the separable p-power part is unique
275
+ P = point_of_order(self.domain(), p**(m-insep))
276
+ ker.append(P)
277
+ continue
278
+
279
+ # F = self.domain().division_field(l**m) #FIXME this can be used once #35936 is done; workaround below
280
+ F = self.domain().division_polynomial(l**m).splitting_field('X').extension(2,'Y')
281
+
282
+ P,Q = self.domain().change_ring(F).torsion_basis(l**m)
283
+ if self.is_endomorphism():
284
+ R,S = P,Q
285
+ else:
286
+ R,S = self.codomain().change_ring(F).torsion_basis(l**m)
287
+ M = self.matrix_on_subgroup((P,Q), (R,S))
288
+ g = ZZ(gcd(M.list())).p_primary_part(l)
289
+ if g > 1:
290
+ scalar *= g
291
+ M = (M.change_ring(ZZ) / g).change_ring(M.base_ring())
292
+ K = M.left_kernel_matrix()
293
+ for row in K:
294
+ u,v = map(ZZ, row)
295
+ pt = u*P + v*Q
296
+ pt.set_order(row.additive_order())
297
+ ker.append(pt)
298
+
299
+ from sage.schemes.elliptic_curves.hom_composite import EllipticCurveHom_composite
300
+ phi = EllipticCurveHom_composite(self.domain(), [])
301
+
302
+ if scalar != 1:
303
+ phi *= phi.codomain().scalar_multiplication(scalar)
304
+
305
+ while ker:
306
+ K = ker.pop(0)
307
+
308
+ (l,e), = K.order().factor()
309
+ for i in reversed(range(e)):
310
+ Kl = l**i * K
311
+ Kl.set_order(l)
312
+
313
+ from sage.groups.generic import multiples
314
+ from sage.misc.misc_c import prod
315
+ x = polygen(Kl.base_ring())
316
+ poly = prod(x - T.x() for T in multiples(Kl, l//2, Kl))
317
+ poly = poly.change_ring(self.base_ring())
318
+
319
+ psi = phi.codomain().isogeny(poly)
320
+ phi = psi * phi
321
+ K = psi._eval(K)
322
+ ker = [psi._eval(P) for P in ker]
323
+
324
+ if insep:
325
+ frob = phi.codomain().frobenius_isogeny(insep)
326
+ phi = frob * phi
327
+
328
+ from sage.schemes.elliptic_curves.hom import find_post_isomorphism
329
+ iso = find_post_isomorphism(phi, self)
330
+ return iso * phi
331
+
332
+ # EllipticCurveHom methods
333
+
334
+ def _degree_bounds(self):
335
+ r"""
336
+ Return a lower and upper bound on the degree of this sum morphism.
337
+
338
+ EXAMPLES::
339
+
340
+ sage: E = EllipticCurve(GF(307), [5,5])
341
+ sage: phi = E.isogenies_prime_degree(3)[0]; phi
342
+ Isogeny of degree 3 from Elliptic Curve defined by y^2 = x^3 + 5*x + 5 over Finite Field of size 307 to Elliptic Curve defined by y^2 = x^3 + 227*x + 163 over Finite Field of size 307
343
+ sage: psi = next(iso*psi for psi in E.isogenies_prime_degree(43)
344
+ ....: for iso in psi.codomain().isomorphisms(phi.codomain())); psi
345
+ Isogeny of degree 43 from Elliptic Curve defined by y^2 = x^3 + 5*x + 5 over Finite Field of size 307 to Elliptic Curve defined by y^2 = x^3 + 227*x + 163 over Finite Field of size 307
346
+ sage: (phi + psi)._degree_bounds()
347
+ (24, 68)
348
+ sage: (phi + psi).degree()
349
+ 31
350
+ sage: (phi - phi)._degree_bounds()
351
+ (0, 12)
352
+ sage: (phi - phi).degree()
353
+ 0
354
+
355
+ ::
356
+
357
+ sage: E = EllipticCurve(GF(443), [1,1])
358
+ sage: pi = E.frobenius_endomorphism()
359
+ sage: m1 = E.scalar_multiplication(1)
360
+ sage: (pi - m1)._degree_bounds()
361
+ (402, 486)
362
+ sage: (pi - m1)._degree_bounds() == Hasse_bounds(443)
363
+ True
364
+ sage: (pi - m1).degree()
365
+ 433
366
+
367
+ ALGORITHM: Repeated application of the Cauchy-Schwarz inequality,
368
+ here in the form
369
+ `|\deg(f+g) - \deg(f) - \deg(g)| \leq 2\sqrt{\deg(f)\cdot\deg(g)}`.
370
+ See for instance Lemma V.1.2 of [Sil2009]_.
371
+ """
372
+ lo, hi = ZZ.zero(), ZZ.zero()
373
+ for phi in self._phis:
374
+ m = (hi * phi.degree()).isqrt()
375
+ hi += phi.degree() + 2*m
376
+ lo += phi.degree() - 2*m
377
+ lo = max(lo, 0)
378
+ return lo, hi
379
+
380
+ def _compute_degree(self):
381
+ r"""
382
+ Internal method to compute and cache the degree of this sum morphism
383
+ (and its dual).
384
+
385
+ ALGORITHM: Evaluate the composition with the dual on points of small
386
+ order and solve logarithms to eventually recover the degree using CRT.
387
+ (This is essentially Schoof's algorithm, applied to a scalar.)
388
+
389
+ EXAMPLES::
390
+
391
+ sage: E = EllipticCurve(GF(101), [5,5])
392
+ sage: phi = E.isogenies_prime_degree(7)[0]
393
+ sage: isog = phi + phi
394
+ sage: print(isog._degree)
395
+ None
396
+ sage: isog._compute_degree()
397
+ sage: isog._degree
398
+ 28
399
+
400
+ ::
401
+
402
+ sage: E = EllipticCurve(GF(443), [1,1])
403
+ sage: pi = E.frobenius_endomorphism()
404
+ sage: m1 = E.scalar_multiplication(1)
405
+ sage: endo = pi - m1
406
+ sage: print(endo._degree)
407
+ None
408
+ sage: endo._compute_degree()
409
+ sage: endo._degree
410
+ 433
411
+ sage: endo.dual()._degree
412
+ 433
413
+ """
414
+ if self._degree is not None:
415
+ return
416
+ if not self._phis:
417
+ self._degree = ZZ.zero()
418
+ elif len(self._phis) == 1:
419
+ self._degree = self._phis[0].degree()
420
+ else:
421
+ #TODO In some cases it would probably be faster to simply
422
+ # compute the kernel polynomial using the addition formulas?
423
+ from sage.rings.finite_rings.integer_mod import Mod
424
+
425
+ lo, hi = self._degree_bounds()
426
+ M = hi - lo + 1
427
+ rem = Mod(0,1)
428
+ for l in Primes():
429
+ if rem.modulus() >= M:
430
+ break
431
+ try:
432
+ P = point_of_order(self._domain, l)
433
+ except ValueError:
434
+ continue # supersingular and l == p
435
+
436
+ Q = self.dual()._eval(self._eval(P))
437
+ d = discrete_log(Q, P, ord=l, operation='+')
438
+ rem = rem.crt(Mod(d-lo, l))
439
+
440
+ self._degree = lo + rem.lift()
441
+ self.dual()._degree = self._degree
442
+
443
+ @staticmethod
444
+ def _comparison_impl(left, right, op):
445
+ r"""
446
+ Compare a sum morphism to another elliptic-curve morphism.
447
+
448
+ Called by :meth:`EllipticCurveHom._richcmp_`.
449
+
450
+ If possible, we use
451
+ :func:`~sage.schemes.elliptic_curves.hom.compare_via_evaluation`.
452
+ The complexity in that case is polynomial in the logarithm of
453
+ the degree.
454
+
455
+ TESTS::
456
+
457
+ sage: from sage.schemes.elliptic_curves.hom_sum import EllipticCurveHom_sum
458
+ sage: E = EllipticCurve(GF(419^2), [1,0])
459
+ sage: i = E.automorphisms()[-1]
460
+ sage: j = E.frobenius_isogeny()
461
+ sage: i + j == j + i # needs sage.symbolic
462
+ True
463
+ """
464
+ from sage.structure.richcmp import op_EQ
465
+ if op != op_EQ:
466
+ return NotImplemented
467
+ try:
468
+ return compare_via_evaluation(left, right)
469
+ except NotImplementedError:
470
+ return NotImplemented
471
+
472
+ def degree(self):
473
+ r"""
474
+ Return the degree of this sum morphism.
475
+
476
+ EXAMPLES::
477
+
478
+ sage: E = EllipticCurve(GF(101), [5,5])
479
+ sage: phi = E.isogenies_prime_degree(7)[0]
480
+ sage: (phi + phi).degree()
481
+ 28
482
+
483
+ This method yields a simple toy point-counting algorithm::
484
+
485
+ sage: E = EllipticCurve(GF(101), [5,5])
486
+ sage: m1 = E.scalar_multiplication(1)
487
+ sage: pi = E.frobenius_endomorphism()
488
+ sage: (pi - m1).degree()
489
+ 119
490
+ sage: E.count_points()
491
+ 119
492
+
493
+ ALGORITHM: Essentially Schoof's algorithm; see :meth:`_compute_degree`.
494
+ """
495
+ if self._degree is None:
496
+ self._compute_degree()
497
+ return self._degree
498
+
499
+ def rational_maps(self):
500
+ r"""
501
+ Return the rational maps of this sum morphism.
502
+
503
+ EXAMPLES::
504
+
505
+ sage: E = EllipticCurve(GF(101), [5,5])
506
+ sage: phi = E.isogenies_prime_degree(7)[0]
507
+ sage: (phi + phi).rational_maps()
508
+ ((5*x^28 + 43*x^27 + 26*x^26 - ... + 7*x^2 - 23*x + 38)/(23*x^27 + 16*x^26 + 9*x^25 + ... - 43*x^2 - 22*x + 37),
509
+ (42*x^42*y - 44*x^41*y - 22*x^40*y + ... - 26*x^2*y - 50*x*y - 18*y)/(-24*x^42 - 47*x^41 - 12*x^40 + ... + 18*x^2 - 48*x + 18))
510
+
511
+ ALGORITHM: :meth:`to_isogeny_chain`.
512
+ """
513
+ #TODO In some cases it would probably be faster to compute this
514
+ # directly using the addition formulas?
515
+ return self.to_isogeny_chain().rational_maps()
516
+
517
+ def x_rational_map(self):
518
+ r"""
519
+ Return the `x`-coordinate rational map of this sum morphism.
520
+
521
+ EXAMPLES::
522
+
523
+ sage: E = EllipticCurve(GF(101), [5,5])
524
+ sage: phi = E.isogenies_prime_degree(7)[0]
525
+ sage: (phi + phi).x_rational_map()
526
+ (9*x^28 + 37*x^27 + 67*x^26 + ... + 53*x^2 + 100*x + 28)/(x^27 + 49*x^26 + 97*x^25 + ... + 64*x^2 + 21*x + 6)
527
+
528
+ ALGORITHM: :meth:`to_isogeny_chain`.
529
+ """
530
+ #TODO In some cases it would probably be faster to compute this
531
+ # directly using the addition formulas?
532
+ return self.to_isogeny_chain().x_rational_map()
533
+
534
+ def kernel_polynomial(self):
535
+ r"""
536
+ Return the kernel polynomial of this sum morphism.
537
+
538
+ EXAMPLES::
539
+
540
+ sage: E = EllipticCurve(GF(101), [5,5])
541
+ sage: phi = E.isogenies_prime_degree(7)[0]
542
+ sage: (phi + phi).kernel_polynomial()
543
+ x^15 + 75*x^14 + 16*x^13 + 59*x^12 + 28*x^11 + 60*x^10 + 69*x^9 + 79*x^8 + 79*x^7 + 52*x^6 + 35*x^5 + 11*x^4 + 37*x^3 + 69*x^2 + 66*x + 63
544
+
545
+ ::
546
+
547
+ sage: E = EllipticCurve(GF(11), [5,5])
548
+ sage: pi = E.frobenius_endomorphism()
549
+ sage: m1 = E.scalar_multiplication(1)
550
+ sage: (pi - m1).kernel_polynomial()
551
+ x^9 + 7*x^8 + 2*x^7 + 4*x^6 + 10*x^4 + 4*x^3 + 9*x^2 + 7*x
552
+
553
+ ALGORITHM: :meth:`to_isogeny_chain`.
554
+ """
555
+ #TODO In some cases it would probably be faster to compute this
556
+ # directly using the addition formulas?
557
+ return self.to_isogeny_chain().kernel_polynomial()
558
+
559
+ def scaling_factor(self):
560
+ r"""
561
+ Return the Weierstrass scaling factor associated to this
562
+ sum morphism.
563
+
564
+ The scaling factor is the constant `u` (in the base field)
565
+ such that `\varphi^* \omega_2 = u \omega_1`, where
566
+ `\varphi: E_1\to E_2` is this morphism and `\omega_i` are
567
+ the standard Weierstrass differentials on `E_i` defined by
568
+ `\mathrm dx/(2y+a_1x+a_3)`.
569
+
570
+ EXAMPLES::
571
+
572
+ sage: E = EllipticCurve(GF(101), [5,5])
573
+ sage: phi = E.isogenies_prime_degree(7)[0]
574
+ sage: phi.scaling_factor()
575
+ 84
576
+ sage: (phi + phi).scaling_factor()
577
+ 67
578
+
579
+ ALGORITHM: The scaling factor is additive under addition
580
+ of elliptic-curve morphisms, so we simply add together the
581
+ scaling factors of the :meth:`summands`.
582
+ """
583
+ return sum(phi.scaling_factor() for phi in self._phis)
584
+
585
+ @cached_method
586
+ def dual(self):
587
+ r"""
588
+ Return the dual of this sum morphism.
589
+
590
+ EXAMPLES::
591
+
592
+ sage: E = EllipticCurve(GF(101), [5,5])
593
+ sage: phi = E.isogenies_prime_degree(7)[0]
594
+ sage: (phi + phi).dual()
595
+ Sum morphism:
596
+ From: Elliptic Curve defined by y^2 = x^3 + 12*x + 98 over Finite Field of size 101
597
+ To: Elliptic Curve defined by y^2 = x^3 + 5*x + 5 over Finite Field of size 101
598
+ Via: (Isogeny of degree 7 from Elliptic Curve defined by y^2 = x^3 + 12*x + 98 over Finite Field of size 101 to Elliptic Curve defined by y^2 = x^3 + 5*x + 5 over Finite Field of size 101, Isogeny of degree 7 from Elliptic Curve defined by y^2 = x^3 + 12*x + 98 over Finite Field of size 101 to Elliptic Curve defined by y^2 = x^3 + 5*x + 5 over Finite Field of size 101)
599
+ sage: (phi + phi).dual() == phi.dual() + phi.dual() # needs sage.symbolic
600
+ True
601
+
602
+ ::
603
+
604
+ sage: E = EllipticCurve(GF(431^2), [1,0])
605
+ sage: iota = E.automorphisms()[2]
606
+ sage: m2 = E.scalar_multiplication(2)
607
+ sage: endo = m2 + iota
608
+ sage: endo.dual()
609
+ Sum morphism:
610
+ From: Elliptic Curve defined by y^2 = x^3 + x over Finite Field in z2 of size 431^2
611
+ To: Elliptic Curve defined by y^2 = x^3 + x over Finite Field in z2 of size 431^2
612
+ Via: (Scalar-multiplication endomorphism [2] of Elliptic Curve defined by y^2 = x^3 + x over Finite Field in z2 of size 431^2, Elliptic-curve endomorphism of Elliptic Curve defined by y^2 = x^3 + x over Finite Field in z2 of size 431^2
613
+ Via: (u,r,s,t) = (8*z2 + 427, 0, 0, 0))
614
+ sage: endo.dual() == (m2 - iota) # needs sage.symbolic
615
+ True
616
+
617
+ ALGORITHM: Taking the dual distributes over addition.
618
+ """
619
+ psi = EllipticCurveHom_sum((phi.dual() for phi in self._phis),
620
+ domain=self._codomain, codomain=self._domain)
621
+ psi._degree = self._degree
622
+ if self.trace.is_in_cache():
623
+ psi.trace.set_cache(-self.trace.cache)
624
+ psi.dual.set_cache(self)
625
+ return psi
626
+
627
+ @cached_method
628
+ def inseparable_degree(self):
629
+ r"""
630
+ Compute the inseparable degree of this sum morphism.
631
+
632
+ EXAMPLES::
633
+
634
+ sage: E = EllipticCurve(GF(7), [0,1])
635
+ sage: m3 = E.scalar_multiplication(3)
636
+ sage: m3.inseparable_degree()
637
+ 1
638
+ sage: m4 = E.scalar_multiplication(4)
639
+ sage: m7 = m3 + m4; m7
640
+ Sum morphism:
641
+ From: Elliptic Curve defined by y^2 = x^3 + 1 over Finite Field of size 7
642
+ To: Elliptic Curve defined by y^2 = x^3 + 1 over Finite Field of size 7
643
+ Via: (Scalar-multiplication endomorphism [3] of Elliptic Curve defined by y^2 = x^3 + 1 over Finite Field of size 7, Scalar-multiplication endomorphism [4] of Elliptic Curve defined by y^2 = x^3 + 1 over Finite Field of size 7)
644
+ sage: m7.degree()
645
+ 49
646
+ sage: m7.inseparable_degree()
647
+ 7
648
+
649
+ A supersingular example::
650
+
651
+ sage: E = EllipticCurve(GF(7), [1,0])
652
+ sage: m3 = E.scalar_multiplication(3)
653
+ sage: m3.inseparable_degree()
654
+ 1
655
+ sage: m4 = E.scalar_multiplication(4)
656
+ sage: m7 = m3 + m4; m7
657
+ Sum morphism:
658
+ From: Elliptic Curve defined by y^2 = x^3 + x over Finite Field of size 7
659
+ To: Elliptic Curve defined by y^2 = x^3 + x over Finite Field of size 7
660
+ Via: (Scalar-multiplication endomorphism [3] of Elliptic Curve defined by y^2 = x^3 + x over Finite Field of size 7, Scalar-multiplication endomorphism [4] of Elliptic Curve defined by y^2 = x^3 + x over Finite Field of size 7)
661
+ sage: m7.inseparable_degree()
662
+ 49
663
+ """
664
+ if self.is_zero():
665
+ raise ValueError('zero morphism is not an isogeny')
666
+
667
+ p = self.base_ring().characteristic()
668
+ if not p:
669
+ return ZZ.one()
670
+
671
+ m = self.degree().valuation(p)
672
+ if not m:
673
+ return ZZ.one()
674
+
675
+ try:
676
+ P = point_of_order(self.domain(), p**m)
677
+ except ValueError:
678
+ # supersingular; every p-isogeny is purely inseparable
679
+ return p**m
680
+
681
+ Q = self._eval(P)
682
+ return order_from_multiple(Q, p**m)