passagemath-schemes 10.8.1a4__cp314-cp314t-macosx_13_0_arm64.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (312) hide show
  1. passagemath_schemes/.dylibs/libflint.22.0.dylib +0 -0
  2. passagemath_schemes/.dylibs/libgmp.10.dylib +0 -0
  3. passagemath_schemes/.dylibs/libgmpxx.4.dylib +0 -0
  4. passagemath_schemes/.dylibs/libmpfr.6.dylib +0 -0
  5. passagemath_schemes/__init__.py +3 -0
  6. passagemath_schemes-10.8.1a4.dist-info/METADATA +203 -0
  7. passagemath_schemes-10.8.1a4.dist-info/METADATA.bak +204 -0
  8. passagemath_schemes-10.8.1a4.dist-info/RECORD +312 -0
  9. passagemath_schemes-10.8.1a4.dist-info/WHEEL +6 -0
  10. passagemath_schemes-10.8.1a4.dist-info/top_level.txt +3 -0
  11. sage/all__sagemath_schemes.py +23 -0
  12. sage/databases/all__sagemath_schemes.py +7 -0
  13. sage/databases/cremona.py +1723 -0
  14. sage/dynamics/all__sagemath_schemes.py +2 -0
  15. sage/dynamics/arithmetic_dynamics/affine_ds.py +1083 -0
  16. sage/dynamics/arithmetic_dynamics/all.py +14 -0
  17. sage/dynamics/arithmetic_dynamics/berkovich_ds.py +1101 -0
  18. sage/dynamics/arithmetic_dynamics/dynamical_semigroup.py +1543 -0
  19. sage/dynamics/arithmetic_dynamics/endPN_automorphism_group.py +2426 -0
  20. sage/dynamics/arithmetic_dynamics/endPN_minimal_model.py +1169 -0
  21. sage/dynamics/arithmetic_dynamics/generic_ds.py +663 -0
  22. sage/dynamics/arithmetic_dynamics/product_projective_ds.py +339 -0
  23. sage/dynamics/arithmetic_dynamics/projective_ds.py +9556 -0
  24. sage/dynamics/arithmetic_dynamics/projective_ds_helper.cpython-314t-darwin.so +0 -0
  25. sage/dynamics/arithmetic_dynamics/projective_ds_helper.pyx +301 -0
  26. sage/dynamics/arithmetic_dynamics/wehlerK3.py +2578 -0
  27. sage/lfunctions/all.py +18 -0
  28. sage/lfunctions/dokchitser.py +727 -0
  29. sage/lfunctions/pari.py +971 -0
  30. sage/lfunctions/zero_sums.cpython-314t-darwin.so +0 -0
  31. sage/lfunctions/zero_sums.pyx +1847 -0
  32. sage/modular/abvar/abvar.py +5132 -0
  33. sage/modular/abvar/abvar_ambient_jacobian.py +414 -0
  34. sage/modular/abvar/abvar_newform.py +246 -0
  35. sage/modular/abvar/all.py +8 -0
  36. sage/modular/abvar/constructor.py +187 -0
  37. sage/modular/abvar/cuspidal_subgroup.py +371 -0
  38. sage/modular/abvar/finite_subgroup.py +896 -0
  39. sage/modular/abvar/homology.py +721 -0
  40. sage/modular/abvar/homspace.py +989 -0
  41. sage/modular/abvar/lseries.py +415 -0
  42. sage/modular/abvar/morphism.py +935 -0
  43. sage/modular/abvar/torsion_point.py +274 -0
  44. sage/modular/abvar/torsion_subgroup.py +741 -0
  45. sage/modular/all.py +43 -0
  46. sage/modular/arithgroup/all.py +20 -0
  47. sage/modular/arithgroup/arithgroup_element.cpython-314t-darwin.so +0 -0
  48. sage/modular/arithgroup/arithgroup_element.pyx +474 -0
  49. sage/modular/arithgroup/arithgroup_generic.py +1406 -0
  50. sage/modular/arithgroup/arithgroup_perm.py +2692 -0
  51. sage/modular/arithgroup/congroup.cpython-314t-darwin.so +0 -0
  52. sage/modular/arithgroup/congroup.pyx +334 -0
  53. sage/modular/arithgroup/congroup_gamma.py +361 -0
  54. sage/modular/arithgroup/congroup_gamma0.py +692 -0
  55. sage/modular/arithgroup/congroup_gamma1.py +659 -0
  56. sage/modular/arithgroup/congroup_gammaH.py +1491 -0
  57. sage/modular/arithgroup/congroup_generic.py +630 -0
  58. sage/modular/arithgroup/congroup_sl2z.py +266 -0
  59. sage/modular/arithgroup/farey_symbol.cpython-314t-darwin.so +0 -0
  60. sage/modular/arithgroup/farey_symbol.pyx +1067 -0
  61. sage/modular/arithgroup/tests.py +425 -0
  62. sage/modular/btquotients/all.py +4 -0
  63. sage/modular/btquotients/btquotient.py +3736 -0
  64. sage/modular/btquotients/pautomorphicform.py +2564 -0
  65. sage/modular/buzzard.py +100 -0
  66. sage/modular/congroup.py +29 -0
  67. sage/modular/congroup_element.py +13 -0
  68. sage/modular/cusps.py +1107 -0
  69. sage/modular/cusps_nf.py +1270 -0
  70. sage/modular/dims.py +571 -0
  71. sage/modular/dirichlet.py +3310 -0
  72. sage/modular/drinfeld_modform/all.py +2 -0
  73. sage/modular/drinfeld_modform/element.py +446 -0
  74. sage/modular/drinfeld_modform/ring.py +773 -0
  75. sage/modular/drinfeld_modform/tutorial.py +236 -0
  76. sage/modular/etaproducts.py +1076 -0
  77. sage/modular/hecke/algebra.py +725 -0
  78. sage/modular/hecke/all.py +19 -0
  79. sage/modular/hecke/ambient_module.py +994 -0
  80. sage/modular/hecke/degenmap.py +119 -0
  81. sage/modular/hecke/element.py +302 -0
  82. sage/modular/hecke/hecke_operator.py +736 -0
  83. sage/modular/hecke/homspace.py +185 -0
  84. sage/modular/hecke/module.py +1744 -0
  85. sage/modular/hecke/morphism.py +139 -0
  86. sage/modular/hecke/submodule.py +970 -0
  87. sage/modular/hypergeometric_misc.cpython-314t-darwin.so +0 -0
  88. sage/modular/hypergeometric_misc.pxd +4 -0
  89. sage/modular/hypergeometric_misc.pyx +166 -0
  90. sage/modular/hypergeometric_motive.py +2020 -0
  91. sage/modular/local_comp/all.py +2 -0
  92. sage/modular/local_comp/liftings.py +292 -0
  93. sage/modular/local_comp/local_comp.py +1070 -0
  94. sage/modular/local_comp/smoothchar.py +1825 -0
  95. sage/modular/local_comp/type_space.py +748 -0
  96. sage/modular/modform/all.py +30 -0
  97. sage/modular/modform/ambient.py +817 -0
  98. sage/modular/modform/ambient_R.py +177 -0
  99. sage/modular/modform/ambient_eps.py +306 -0
  100. sage/modular/modform/ambient_g0.py +120 -0
  101. sage/modular/modform/ambient_g1.py +199 -0
  102. sage/modular/modform/constructor.py +545 -0
  103. sage/modular/modform/cuspidal_submodule.py +708 -0
  104. sage/modular/modform/defaults.py +14 -0
  105. sage/modular/modform/eis_series.py +487 -0
  106. sage/modular/modform/eisenstein_submodule.py +663 -0
  107. sage/modular/modform/element.py +4105 -0
  108. sage/modular/modform/half_integral.py +154 -0
  109. sage/modular/modform/hecke_operator_on_qexp.py +247 -0
  110. sage/modular/modform/j_invariant.py +47 -0
  111. sage/modular/modform/l_series_gross_zagier.py +127 -0
  112. sage/modular/modform/l_series_gross_zagier_coeffs.cpython-314t-darwin.so +0 -0
  113. sage/modular/modform/l_series_gross_zagier_coeffs.pyx +177 -0
  114. sage/modular/modform/notes.py +45 -0
  115. sage/modular/modform/numerical.py +514 -0
  116. sage/modular/modform/periods.py +14 -0
  117. sage/modular/modform/ring.py +1257 -0
  118. sage/modular/modform/space.py +1859 -0
  119. sage/modular/modform/submodule.py +118 -0
  120. sage/modular/modform/tests.py +64 -0
  121. sage/modular/modform/theta.py +110 -0
  122. sage/modular/modform/vm_basis.py +380 -0
  123. sage/modular/modform/weight1.py +221 -0
  124. sage/modular/modform_hecketriangle/abstract_ring.py +1932 -0
  125. sage/modular/modform_hecketriangle/abstract_space.py +2527 -0
  126. sage/modular/modform_hecketriangle/all.py +30 -0
  127. sage/modular/modform_hecketriangle/analytic_type.py +590 -0
  128. sage/modular/modform_hecketriangle/constructor.py +416 -0
  129. sage/modular/modform_hecketriangle/element.py +351 -0
  130. sage/modular/modform_hecketriangle/functors.py +752 -0
  131. sage/modular/modform_hecketriangle/graded_ring.py +541 -0
  132. sage/modular/modform_hecketriangle/graded_ring_element.py +2225 -0
  133. sage/modular/modform_hecketriangle/hecke_triangle_group_element.py +3349 -0
  134. sage/modular/modform_hecketriangle/hecke_triangle_groups.py +1426 -0
  135. sage/modular/modform_hecketriangle/readme.py +1214 -0
  136. sage/modular/modform_hecketriangle/series_constructor.py +580 -0
  137. sage/modular/modform_hecketriangle/space.py +1037 -0
  138. sage/modular/modform_hecketriangle/subspace.py +423 -0
  139. sage/modular/modsym/all.py +17 -0
  140. sage/modular/modsym/ambient.py +3844 -0
  141. sage/modular/modsym/boundary.py +1420 -0
  142. sage/modular/modsym/element.py +336 -0
  143. sage/modular/modsym/g1list.py +178 -0
  144. sage/modular/modsym/ghlist.py +182 -0
  145. sage/modular/modsym/hecke_operator.py +73 -0
  146. sage/modular/modsym/manin_symbol.cpython-314t-darwin.so +0 -0
  147. sage/modular/modsym/manin_symbol.pxd +5 -0
  148. sage/modular/modsym/manin_symbol.pyx +497 -0
  149. sage/modular/modsym/manin_symbol_list.py +1291 -0
  150. sage/modular/modsym/modsym.py +400 -0
  151. sage/modular/modsym/modular_symbols.py +384 -0
  152. sage/modular/modsym/p1list_nf.py +1241 -0
  153. sage/modular/modsym/relation_matrix.py +591 -0
  154. sage/modular/modsym/relation_matrix_pyx.cpython-314t-darwin.so +0 -0
  155. sage/modular/modsym/relation_matrix_pyx.pyx +108 -0
  156. sage/modular/modsym/space.py +2468 -0
  157. sage/modular/modsym/subspace.py +455 -0
  158. sage/modular/modsym/tests.py +376 -0
  159. sage/modular/multiple_zeta.py +2635 -0
  160. sage/modular/multiple_zeta_F_algebra.py +789 -0
  161. sage/modular/overconvergent/all.py +6 -0
  162. sage/modular/overconvergent/genus0.py +1879 -0
  163. sage/modular/overconvergent/hecke_series.py +1187 -0
  164. sage/modular/overconvergent/weightspace.py +776 -0
  165. sage/modular/pollack_stevens/all.py +4 -0
  166. sage/modular/pollack_stevens/distributions.py +874 -0
  167. sage/modular/pollack_stevens/fund_domain.py +1572 -0
  168. sage/modular/pollack_stevens/manin_map.py +856 -0
  169. sage/modular/pollack_stevens/modsym.py +1590 -0
  170. sage/modular/pollack_stevens/padic_lseries.py +417 -0
  171. sage/modular/pollack_stevens/sigma0.py +534 -0
  172. sage/modular/pollack_stevens/space.py +1078 -0
  173. sage/modular/quasimodform/all.py +3 -0
  174. sage/modular/quasimodform/element.py +846 -0
  175. sage/modular/quasimodform/ring.py +826 -0
  176. sage/modular/quatalg/all.py +3 -0
  177. sage/modular/quatalg/brandt.py +1642 -0
  178. sage/modular/ssmod/all.py +8 -0
  179. sage/modular/ssmod/ssmod.py +827 -0
  180. sage/rings/all__sagemath_schemes.py +1 -0
  181. sage/rings/polynomial/all__sagemath_schemes.py +1 -0
  182. sage/rings/polynomial/binary_form_reduce.py +585 -0
  183. sage/schemes/all.py +41 -0
  184. sage/schemes/berkovich/all.py +6 -0
  185. sage/schemes/berkovich/berkovich_cp_element.py +2582 -0
  186. sage/schemes/berkovich/berkovich_space.py +700 -0
  187. sage/schemes/curves/affine_curve.py +2924 -0
  188. sage/schemes/curves/all.py +33 -0
  189. sage/schemes/curves/closed_point.py +434 -0
  190. sage/schemes/curves/constructor.py +397 -0
  191. sage/schemes/curves/curve.py +542 -0
  192. sage/schemes/curves/plane_curve_arrangement.py +1283 -0
  193. sage/schemes/curves/point.py +463 -0
  194. sage/schemes/curves/projective_curve.py +3203 -0
  195. sage/schemes/curves/weighted_projective_curve.py +106 -0
  196. sage/schemes/curves/zariski_vankampen.py +1931 -0
  197. sage/schemes/cyclic_covers/all.py +2 -0
  198. sage/schemes/cyclic_covers/charpoly_frobenius.py +320 -0
  199. sage/schemes/cyclic_covers/constructor.py +137 -0
  200. sage/schemes/cyclic_covers/cycliccover_finite_field.py +1309 -0
  201. sage/schemes/cyclic_covers/cycliccover_generic.py +310 -0
  202. sage/schemes/elliptic_curves/BSD.py +991 -0
  203. sage/schemes/elliptic_curves/Qcurves.py +592 -0
  204. sage/schemes/elliptic_curves/addition_formulas_ring.py +94 -0
  205. sage/schemes/elliptic_curves/all.py +49 -0
  206. sage/schemes/elliptic_curves/cardinality.py +609 -0
  207. sage/schemes/elliptic_curves/cm.py +1103 -0
  208. sage/schemes/elliptic_curves/constructor.py +1530 -0
  209. sage/schemes/elliptic_curves/ec_database.py +175 -0
  210. sage/schemes/elliptic_curves/ell_curve_isogeny.py +3971 -0
  211. sage/schemes/elliptic_curves/ell_egros.py +457 -0
  212. sage/schemes/elliptic_curves/ell_field.py +2837 -0
  213. sage/schemes/elliptic_curves/ell_finite_field.py +3249 -0
  214. sage/schemes/elliptic_curves/ell_generic.py +3760 -0
  215. sage/schemes/elliptic_curves/ell_local_data.py +1207 -0
  216. sage/schemes/elliptic_curves/ell_modular_symbols.py +775 -0
  217. sage/schemes/elliptic_curves/ell_number_field.py +4220 -0
  218. sage/schemes/elliptic_curves/ell_padic_field.py +107 -0
  219. sage/schemes/elliptic_curves/ell_point.py +4944 -0
  220. sage/schemes/elliptic_curves/ell_rational_field.py +7184 -0
  221. sage/schemes/elliptic_curves/ell_tate_curve.py +671 -0
  222. sage/schemes/elliptic_curves/ell_torsion.py +436 -0
  223. sage/schemes/elliptic_curves/ell_wp.py +352 -0
  224. sage/schemes/elliptic_curves/formal_group.py +760 -0
  225. sage/schemes/elliptic_curves/gal_reps.py +1459 -0
  226. sage/schemes/elliptic_curves/gal_reps_number_field.py +1663 -0
  227. sage/schemes/elliptic_curves/gp_simon.py +152 -0
  228. sage/schemes/elliptic_curves/heegner.py +7328 -0
  229. sage/schemes/elliptic_curves/height.py +2108 -0
  230. sage/schemes/elliptic_curves/hom.py +1788 -0
  231. sage/schemes/elliptic_curves/hom_composite.py +1084 -0
  232. sage/schemes/elliptic_curves/hom_fractional.py +544 -0
  233. sage/schemes/elliptic_curves/hom_frobenius.py +522 -0
  234. sage/schemes/elliptic_curves/hom_scalar.py +531 -0
  235. sage/schemes/elliptic_curves/hom_sum.py +681 -0
  236. sage/schemes/elliptic_curves/hom_velusqrt.py +1290 -0
  237. sage/schemes/elliptic_curves/homset.py +271 -0
  238. sage/schemes/elliptic_curves/isogeny_class.py +1523 -0
  239. sage/schemes/elliptic_curves/isogeny_small_degree.py +2797 -0
  240. sage/schemes/elliptic_curves/jacobian.py +247 -0
  241. sage/schemes/elliptic_curves/kodaira_symbol.py +344 -0
  242. sage/schemes/elliptic_curves/kraus.py +1014 -0
  243. sage/schemes/elliptic_curves/lseries_ell.py +915 -0
  244. sage/schemes/elliptic_curves/mod5family.py +105 -0
  245. sage/schemes/elliptic_curves/mod_poly.py +197 -0
  246. sage/schemes/elliptic_curves/mod_sym_num.cpython-314t-darwin.so +0 -0
  247. sage/schemes/elliptic_curves/mod_sym_num.pyx +3796 -0
  248. sage/schemes/elliptic_curves/modular_parametrization.py +305 -0
  249. sage/schemes/elliptic_curves/padic_lseries.py +1793 -0
  250. sage/schemes/elliptic_curves/padics.py +1816 -0
  251. sage/schemes/elliptic_curves/period_lattice.py +2234 -0
  252. sage/schemes/elliptic_curves/period_lattice_region.cpython-314t-darwin.so +0 -0
  253. sage/schemes/elliptic_curves/period_lattice_region.pyx +722 -0
  254. sage/schemes/elliptic_curves/saturation.py +716 -0
  255. sage/schemes/elliptic_curves/sha_tate.py +1158 -0
  256. sage/schemes/elliptic_curves/weierstrass_morphism.py +1117 -0
  257. sage/schemes/elliptic_curves/weierstrass_transform.py +200 -0
  258. sage/schemes/hyperelliptic_curves/all.py +6 -0
  259. sage/schemes/hyperelliptic_curves/constructor.py +369 -0
  260. sage/schemes/hyperelliptic_curves/hyperelliptic_finite_field.py +1948 -0
  261. sage/schemes/hyperelliptic_curves/hyperelliptic_g2.py +192 -0
  262. sage/schemes/hyperelliptic_curves/hyperelliptic_generic.py +936 -0
  263. sage/schemes/hyperelliptic_curves/hyperelliptic_padic_field.py +1332 -0
  264. sage/schemes/hyperelliptic_curves/hyperelliptic_rational_field.py +84 -0
  265. sage/schemes/hyperelliptic_curves/invariants.py +410 -0
  266. sage/schemes/hyperelliptic_curves/jacobian_endomorphism_utils.py +312 -0
  267. sage/schemes/hyperelliptic_curves/jacobian_g2.py +32 -0
  268. sage/schemes/hyperelliptic_curves/jacobian_generic.py +437 -0
  269. sage/schemes/hyperelliptic_curves/jacobian_homset.py +186 -0
  270. sage/schemes/hyperelliptic_curves/jacobian_morphism.py +878 -0
  271. sage/schemes/hyperelliptic_curves/kummer_surface.py +99 -0
  272. sage/schemes/hyperelliptic_curves/mestre.py +302 -0
  273. sage/schemes/hyperelliptic_curves/monsky_washnitzer.py +3863 -0
  274. sage/schemes/jacobians/abstract_jacobian.py +277 -0
  275. sage/schemes/jacobians/all.py +2 -0
  276. sage/schemes/overview.py +161 -0
  277. sage/schemes/plane_conics/all.py +22 -0
  278. sage/schemes/plane_conics/con_field.py +1296 -0
  279. sage/schemes/plane_conics/con_finite_field.py +158 -0
  280. sage/schemes/plane_conics/con_number_field.py +456 -0
  281. sage/schemes/plane_conics/con_rational_field.py +406 -0
  282. sage/schemes/plane_conics/con_rational_function_field.py +581 -0
  283. sage/schemes/plane_conics/constructor.py +249 -0
  284. sage/schemes/plane_quartics/all.py +2 -0
  285. sage/schemes/plane_quartics/quartic_constructor.py +71 -0
  286. sage/schemes/plane_quartics/quartic_generic.py +53 -0
  287. sage/schemes/riemann_surfaces/all.py +1 -0
  288. sage/schemes/riemann_surfaces/riemann_surface.py +4177 -0
  289. sage_wheels/share/cremona/cremona_mini.db +0 -0
  290. sage_wheels/share/ellcurves/rank0 +30427 -0
  291. sage_wheels/share/ellcurves/rank1 +31871 -0
  292. sage_wheels/share/ellcurves/rank10 +6 -0
  293. sage_wheels/share/ellcurves/rank11 +6 -0
  294. sage_wheels/share/ellcurves/rank12 +1 -0
  295. sage_wheels/share/ellcurves/rank14 +1 -0
  296. sage_wheels/share/ellcurves/rank15 +1 -0
  297. sage_wheels/share/ellcurves/rank17 +1 -0
  298. sage_wheels/share/ellcurves/rank19 +1 -0
  299. sage_wheels/share/ellcurves/rank2 +2388 -0
  300. sage_wheels/share/ellcurves/rank20 +1 -0
  301. sage_wheels/share/ellcurves/rank21 +1 -0
  302. sage_wheels/share/ellcurves/rank22 +1 -0
  303. sage_wheels/share/ellcurves/rank23 +1 -0
  304. sage_wheels/share/ellcurves/rank24 +1 -0
  305. sage_wheels/share/ellcurves/rank28 +1 -0
  306. sage_wheels/share/ellcurves/rank3 +836 -0
  307. sage_wheels/share/ellcurves/rank4 +10 -0
  308. sage_wheels/share/ellcurves/rank5 +5 -0
  309. sage_wheels/share/ellcurves/rank6 +5 -0
  310. sage_wheels/share/ellcurves/rank7 +5 -0
  311. sage_wheels/share/ellcurves/rank8 +6 -0
  312. sage_wheels/share/ellcurves/rank9 +7 -0
@@ -0,0 +1,681 @@
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)
280
+
281
+ P,Q = self.domain().change_ring(F).torsion_basis(l**m)
282
+ if self.is_endomorphism():
283
+ R,S = P,Q
284
+ else:
285
+ R,S = self.codomain().change_ring(F).torsion_basis(l**m)
286
+ M = self.matrix_on_subgroup((P,Q), (R,S))
287
+ g = ZZ(gcd(M.list())).p_primary_part(l)
288
+ if g > 1:
289
+ scalar *= g
290
+ M = (M.change_ring(ZZ) / g).change_ring(M.base_ring())
291
+ K = M.left_kernel_matrix()
292
+ for row in K:
293
+ u,v = map(ZZ, row)
294
+ pt = u*P + v*Q
295
+ pt.set_order(row.additive_order())
296
+ ker.append(pt)
297
+
298
+ from sage.schemes.elliptic_curves.hom_composite import EllipticCurveHom_composite
299
+ phi = EllipticCurveHom_composite(self.domain(), [])
300
+
301
+ if scalar != 1:
302
+ phi *= phi.codomain().scalar_multiplication(scalar)
303
+
304
+ while ker:
305
+ K = ker.pop(0)
306
+
307
+ (l,e), = K.order().factor()
308
+ for i in reversed(range(e)):
309
+ Kl = l**i * K
310
+ Kl.set_order(l)
311
+
312
+ from sage.groups.generic import multiples
313
+ from sage.misc.misc_c import prod
314
+ x = polygen(Kl.base_ring())
315
+ poly = prod(x - T.x() for T in multiples(Kl, l//2, Kl))
316
+ poly = poly.change_ring(self.base_ring())
317
+
318
+ psi = phi.codomain().isogeny(poly)
319
+ phi = psi * phi
320
+ K = psi._eval(K)
321
+ ker = [psi._eval(P) for P in ker]
322
+
323
+ if insep:
324
+ frob = phi.codomain().frobenius_isogeny(insep)
325
+ phi = frob * phi
326
+
327
+ from sage.schemes.elliptic_curves.hom import find_post_isomorphism
328
+ iso = find_post_isomorphism(phi, self)
329
+ return iso * phi
330
+
331
+ # EllipticCurveHom methods
332
+
333
+ def _degree_bounds(self):
334
+ r"""
335
+ Return a lower and upper bound on the degree of this sum morphism.
336
+
337
+ EXAMPLES::
338
+
339
+ sage: E = EllipticCurve(GF(307), [5,5])
340
+ sage: phi = E.isogenies_prime_degree(3)[0]; phi
341
+ 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
342
+ sage: psi = next(iso*psi for psi in E.isogenies_prime_degree(43)
343
+ ....: for iso in psi.codomain().isomorphisms(phi.codomain())); psi
344
+ 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
345
+ sage: (phi + psi)._degree_bounds()
346
+ (24, 68)
347
+ sage: (phi + psi).degree()
348
+ 31
349
+ sage: (phi - phi)._degree_bounds()
350
+ (0, 12)
351
+ sage: (phi - phi).degree()
352
+ 0
353
+
354
+ ::
355
+
356
+ sage: E = EllipticCurve(GF(443), [1,1])
357
+ sage: pi = E.frobenius_endomorphism()
358
+ sage: m1 = E.scalar_multiplication(1)
359
+ sage: (pi - m1)._degree_bounds()
360
+ (402, 486)
361
+ sage: (pi - m1)._degree_bounds() == Hasse_bounds(443)
362
+ True
363
+ sage: (pi - m1).degree()
364
+ 433
365
+
366
+ ALGORITHM: Repeated application of the Cauchy-Schwarz inequality,
367
+ here in the form
368
+ `|\deg(f+g) - \deg(f) - \deg(g)| \leq 2\sqrt{\deg(f)\cdot\deg(g)}`.
369
+ See for instance Lemma V.1.2 of [Sil2009]_.
370
+ """
371
+ lo, hi = ZZ.zero(), ZZ.zero()
372
+ for phi in self._phis:
373
+ m = (hi * phi.degree()).isqrt()
374
+ hi += phi.degree() + 2*m
375
+ lo += phi.degree() - 2*m
376
+ lo = max(lo, 0)
377
+ return lo, hi
378
+
379
+ def _compute_degree(self):
380
+ r"""
381
+ Internal method to compute and cache the degree of this sum morphism
382
+ (and its dual).
383
+
384
+ ALGORITHM: Evaluate the composition with the dual on points of small
385
+ order and solve logarithms to eventually recover the degree using CRT.
386
+ (This is essentially Schoof's algorithm, applied to a scalar.)
387
+
388
+ EXAMPLES::
389
+
390
+ sage: E = EllipticCurve(GF(101), [5,5])
391
+ sage: phi = E.isogenies_prime_degree(7)[0]
392
+ sage: isog = phi + phi
393
+ sage: print(isog._degree)
394
+ None
395
+ sage: isog._compute_degree()
396
+ sage: isog._degree
397
+ 28
398
+
399
+ ::
400
+
401
+ sage: E = EllipticCurve(GF(443), [1,1])
402
+ sage: pi = E.frobenius_endomorphism()
403
+ sage: m1 = E.scalar_multiplication(1)
404
+ sage: endo = pi - m1
405
+ sage: print(endo._degree)
406
+ None
407
+ sage: endo._compute_degree()
408
+ sage: endo._degree
409
+ 433
410
+ sage: endo.dual()._degree
411
+ 433
412
+ """
413
+ if self._degree is not None:
414
+ return
415
+ if not self._phis:
416
+ self._degree = ZZ.zero()
417
+ elif len(self._phis) == 1:
418
+ self._degree = self._phis[0].degree()
419
+ else:
420
+ #TODO In some cases it would probably be faster to simply
421
+ # compute the kernel polynomial using the addition formulas?
422
+ from sage.rings.finite_rings.integer_mod import Mod
423
+
424
+ lo, hi = self._degree_bounds()
425
+ M = hi - lo + 1
426
+ rem = Mod(0,1)
427
+ for l in Primes():
428
+ if rem.modulus() >= M:
429
+ break
430
+ try:
431
+ P = point_of_order(self._domain, l)
432
+ except ValueError:
433
+ continue # supersingular and l == p
434
+
435
+ Q = self.dual()._eval(self._eval(P))
436
+ d = discrete_log(Q, P, ord=l, operation='+')
437
+ rem = rem.crt(Mod(d-lo, l))
438
+
439
+ self._degree = lo + rem.lift()
440
+ self.dual()._degree = self._degree
441
+
442
+ @staticmethod
443
+ def _comparison_impl(left, right, op):
444
+ r"""
445
+ Compare a sum morphism to another elliptic-curve morphism.
446
+
447
+ Called by :meth:`EllipticCurveHom._richcmp_`.
448
+
449
+ If possible, we use
450
+ :func:`~sage.schemes.elliptic_curves.hom.compare_via_evaluation`.
451
+ The complexity in that case is polynomial in the logarithm of
452
+ the degree.
453
+
454
+ TESTS::
455
+
456
+ sage: from sage.schemes.elliptic_curves.hom_sum import EllipticCurveHom_sum
457
+ sage: E = EllipticCurve(GF(419^2), [1,0])
458
+ sage: i = E.automorphisms()[-1]
459
+ sage: j = E.frobenius_isogeny()
460
+ sage: i + j == j + i # needs sage.symbolic
461
+ True
462
+ """
463
+ from sage.structure.richcmp import op_EQ
464
+ if op != op_EQ:
465
+ return NotImplemented
466
+ try:
467
+ return compare_via_evaluation(left, right)
468
+ except NotImplementedError:
469
+ return NotImplemented
470
+
471
+ def degree(self):
472
+ r"""
473
+ Return the degree of this sum morphism.
474
+
475
+ EXAMPLES::
476
+
477
+ sage: E = EllipticCurve(GF(101), [5,5])
478
+ sage: phi = E.isogenies_prime_degree(7)[0]
479
+ sage: (phi + phi).degree()
480
+ 28
481
+
482
+ This method yields a simple toy point-counting algorithm::
483
+
484
+ sage: E = EllipticCurve(GF(101), [5,5])
485
+ sage: m1 = E.scalar_multiplication(1)
486
+ sage: pi = E.frobenius_endomorphism()
487
+ sage: (pi - m1).degree()
488
+ 119
489
+ sage: E.count_points()
490
+ 119
491
+
492
+ ALGORITHM: Essentially Schoof's algorithm; see :meth:`_compute_degree`.
493
+ """
494
+ if self._degree is None:
495
+ self._compute_degree()
496
+ return self._degree
497
+
498
+ def rational_maps(self):
499
+ r"""
500
+ Return the rational maps of this sum morphism.
501
+
502
+ EXAMPLES::
503
+
504
+ sage: E = EllipticCurve(GF(101), [5,5])
505
+ sage: phi = E.isogenies_prime_degree(7)[0]
506
+ sage: (phi + phi).rational_maps()
507
+ ((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),
508
+ (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))
509
+
510
+ ALGORITHM: :meth:`to_isogeny_chain`.
511
+ """
512
+ #TODO In some cases it would probably be faster to compute this
513
+ # directly using the addition formulas?
514
+ return self.to_isogeny_chain().rational_maps()
515
+
516
+ def x_rational_map(self):
517
+ r"""
518
+ Return the `x`-coordinate rational map of this sum morphism.
519
+
520
+ EXAMPLES::
521
+
522
+ sage: E = EllipticCurve(GF(101), [5,5])
523
+ sage: phi = E.isogenies_prime_degree(7)[0]
524
+ sage: (phi + phi).x_rational_map()
525
+ (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)
526
+
527
+ ALGORITHM: :meth:`to_isogeny_chain`.
528
+ """
529
+ #TODO In some cases it would probably be faster to compute this
530
+ # directly using the addition formulas?
531
+ return self.to_isogeny_chain().x_rational_map()
532
+
533
+ def kernel_polynomial(self):
534
+ r"""
535
+ Return the kernel polynomial of this sum morphism.
536
+
537
+ EXAMPLES::
538
+
539
+ sage: E = EllipticCurve(GF(101), [5,5])
540
+ sage: phi = E.isogenies_prime_degree(7)[0]
541
+ sage: (phi + phi).kernel_polynomial()
542
+ 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
543
+
544
+ ::
545
+
546
+ sage: E = EllipticCurve(GF(11), [5,5])
547
+ sage: pi = E.frobenius_endomorphism()
548
+ sage: m1 = E.scalar_multiplication(1)
549
+ sage: (pi - m1).kernel_polynomial()
550
+ x^9 + 7*x^8 + 2*x^7 + 4*x^6 + 10*x^4 + 4*x^3 + 9*x^2 + 7*x
551
+
552
+ ALGORITHM: :meth:`to_isogeny_chain`.
553
+ """
554
+ #TODO In some cases it would probably be faster to compute this
555
+ # directly using the addition formulas?
556
+ return self.to_isogeny_chain().kernel_polynomial()
557
+
558
+ def scaling_factor(self):
559
+ r"""
560
+ Return the Weierstrass scaling factor associated to this
561
+ sum morphism.
562
+
563
+ The scaling factor is the constant `u` (in the base field)
564
+ such that `\varphi^* \omega_2 = u \omega_1`, where
565
+ `\varphi: E_1\to E_2` is this morphism and `\omega_i` are
566
+ the standard Weierstrass differentials on `E_i` defined by
567
+ `\mathrm dx/(2y+a_1x+a_3)`.
568
+
569
+ EXAMPLES::
570
+
571
+ sage: E = EllipticCurve(GF(101), [5,5])
572
+ sage: phi = E.isogenies_prime_degree(7)[0]
573
+ sage: phi.scaling_factor()
574
+ 84
575
+ sage: (phi + phi).scaling_factor()
576
+ 67
577
+
578
+ ALGORITHM: The scaling factor is additive under addition
579
+ of elliptic-curve morphisms, so we simply add together the
580
+ scaling factors of the :meth:`summands`.
581
+ """
582
+ return sum(phi.scaling_factor() for phi in self._phis)
583
+
584
+ @cached_method
585
+ def dual(self):
586
+ r"""
587
+ Return the dual of this sum morphism.
588
+
589
+ EXAMPLES::
590
+
591
+ sage: E = EllipticCurve(GF(101), [5,5])
592
+ sage: phi = E.isogenies_prime_degree(7)[0]
593
+ sage: (phi + phi).dual()
594
+ Sum morphism:
595
+ From: Elliptic Curve defined by y^2 = x^3 + 12*x + 98 over Finite Field of size 101
596
+ To: Elliptic Curve defined by y^2 = x^3 + 5*x + 5 over Finite Field of size 101
597
+ 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)
598
+ sage: (phi + phi).dual() == phi.dual() + phi.dual() # needs sage.symbolic
599
+ True
600
+
601
+ ::
602
+
603
+ sage: E = EllipticCurve(GF(431^2), [1,0])
604
+ sage: iota = E.automorphisms()[2]
605
+ sage: m2 = E.scalar_multiplication(2)
606
+ sage: endo = m2 + iota
607
+ sage: endo.dual()
608
+ Sum morphism:
609
+ From: Elliptic Curve defined by y^2 = x^3 + x over Finite Field in z2 of size 431^2
610
+ To: Elliptic Curve defined by y^2 = x^3 + x over Finite Field in z2 of size 431^2
611
+ 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
612
+ Via: (u,r,s,t) = (8*z2 + 427, 0, 0, 0))
613
+ sage: endo.dual() == (m2 - iota) # needs sage.symbolic
614
+ True
615
+
616
+ ALGORITHM: Taking the dual distributes over addition.
617
+ """
618
+ psi = EllipticCurveHom_sum((phi.dual() for phi in self._phis),
619
+ domain=self._codomain, codomain=self._domain)
620
+ psi._degree = self._degree
621
+ if self.trace.is_in_cache():
622
+ psi.trace.set_cache(-self.trace.cache)
623
+ psi.dual.set_cache(self)
624
+ return psi
625
+
626
+ @cached_method
627
+ def inseparable_degree(self):
628
+ r"""
629
+ Compute the inseparable degree of this sum morphism.
630
+
631
+ EXAMPLES::
632
+
633
+ sage: E = EllipticCurve(GF(7), [0,1])
634
+ sage: m3 = E.scalar_multiplication(3)
635
+ sage: m3.inseparable_degree()
636
+ 1
637
+ sage: m4 = E.scalar_multiplication(4)
638
+ sage: m7 = m3 + m4; m7
639
+ Sum morphism:
640
+ From: Elliptic Curve defined by y^2 = x^3 + 1 over Finite Field of size 7
641
+ To: Elliptic Curve defined by y^2 = x^3 + 1 over Finite Field of size 7
642
+ 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)
643
+ sage: m7.degree()
644
+ 49
645
+ sage: m7.inseparable_degree()
646
+ 7
647
+
648
+ A supersingular example::
649
+
650
+ sage: E = EllipticCurve(GF(7), [1,0])
651
+ sage: m3 = E.scalar_multiplication(3)
652
+ sage: m3.inseparable_degree()
653
+ 1
654
+ sage: m4 = E.scalar_multiplication(4)
655
+ sage: m7 = m3 + m4; m7
656
+ Sum morphism:
657
+ From: Elliptic Curve defined by y^2 = x^3 + x over Finite Field of size 7
658
+ To: Elliptic Curve defined by y^2 = x^3 + x over Finite Field of size 7
659
+ 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)
660
+ sage: m7.inseparable_degree()
661
+ 49
662
+ """
663
+ if self.is_zero():
664
+ raise ValueError('zero morphism is not an isogeny')
665
+
666
+ p = self.base_ring().characteristic()
667
+ if not p:
668
+ return ZZ.one()
669
+
670
+ m = self.degree().valuation(p)
671
+ if not m:
672
+ return ZZ.one()
673
+
674
+ try:
675
+ P = point_of_order(self.domain(), p**m)
676
+ except ValueError:
677
+ # supersingular; every p-isogeny is purely inseparable
678
+ return p**m
679
+
680
+ Q = self._eval(P)
681
+ return order_from_multiple(Q, p**m)