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,1270 @@
1
+ # sage_setup: distribution = sagemath-schemes
2
+ # sage.doctest: needs sage.rings.number_field
3
+ r"""
4
+ The set `\mathbb{P}^1(K)` of cusps of a number field `K`
5
+
6
+ AUTHORS:
7
+
8
+ - Maite Aranes (2009): Initial version
9
+
10
+ EXAMPLES:
11
+
12
+ The space of cusps over a number field k::
13
+
14
+ sage: x = polygen(ZZ, 'x')
15
+ sage: k.<a> = NumberField(x^2 + 5)
16
+ sage: kCusps = NFCusps(k); kCusps
17
+ Set of all cusps of Number Field in a with defining polynomial x^2 + 5
18
+ sage: kCusps is NFCusps(k)
19
+ True
20
+
21
+ Define a cusp over a number field::
22
+
23
+ sage: NFCusp(k, a, 2/(a+1))
24
+ Cusp [a - 5: 2] of Number Field in a with defining polynomial x^2 + 5
25
+ sage: kCusps((a,2))
26
+ Cusp [a: 2] of Number Field in a with defining polynomial x^2 + 5
27
+ sage: NFCusp(k,oo)
28
+ Cusp Infinity of Number Field in a with defining polynomial x^2 + 5
29
+
30
+ Different operations with cusps over a number field::
31
+
32
+ sage: alpha = NFCusp(k, 3, 1/a + 2); alpha
33
+ Cusp [a + 10: 7] of Number Field in a with defining polynomial x^2 + 5
34
+ sage: alpha.numerator()
35
+ a + 10
36
+ sage: alpha.denominator()
37
+ 7
38
+ sage: alpha.ideal()
39
+ Fractional ideal (7, a + 3)
40
+ sage: M = alpha.ABmatrix(); M # random
41
+ [a + 10, 2*a + 6, 7, a + 5]
42
+ sage: NFCusp(k, oo).apply(M)
43
+ Cusp [a + 10: 7] of Number Field in a with defining polynomial x^2 + 5
44
+
45
+ Check Gamma0(N)-equivalence of cusps::
46
+
47
+ sage: N = k.ideal(3)
48
+ sage: alpha = NFCusp(k, 3, a + 1)
49
+ sage: beta = kCusps((2, a - 3))
50
+ sage: alpha.is_Gamma0_equivalent(beta, N)
51
+ True
52
+
53
+ Obtain transformation matrix for equivalent cusps::
54
+
55
+ sage: t, M = alpha.is_Gamma0_equivalent(beta, N, Transformation=True)
56
+ sage: M[2] in N
57
+ True
58
+ sage: M[0]*M[3] - M[1]*M[2] == 1
59
+ True
60
+ sage: alpha.apply(M) == beta
61
+ True
62
+
63
+ List representatives for Gamma_0(N) - equivalence classes of cusps::
64
+
65
+ sage: Gamma0_NFCusps(N)
66
+ [Cusp [0: 1] of Number Field in a with defining polynomial x^2 + 5,
67
+ Cusp [1: 3] of Number Field in a with defining polynomial x^2 + 5,
68
+ ...]
69
+ """
70
+ # ****************************************************************************
71
+ # Copyright (C) 2009, Maite Aranes <M.T.Aranes@warwick.ac.uk>
72
+ #
73
+ # Distributed under the terms of the GNU General Public License (GPL)
74
+ # https://www.gnu.org/licenses/
75
+ # ****************************************************************************
76
+ from typing import Any
77
+
78
+ from sage.misc.cachefunc import cached_method, cached_function
79
+ from sage.structure.parent import Parent
80
+ from sage.structure.element import Element, InfinityElement
81
+ from sage.structure.richcmp import richcmp, rich_to_bool
82
+ from sage.structure.unique_representation import UniqueRepresentation
83
+
84
+
85
+ @cached_function
86
+ def list_of_representatives(N):
87
+ """
88
+ Return a list of ideals, coprime to the ideal ``N``, representatives of
89
+ the ideal classes of the corresponding number field.
90
+
91
+ .. NOTE::
92
+
93
+ This list, used every time we check `\\Gamma_0(N)` - equivalence of
94
+ cusps, is cached.
95
+
96
+ INPUT:
97
+
98
+ - ``N`` -- an ideal of a number field
99
+
100
+ OUTPUT:
101
+
102
+ A list of ideals coprime to the ideal ``N``, such that they are
103
+ representatives of all the ideal classes of the number field.
104
+
105
+ EXAMPLES::
106
+
107
+ sage: from sage.modular.cusps_nf import list_of_representatives
108
+ sage: x = polygen(ZZ, 'x')
109
+ sage: k.<a> = NumberField(x^4 + 13*x^3 - 11)
110
+ sage: N = k.ideal(713, a + 208)
111
+ sage: L = list_of_representatives(N); L
112
+ (Fractional ideal (1),
113
+ Fractional ideal (47, a - 9),
114
+ Fractional ideal (53, a - 16))
115
+ """
116
+ return NFCusps_ideal_reps_for_levelN(N)[0]
117
+
118
+
119
+ @cached_function
120
+ def NFCusps(number_field):
121
+ r"""
122
+ The set of cusps of a number field `K`, i.e. `\mathbb{P}^1(K)`.
123
+
124
+ INPUT:
125
+
126
+ - ``number_field`` -- a number field
127
+
128
+ OUTPUT: the set of cusps over the given number field
129
+
130
+ EXAMPLES::
131
+
132
+ sage: x = polygen(ZZ, 'x')
133
+ sage: k.<a> = NumberField(x^2 + 5)
134
+ sage: kCusps = NFCusps(k); kCusps
135
+ Set of all cusps of Number Field in a with defining polynomial x^2 + 5
136
+ sage: kCusps is NFCusps(k)
137
+ True
138
+
139
+ Saving and loading works::
140
+
141
+ sage: loads(kCusps.dumps()) == kCusps
142
+ True
143
+ """
144
+ return NFCuspsSpace(number_field)
145
+
146
+
147
+ # *************************************************************************
148
+ # NFCuspsSpace class *
149
+ # *************************************************************************
150
+
151
+
152
+ class NFCuspsSpace(UniqueRepresentation, Parent):
153
+ """
154
+ The set of cusps of a number field. See ``NFCusps`` for full documentation.
155
+
156
+ EXAMPLES::
157
+
158
+ sage: x = polygen(ZZ, 'x')
159
+ sage: k.<a> = NumberField(x^2 + 5)
160
+ sage: kCusps = NFCusps(k); kCusps
161
+ Set of all cusps of Number Field in a with defining polynomial x^2 + 5
162
+ """
163
+ def __init__(self, number_field):
164
+ """
165
+ See ``NFCusps`` for full documentation.
166
+
167
+ EXAMPLES::
168
+
169
+ sage: x = polygen(ZZ, 'x')
170
+ sage: k.<a> = NumberField(x^3 + x^2 + 13)
171
+ sage: kCusps = NFCusps(k); kCusps
172
+ Set of all cusps of Number Field in a with defining polynomial x^3 + x^2 + 13
173
+ """
174
+ self.__number_field = number_field
175
+ Parent.__init__(self, self)
176
+
177
+ def __eq__(self, right):
178
+ """
179
+ Return equality only if right is the set of cusps for the same field.
180
+
181
+ EXAMPLES::
182
+
183
+ sage: x = polygen(ZZ, 'x')
184
+ sage: k.<a> = NumberField(x^2 + 5)
185
+ sage: L.<a> = NumberField(x^2 + 23)
186
+ sage: kCusps = NFCusps(k); kCusps
187
+ Set of all cusps of Number Field in a with defining polynomial x^2 + 5
188
+ sage: LCusps = NFCusps(L); LCusps
189
+ Set of all cusps of Number Field in a with defining polynomial x^2 + 23
190
+ sage: kCusps == NFCusps(k)
191
+ True
192
+ sage: LCusps == NFCusps(L)
193
+ True
194
+ sage: LCusps == kCusps
195
+ False
196
+ """
197
+ if not isinstance(right, NFCuspsSpace):
198
+ return False
199
+ return self.number_field() == right.number_field()
200
+
201
+ def __ne__(self, right):
202
+ """
203
+ Check that ``self`` is not equal to ``right``.
204
+
205
+ EXAMPLES::
206
+
207
+ sage: x = polygen(ZZ, 'x')
208
+ sage: k.<a> = NumberField(x^2 + 5)
209
+ sage: L.<a> = NumberField(x^2 + 23)
210
+ sage: kCusps = NFCusps(k); kCusps
211
+ Set of all cusps of Number Field in a with defining polynomial x^2 + 5
212
+ sage: LCusps = NFCusps(L); LCusps
213
+ Set of all cusps of Number Field in a with defining polynomial x^2 + 23
214
+ sage: kCusps != NFCusps(k)
215
+ False
216
+ sage: LCusps != NFCusps(L)
217
+ False
218
+ sage: LCusps != kCusps
219
+ True
220
+ """
221
+ return not (self == right)
222
+
223
+ def _repr_(self):
224
+ """
225
+ String representation of the set of cusps of a number field.
226
+
227
+ EXAMPLES::
228
+
229
+ sage: x = polygen(ZZ, 'x')
230
+ sage: k.<a> = NumberField(x^2 + 2)
231
+ sage: kCusps = NFCusps(k)
232
+ sage: kCusps
233
+ Set of all cusps of Number Field in a with defining polynomial x^2 + 2
234
+ sage: kCusps._repr_()
235
+ 'Set of all cusps of Number Field in a with defining polynomial x^2 + 2'
236
+ sage: kCusps.rename('Number Field Cusps'); kCusps
237
+ Number Field Cusps
238
+ sage: kCusps.rename(); kCusps
239
+ Set of all cusps of Number Field in a with defining polynomial x^2 + 2
240
+ """
241
+ return "Set of all cusps of %s" % self.number_field()
242
+
243
+ def _latex_(self):
244
+ r"""
245
+ Return latex representation of ``self``.
246
+
247
+ EXAMPLES::
248
+
249
+ sage: x = polygen(ZZ, 'x')
250
+ sage: k.<a> = NumberField(x^2 + 5)
251
+ sage: kCusps = NFCusps(k)
252
+ sage: latex(kCusps) # indirect doctest
253
+ \mathbf{P}^1(\Bold{Q}[a]/(a^{2} + 5))
254
+ """
255
+ return r"\mathbf{P}^1(%s)" % self.number_field()._latex_()
256
+
257
+ def __call__(self, x):
258
+ """
259
+ Convert x into the set of cusps of a number field.
260
+
261
+ EXAMPLES::
262
+
263
+ sage: x = polygen(ZZ, 'x')
264
+ sage: k.<a> = NumberField(x^2 + 5)
265
+ sage: kCusps = NFCusps(k)
266
+ sage: c = kCusps(a,2)
267
+ Traceback (most recent call last):
268
+ ...
269
+ TypeError: ...__call__() takes 2 positional arguments but 3 were given
270
+
271
+ ::
272
+
273
+ sage: c = kCusps((a,2)); c
274
+ Cusp [a: 2] of Number Field in a with defining polynomial x^2 + 5
275
+ sage: kCusps(2/a)
276
+ Cusp [-2*a: 5] of Number Field in a with defining polynomial x^2 + 5
277
+ sage: kCusps(oo)
278
+ Cusp Infinity of Number Field in a with defining polynomial x^2 + 5
279
+ """
280
+ return NFCusp(self.number_field(), x, parent=self)
281
+
282
+ @cached_method
283
+ def zero(self):
284
+ """
285
+ Return the zero cusp.
286
+
287
+ .. NOTE::
288
+
289
+ This method just exists to make some general algorithms work.
290
+ It is not intended that the returned cusp is an additive
291
+ neutral element.
292
+
293
+ EXAMPLES::
294
+
295
+ sage: x = polygen(ZZ, 'x')
296
+ sage: k.<a> = NumberField(x^2 + 5)
297
+ sage: kCusps = NFCusps(k)
298
+ sage: kCusps.zero()
299
+ Cusp [0: 1] of Number Field in a with defining polynomial x^2 + 5
300
+ """
301
+ return self(0)
302
+
303
+ def number_field(self):
304
+ """
305
+ Return the number field that this set of cusps is attached to.
306
+
307
+ EXAMPLES::
308
+
309
+ sage: x = polygen(ZZ, 'x')
310
+ sage: k.<a> = NumberField(x^2 + 1)
311
+ sage: kCusps = NFCusps(k)
312
+ sage: kCusps.number_field()
313
+ Number Field in a with defining polynomial x^2 + 1
314
+ """
315
+ return self.__number_field
316
+
317
+ # *************************************************************************
318
+ # NFCusp class *
319
+ # *************************************************************************
320
+
321
+
322
+ class NFCusp(Element):
323
+ r"""
324
+ Create a number field cusp, i.e., an element of `\mathbb{P}^1(k)`.
325
+
326
+ A cusp on a number field is either an element of the field or infinity,
327
+ i.e., an element of the projective line over the number field. It is
328
+ stored as a pair (a,b), where a, b are integral elements of the number
329
+ field.
330
+
331
+ INPUT:
332
+
333
+ - ``number_field`` -- the number field over which the cusp is defined
334
+
335
+ - ``a`` -- it can be a number field element (integral or not), or
336
+ a number field cusp
337
+
338
+ - ``b`` -- (optional) when present, it must be either Infinity or
339
+ coercible to an element of the number field
340
+
341
+ - ``lreps`` -- (optional) a list of chosen representatives for all the
342
+ ideal classes of the field. When given, the representative of the cusp
343
+ will be changed so its associated ideal is one of the ideals in the list.
344
+
345
+ OUTPUT:
346
+
347
+ ``[a: b]`` -- a number field cusp.
348
+
349
+ EXAMPLES::
350
+
351
+ sage: x = polygen(ZZ, 'x')
352
+ sage: k.<a> = NumberField(x^2 + 5)
353
+ sage: NFCusp(k, a, 2)
354
+ Cusp [a: 2] of Number Field in a with defining polynomial x^2 + 5
355
+ sage: NFCusp(k, (a,2))
356
+ Cusp [a: 2] of Number Field in a with defining polynomial x^2 + 5
357
+ sage: NFCusp(k, a, 2/(a+1))
358
+ Cusp [a - 5: 2] of Number Field in a with defining polynomial x^2 + 5
359
+
360
+ Cusp Infinity:
361
+
362
+ ::
363
+
364
+ sage: NFCusp(k, 0)
365
+ Cusp [0: 1] of Number Field in a with defining polynomial x^2 + 5
366
+ sage: NFCusp(k, oo)
367
+ Cusp Infinity of Number Field in a with defining polynomial x^2 + 5
368
+ sage: NFCusp(k, 3*a, oo)
369
+ Cusp [0: 1] of Number Field in a with defining polynomial x^2 + 5
370
+ sage: NFCusp(k, a + 5, 0)
371
+ Cusp Infinity of Number Field in a with defining polynomial x^2 + 5
372
+
373
+ Saving and loading works:
374
+
375
+ ::
376
+
377
+ sage: alpha = NFCusp(k, a, 2/(a+1))
378
+ sage: loads(dumps(alpha))==alpha
379
+ True
380
+
381
+ Some tests:
382
+
383
+ ::
384
+
385
+ sage: I*I
386
+ -1
387
+ sage: NFCusp(k, I)
388
+ Traceback (most recent call last):
389
+ ...
390
+ TypeError: unable to convert I to a cusp of the number field
391
+
392
+ ::
393
+
394
+ sage: NFCusp(k, oo, oo)
395
+ Traceback (most recent call last):
396
+ ...
397
+ TypeError: unable to convert (+Infinity, +Infinity) to a cusp of the number field
398
+
399
+ ::
400
+
401
+ sage: NFCusp(k, 0, 0)
402
+ Traceback (most recent call last):
403
+ ...
404
+ TypeError: unable to convert (0, 0) to a cusp of the number field
405
+
406
+ ::
407
+
408
+ sage: NFCusp(k, "a + 2", a)
409
+ Cusp [-2*a + 5: 5] of Number Field in a with defining polynomial x^2 + 5
410
+
411
+ ::
412
+
413
+ sage: NFCusp(k, NFCusp(k, oo))
414
+ Cusp Infinity of Number Field in a with defining polynomial x^2 + 5
415
+ sage: c = NFCusp(k, 3, 2*a)
416
+ sage: NFCusp(k, c, a + 1)
417
+ Cusp [-a - 5: 20] of Number Field in a with defining polynomial x^2 + 5
418
+ sage: L.<b> = NumberField(x^2 + 2)
419
+ sage: NFCusp(L, c)
420
+ Traceback (most recent call last):
421
+ ...
422
+ ValueError: Cannot coerce cusps from one field to another
423
+ """
424
+ def __init__(self, number_field, a, b=None, parent=None, lreps=None):
425
+ """
426
+ Constructor of number field cusps. See ``NFCusp`` for full
427
+ documentation.
428
+
429
+ EXAMPLES::
430
+
431
+ sage: x = polygen(ZZ, 'x')
432
+ sage: k.<a> = NumberField(x^2 + 1)
433
+ sage: c = NFCusp(k, 3, a+1); c
434
+ Cusp [3: a + 1] of Number Field in a with defining polynomial x^2 + 1
435
+ sage: c.parent()
436
+ Set of all cusps of Number Field in a with defining polynomial x^2 + 1
437
+ sage: kCusps = NFCusps(k)
438
+ sage: c.parent() is kCusps
439
+ True
440
+ """
441
+ if parent is None:
442
+ parent = NFCusps(number_field)
443
+ Element.__init__(self, parent)
444
+ R = number_field.maximal_order()
445
+ if b is None:
446
+ if not a: # that is cusp "0"
447
+ self.__a = R.zero()
448
+ self.__b = R.one()
449
+ return
450
+ if isinstance(a, NFCusp):
451
+ if a.parent() == parent:
452
+ self.__a = R(a.__a)
453
+ self.__b = R(a.__b)
454
+ else:
455
+ raise ValueError("Cannot coerce cusps from one field to another")
456
+ elif a in R:
457
+ self.__a = R(a)
458
+ self.__b = R.one()
459
+ elif a in number_field:
460
+ self.__b = R(a.denominator())
461
+ self.__a = R(a * self.__b)
462
+ elif isinstance(a, InfinityElement):
463
+ self.__a = R.one()
464
+ self.__b = R.zero()
465
+ elif isinstance(a, int):
466
+ self.__a = R(a)
467
+ self.__b = R.one()
468
+ elif isinstance(a, (tuple, list)):
469
+ if len(a) != 2:
470
+ raise TypeError("unable to convert %r to a cusp \
471
+ of the number field" % a)
472
+ if a[1].is_zero():
473
+ self.__a = R.one()
474
+ self.__b = R.zero()
475
+ elif a[0] in R and a[1] in R:
476
+ self.__a = R(a[0])
477
+ self.__b = R(a[1])
478
+ elif isinstance(a[0], NFCusp): # we know that a[1] is not zero
479
+ if a[1] == 1:
480
+ self.__a = a[0].__a
481
+ self.__b = a[0].__b
482
+ else:
483
+ r = a[0].__a / (a[0].__b * a[1])
484
+ self.__b = R(r.denominator())
485
+ self.__a = R(r * self.__b)
486
+ else:
487
+ try:
488
+ r = number_field(a[0] / a[1])
489
+ self.__b = R(r.denominator())
490
+ self.__a = R(r * self.__b)
491
+ except (ValueError, TypeError):
492
+ raise TypeError(f"unable to convert {a} to a cusp "
493
+ "of the number field")
494
+ else:
495
+ try:
496
+ r = number_field(a)
497
+ self.__b = R(r.denominator())
498
+ self.__a = R(r * self.__b)
499
+ except (ValueError, TypeError):
500
+ raise TypeError("unable to convert %r to a cusp "
501
+ "of the number field" % a)
502
+ else: # 'b' is given
503
+ if isinstance(b, InfinityElement):
504
+ if isinstance(a, InfinityElement) or (isinstance(a, NFCusp) and a.is_infinity()):
505
+ raise TypeError("unable to convert (%r, %r) "
506
+ "to a cusp of the number field" % (a, b))
507
+ self.__a = R.zero()
508
+ self.__b = R.one()
509
+ return
510
+ elif not b:
511
+ if not a:
512
+ raise TypeError("unable to convert (%r, %r) "
513
+ "to a cusp of the number field" % (a, b))
514
+ self.__a = R.one()
515
+ self.__b = R.zero()
516
+ return
517
+ if not a:
518
+ self.__a = R.zero()
519
+ self.__b = R.one()
520
+ return
521
+ if (b in R or isinstance(b, int)) and (a in R or isinstance(a, int)):
522
+ self.__a = R(a)
523
+ self.__b = R(b)
524
+ else:
525
+ if a in R or a in number_field:
526
+ r = a / b
527
+ elif isinstance(a, InfinityElement):
528
+ self.__a = R.one()
529
+ self.__b = R.zero()
530
+ return
531
+ elif isinstance(a, NFCusp):
532
+ if a.is_infinity():
533
+ self.__a = R.one()
534
+ self.__b = R.zero()
535
+ return
536
+ r = a.__a / (a.__b * b)
537
+ elif isinstance(a, int):
538
+ r = R(a) / b
539
+ elif isinstance(a, (tuple, list)):
540
+ if len(a) != 2:
541
+ raise TypeError("unable to convert (%r, %r) \
542
+ to a cusp of the number field" % (a, b))
543
+ r = R(a[0]) / (R(a[1]) * b)
544
+ else:
545
+ try:
546
+ r = number_field(a) / b
547
+ except (ValueError, TypeError):
548
+ raise TypeError("unable to convert (%r, %r) \
549
+ to a cusp of the number field" % (a, b))
550
+ self.__b = R(r.denominator())
551
+ self.__a = R(r * self.__b)
552
+ if lreps is not None:
553
+ # Changes the representative of the cusp so the ideal associated
554
+ # to the cusp is one of the ideals of the given list lreps.
555
+ # Note: the trivial class is always represented by (1).
556
+ I = self.ideal()
557
+ for J in lreps:
558
+ if (J / I).is_principal():
559
+ newI = J
560
+ l = (newI / I).gens_reduced()[0]
561
+ self.__a = R(l * self.__a)
562
+ self.__b = R(l * self.__b)
563
+
564
+ def _repr_(self):
565
+ """
566
+ String representation of this cusp.
567
+
568
+ EXAMPLES::
569
+
570
+ sage: x = polygen(ZZ, 'x')
571
+ sage: k.<a> = NumberField(x^2 + 1)
572
+ sage: c = NFCusp(k, a, 2); c
573
+ Cusp [a: 2] of Number Field in a with defining polynomial x^2 + 1
574
+ sage: c._repr_()
575
+ 'Cusp [a: 2] of Number Field in a with defining polynomial x^2 + 1'
576
+ sage: c.rename('[a:2](cusp of a number field)');c
577
+ [a:2](cusp of a number field)
578
+ sage: c.rename();c
579
+ Cusp [a: 2] of Number Field in a with defining polynomial x^2 + 1
580
+ """
581
+ if self.__b.is_zero():
582
+ return "Cusp Infinity of %s" % self.parent().number_field()
583
+ else:
584
+ return "Cusp [%s: %s] of %s" % (self.__a, self.__b,
585
+ self.parent().number_field())
586
+
587
+ def number_field(self):
588
+ """
589
+ Return the number field of definition of the cusp ``self``.
590
+
591
+ EXAMPLES::
592
+
593
+ sage: x = polygen(ZZ, 'x')
594
+ sage: k.<a> = NumberField(x^2 + 2)
595
+ sage: alpha = NFCusp(k, 1, a + 1)
596
+ sage: alpha.number_field()
597
+ Number Field in a with defining polynomial x^2 + 2
598
+ """
599
+ return self.parent().number_field()
600
+
601
+ def is_infinity(self) -> bool:
602
+ """
603
+ Return ``True`` if this is the cusp infinity.
604
+
605
+ EXAMPLES::
606
+
607
+ sage: x = polygen(ZZ, 'x')
608
+ sage: k.<a> = NumberField(x^2 + 1)
609
+ sage: NFCusp(k, a, 2).is_infinity()
610
+ False
611
+ sage: NFCusp(k, 2, 0).is_infinity()
612
+ True
613
+ sage: NFCusp(k, oo).is_infinity()
614
+ True
615
+ """
616
+ return self.__b == 0
617
+
618
+ def numerator(self):
619
+ """
620
+ Return the numerator of the cusp ``self``.
621
+
622
+ EXAMPLES::
623
+
624
+ sage: x = polygen(ZZ, 'x')
625
+ sage: k.<a> = NumberField(x^2 + 1)
626
+ sage: c = NFCusp(k, a, 2)
627
+ sage: c.numerator()
628
+ a
629
+ sage: d = NFCusp(k, 1, a)
630
+ sage: d.numerator()
631
+ 1
632
+ sage: NFCusp(k, oo).numerator()
633
+ 1
634
+ """
635
+ return self.__a
636
+
637
+ def denominator(self):
638
+ """
639
+ Return the denominator of the cusp ``self``.
640
+
641
+ EXAMPLES::
642
+
643
+ sage: x = polygen(ZZ, 'x')
644
+ sage: k.<a> = NumberField(x^2 + 1)
645
+ sage: c = NFCusp(k, a, 2)
646
+ sage: c.denominator()
647
+ 2
648
+ sage: d = NFCusp(k, 1, a + 1);d
649
+ Cusp [1: a + 1] of Number Field in a with defining polynomial x^2 + 1
650
+ sage: d.denominator()
651
+ a + 1
652
+ sage: NFCusp(k, oo).denominator()
653
+ 0
654
+ """
655
+ return self.__b
656
+
657
+ def _number_field_element_(self):
658
+ """
659
+ Coerce to an element of the number field.
660
+
661
+ EXAMPLES::
662
+
663
+ sage: x = polygen(ZZ, 'x')
664
+ sage: k.<a> = NumberField(x^2 + 2)
665
+ sage: NFCusp(k, a, 2)._number_field_element_()
666
+ 1/2*a
667
+ sage: NFCusp(k, 1, a + 1)._number_field_element_()
668
+ -1/3*a + 1/3
669
+ """
670
+ if self.__b.is_zero():
671
+ raise TypeError("%s is not an element of %s" % (self,
672
+ self.number_field()))
673
+ k = self.number_field()
674
+ return k(self.__a / self.__b)
675
+
676
+ def _ring_of_integers_element_(self):
677
+ """
678
+ Coerce to an element of the ring of integers of the number field.
679
+
680
+ EXAMPLES::
681
+
682
+ sage: x = polygen(ZZ, 'x')
683
+ sage: k.<a> = NumberField(x^2 + 2)
684
+ sage: NFCusp(k, a+1)._ring_of_integers_element_()
685
+ a + 1
686
+ sage: NFCusp(k, 1, a + 1)._ring_of_integers_element_()
687
+ Traceback (most recent call last):
688
+ ...
689
+ TypeError: Cusp [1: a + 1] of Number Field in a with defining polynomial x^2 + 2 is not an integral element
690
+ """
691
+ if self.__b.is_one():
692
+ return self.__a
693
+ R = self.number_field().ring_of_integers()
694
+ if self.__b.is_zero():
695
+ raise TypeError("%s is not an element of %s" % (self, R))
696
+ try:
697
+ return R(self.__a / self.__b)
698
+ except (ValueError, TypeError):
699
+ raise TypeError("%s is not an integral element" % self)
700
+
701
+ def _latex_(self):
702
+ r"""
703
+ Latex representation of this cusp.
704
+
705
+ EXAMPLES::
706
+
707
+ sage: x = polygen(ZZ, 'x')
708
+ sage: k.<a> = NumberField(x^2 + 11)
709
+ sage: latex(NFCusp(k, 3*a, a + 1)) # indirect doctest
710
+ \[3 a: a + 1\]
711
+ sage: latex(NFCusp(k, 3*a, a + 1)) == NFCusp(k, 3*a, a + 1)._latex_()
712
+ True
713
+ sage: latex(NFCusp(k, oo))
714
+ \infty
715
+ """
716
+ if self.__b.is_zero():
717
+ return "\\infty"
718
+ else:
719
+ return "\\[%s: %s\\]" % (self.__a._latex_(),
720
+ self.__b._latex_())
721
+
722
+ def _richcmp_(self, right, op):
723
+ """
724
+ Compare the cusps ``self`` and ``right``.
725
+
726
+ Comparison is as for elements in the number field, except with
727
+ the cusp oo which is greater than everything but itself.
728
+
729
+ The ordering in comparison is only really meaningful for infinity.
730
+
731
+ EXAMPLES::
732
+
733
+ sage: x = polygen(ZZ, 'x')
734
+ sage: k.<a> = NumberField(x^3 + x + 1)
735
+ sage: kCusps = NFCusps(k)
736
+
737
+ Comparing with infinity::
738
+
739
+ sage: c = kCusps((a,2))
740
+ sage: d = kCusps(oo)
741
+ sage: c < d
742
+ True
743
+ sage: kCusps(oo) < d
744
+ False
745
+
746
+ Comparison as elements of the number field::
747
+
748
+ sage: kCusps(2/3) < kCusps(5/2)
749
+ False
750
+ sage: k(2/3) < k(5/2)
751
+ False
752
+ """
753
+ if self.__b.is_zero():
754
+ if right.__b.is_zero():
755
+ return rich_to_bool(op, 0)
756
+ else:
757
+ return rich_to_bool(op, 1)
758
+ else:
759
+ if right.__b.is_zero():
760
+ return rich_to_bool(op, -1)
761
+ else:
762
+ return richcmp(self._number_field_element_(),
763
+ right._number_field_element_(), op)
764
+
765
+ def __neg__(self):
766
+ """
767
+ The negative of this cusp.
768
+
769
+ EXAMPLES::
770
+
771
+ sage: x = polygen(ZZ, 'x')
772
+ sage: k.<a> = NumberField(x^2 + 23)
773
+ sage: c = NFCusp(k, a, a+1); c
774
+ Cusp [a: a + 1] of Number Field in a with defining polynomial x^2 + 23
775
+ sage: -c
776
+ Cusp [-a: a + 1] of Number Field in a with defining polynomial x^2 + 23
777
+ """
778
+ return NFCusp(self.parent().number_field(), -self.__a, self.__b)
779
+
780
+ def apply(self, g):
781
+ """
782
+ Return g(``self``), where ``g`` is a 2x2 matrix, which we view as a
783
+ linear fractional transformation.
784
+
785
+ INPUT:
786
+
787
+ - ``g`` -- list of integral elements [a, b, c, d] that are the
788
+ entries of a 2x2 matrix
789
+
790
+ OUTPUT:
791
+
792
+ A number field cusp, obtained by the action of ``g`` on the cusp
793
+ ``self``.
794
+
795
+ EXAMPLES::
796
+
797
+ sage: x = polygen(ZZ, 'x')
798
+ sage: k.<a> = NumberField(x^2 + 23)
799
+ sage: beta = NFCusp(k, 0, 1)
800
+ sage: beta.apply([0, -1, 1, 0])
801
+ Cusp Infinity of Number Field in a with defining polynomial x^2 + 23
802
+ sage: beta.apply([1, a, 0, 1])
803
+ Cusp [a: 1] of Number Field in a with defining polynomial x^2 + 23
804
+ """
805
+ k = self.number_field()
806
+ return NFCusp(k, g[0] * self.__a + g[1] * self.__b,
807
+ g[2] * self.__a + g[3] * self.__b)
808
+
809
+ def ideal(self):
810
+ """
811
+ Return the ideal associated to the cusp ``self``.
812
+
813
+ EXAMPLES::
814
+
815
+ sage: x = polygen(ZZ, 'x')
816
+ sage: k.<a> = NumberField(x^2 + 23)
817
+ sage: alpha = NFCusp(k, 3, a-1)
818
+ sage: alpha.ideal()
819
+ Fractional ideal (3, 1/2*a - 1/2)
820
+ sage: NFCusp(k, oo).ideal()
821
+ Fractional ideal (1)
822
+ """
823
+ k = self.number_field()
824
+ return k.ideal(self.__a, self.__b)
825
+
826
+ def ABmatrix(self) -> list:
827
+ """
828
+ Return AB-matrix associated to the cusp ``self``.
829
+
830
+ Given R a Dedekind domain and A, B ideals of R in inverse classes, an
831
+ AB-matrix is a matrix realizing the isomorphism between R+R and A+B.
832
+ An AB-matrix associated to a cusp [a1: a2] is an AB-matrix with A the
833
+ ideal associated to the cusp (A=<a1, a2>) and first column given by
834
+ the coefficients of the cusp.
835
+
836
+ EXAMPLES:
837
+
838
+ ::
839
+
840
+ sage: x = polygen(ZZ, 'x')
841
+ sage: k.<a> = NumberField(x^3 + 11)
842
+ sage: alpha = NFCusp(k, oo)
843
+ sage: alpha.ABmatrix()
844
+ [1, 0, 0, 1]
845
+
846
+ ::
847
+
848
+ sage: alpha = NFCusp(k, 0)
849
+ sage: alpha.ABmatrix()
850
+ [0, -1, 1, 0]
851
+
852
+ Note that the AB-matrix associated to a cusp is not unique, and the
853
+ output of the ``ABmatrix`` function may change.
854
+
855
+ ::
856
+
857
+ sage: alpha = NFCusp(k, 3/2, a-1)
858
+ sage: M = alpha.ABmatrix()
859
+ sage: M # random
860
+ [-a^2 - a - 1, -3*a - 7, 8, -2*a^2 - 3*a + 4]
861
+ sage: M[0] == alpha.numerator() and M[2] == alpha.denominator()
862
+ True
863
+
864
+ An AB-matrix associated to a cusp alpha will send Infinity to alpha:
865
+
866
+ ::
867
+
868
+ sage: alpha = NFCusp(k, 3, a-1)
869
+ sage: M = alpha.ABmatrix()
870
+ sage: (k.ideal(M[1], M[3])*alpha.ideal()).is_principal()
871
+ True
872
+ sage: M[0] == alpha.numerator() and M[2] == alpha.denominator()
873
+ True
874
+ sage: NFCusp(k, oo).apply(M) == alpha
875
+ True
876
+ """
877
+ k = self.number_field()
878
+ A = self.ideal()
879
+
880
+ if self.is_infinity():
881
+ return [1, 0, 0, 1]
882
+ if not self:
883
+ return [0, -1, 1, 0]
884
+
885
+ if A.is_principal():
886
+ B = k.ideal(1)
887
+ else:
888
+ B = k.ideal(A.gens_reduced()[1]) / A
889
+ assert (A * B).is_principal()
890
+
891
+ a1 = self.__a
892
+ a2 = self.__b
893
+
894
+ g = (A * B).gens_reduced()[0]
895
+ Ainv = A**(-1)
896
+ A1 = a1 * Ainv
897
+ A2 = a2 * Ainv
898
+ r = A1.element_1_mod(A2)
899
+ b1 = -(1 - r) / a2 * g
900
+ b2 = (r / a1) * g
901
+ return [a1, b1, a2, b2]
902
+
903
+ def is_Gamma0_equivalent(self, other, N,
904
+ Transformation=False) -> bool | tuple[bool, Any]:
905
+ r"""
906
+ Check if cusps ``self`` and ``other`` are `\Gamma_0(N)`- equivalent.
907
+
908
+ INPUT:
909
+
910
+ - ``other`` -- a number field cusp or a list of two number field
911
+ elements which define a cusp
912
+
913
+ - ``N`` -- an ideal of the number field (level)
914
+
915
+ OUTPUT: boolean; ``True`` if the cusps are equivalent
916
+
917
+ - a transformation matrix -- (if ``Transformation=True``) a list of
918
+ integral elements [a, b, c, d] which are the entries of a 2x2 matrix
919
+ M in `\Gamma_0(N)` such that M * ``self`` = ``other`` if ``other``
920
+ and ``self`` are `\Gamma_0(N)`- equivalent. If ``self`` and ``other``
921
+ are not equivalent it returns zero.
922
+
923
+ EXAMPLES:
924
+
925
+ ::
926
+
927
+ sage: x = polygen(ZZ, 'x')
928
+ sage: K.<a> = NumberField(x^3 - 10)
929
+ sage: N = K.ideal(a - 1)
930
+ sage: alpha = NFCusp(K, 0)
931
+ sage: beta = NFCusp(K, oo)
932
+ sage: alpha.is_Gamma0_equivalent(beta, N)
933
+ False
934
+ sage: alpha.is_Gamma0_equivalent(beta, K.ideal(1))
935
+ True
936
+ sage: b, M = alpha.is_Gamma0_equivalent(beta, K.ideal(1),Transformation=True)
937
+ sage: alpha.apply(M)
938
+ Cusp Infinity of Number Field in a with defining polynomial x^3 - 10
939
+
940
+ ::
941
+
942
+ sage: k.<a> = NumberField(x^2 + 23)
943
+ sage: N = k.ideal(3)
944
+ sage: alpha1 = NFCusp(k, a+1, 4)
945
+ sage: alpha2 = NFCusp(k, a-8, 29)
946
+ sage: alpha1.is_Gamma0_equivalent(alpha2, N)
947
+ True
948
+ sage: b, M = alpha1.is_Gamma0_equivalent(alpha2, N, Transformation=True)
949
+ sage: alpha1.apply(M) == alpha2
950
+ True
951
+ sage: M[2] in N
952
+ True
953
+ """
954
+ k = self.number_field()
955
+ other = NFCusp(k, other)
956
+ if not (self.ideal() / other.ideal()).is_principal():
957
+ if not Transformation:
958
+ return False
959
+ else:
960
+ return False, 0
961
+
962
+ reps = list_of_representatives(N)
963
+ alpha1 = NFCusp(k, self, lreps=reps)
964
+ alpha2 = NFCusp(k, other, lreps=reps)
965
+
966
+ delta = k.ideal(alpha1.__b) + N
967
+ if (k.ideal(alpha2.__b) + N) != delta:
968
+ if not Transformation:
969
+ return False
970
+ else:
971
+ return False, 0
972
+
973
+ M1 = alpha1.ABmatrix()
974
+ M2 = alpha2.ABmatrix()
975
+
976
+ A = alpha1.ideal()
977
+ B = k.ideal(M1[1], M1[3])
978
+
979
+ ABdelta = A * B * delta * delta
980
+
981
+ units = units_mod_ideal(ABdelta)
982
+ for u in units:
983
+ if (M2[2] * M1[3] - u * M1[2] * M2[3]) in ABdelta:
984
+ if not Transformation:
985
+ return True
986
+ else:
987
+ AuxCoeff = [1, 0, 0, 1]
988
+ Aux = M2[2] * M1[3] - u * M1[2] * M2[3]
989
+ if Aux in A * B * N:
990
+ if u != 1:
991
+ AuxCoeff[3] = u
992
+ else:
993
+ A1 = (A * B * N) / ABdelta
994
+ A2 = B * k.ideal(M1[2] * M2[2]) / (A * ABdelta)
995
+ f = A1.element_1_mod(A2)
996
+ w = ((1 - f) * Aux) / (M1[2] * M2[2])
997
+ AuxCoeff[3] = u
998
+ AuxCoeff[1] = w
999
+ from sage.matrix.constructor import Matrix
1000
+ Maux = Matrix(k, 2, AuxCoeff)
1001
+ M1inv = Matrix(k, 2, M1).inverse()
1002
+ Mtrans = Matrix(k, 2, M2) * Maux * M1inv
1003
+ assert Mtrans[1][0] in N
1004
+ return True, Mtrans.list()
1005
+ if not Transformation:
1006
+ return False
1007
+ else:
1008
+ return False, 0
1009
+
1010
+ # *************************************************************************
1011
+ # Global functions:
1012
+ # - Gamma0_NFCusps --compute list of inequivalent cusps
1013
+ # Internal use only:
1014
+ # - number_of_Gamma0_NFCusps -- useful to test Gamma0_NFCusps
1015
+ # - NFCusps_ideal_reps_for_levelN -- lists of reps for ideal classes
1016
+ # - units_mod_ideal -- needed to check Gamma0(N)-equiv of cusps
1017
+ # *************************************************************************
1018
+
1019
+
1020
+ def Gamma0_NFCusps(N):
1021
+ r"""
1022
+ Return a list of inequivalent cusps for `\Gamma_0(N)`, i.e., a set of
1023
+ representatives for the orbits of ``self`` on `\mathbb{P}^1(k)`.
1024
+
1025
+ INPUT:
1026
+
1027
+ - ``N`` -- an integral ideal of the number field k (the level)
1028
+
1029
+ OUTPUT: list of inequivalent number field cusps
1030
+
1031
+ EXAMPLES::
1032
+
1033
+ sage: x = polygen(ZZ, 'x')
1034
+ sage: k.<a> = NumberField(x^2 + 5)
1035
+ sage: N = k.ideal(3)
1036
+ sage: L = Gamma0_NFCusps(N)
1037
+
1038
+ The cusps in the list are inequivalent::
1039
+
1040
+ sage: any(L[i].is_Gamma0_equivalent(L[j], N)
1041
+ ....: for i in range(len(L)) for j in range(len(L)) if i < j)
1042
+ False
1043
+
1044
+ We test that we obtain the right number of orbits::
1045
+
1046
+ sage: from sage.modular.cusps_nf import number_of_Gamma0_NFCusps
1047
+ sage: len(L) == number_of_Gamma0_NFCusps(N)
1048
+ True
1049
+
1050
+ Another example::
1051
+
1052
+ sage: x = polygen(ZZ, 'x')
1053
+ sage: k.<a> = NumberField(x^4 - x^3 -21*x^2 + 17*x + 133)
1054
+ sage: N = k.ideal(5)
1055
+ sage: from sage.modular.cusps_nf import number_of_Gamma0_NFCusps
1056
+ sage: len(Gamma0_NFCusps(N)) == number_of_Gamma0_NFCusps(N) # long time (over 1 sec)
1057
+ True
1058
+ """
1059
+ # We create L a list of three lists, which are different and each a list of
1060
+ # prime ideals, coprime to N, representing the ideal classes of k
1061
+ L = NFCusps_ideal_reps_for_levelN(N, nlists=3)
1062
+ Laux = L[1] + L[2]
1063
+ Lreps = list_of_representatives(N)
1064
+ Lcusps = []
1065
+
1066
+ k = N.number_field()
1067
+
1068
+ for A in L[0]:
1069
+ # find B in inverse class:
1070
+ if A.is_trivial():
1071
+ B = k.ideal(1)
1072
+ # B = k.unit_ideal() produces an error because we need fract ideal
1073
+ g = 1
1074
+ else:
1075
+ Lbs = [P for P in Laux if (P * A).is_principal()]
1076
+ B = Lbs[0]
1077
+ g = (A * B).gens_reduced()[0]
1078
+
1079
+ # for every divisor of N we have to find cusps
1080
+ from sage.arith.misc import divisors
1081
+ for d in divisors(N):
1082
+ # find delta prime coprime to B in inverse class of d*A
1083
+ # by searching in our list of auxiliary prime ideals
1084
+ Lds = [P for P in Laux
1085
+ if (P * d * A).is_principal() and P.is_coprime(B)]
1086
+ deltap = Lds[0]
1087
+ a = (deltap * d * A).gens_reduced()[0]
1088
+ I = d + N / d
1089
+ # special case: A=B=d=<1>:
1090
+ if a.is_one() and I.is_trivial():
1091
+ Lcusps.append(NFCusp(k, 0, 1, lreps=Lreps))
1092
+ else:
1093
+ u = k.unit_group().gens()
1094
+ for b in I.invertible_residues_mod(u):
1095
+ # Note: if I trivial, invertible_residues_mod returns [1]
1096
+ # lift b to (R/a)star
1097
+ # we need the part of d which is coprime to I, call it M
1098
+ M = d.prime_to_idealM_part(I)
1099
+ deltAM = deltap * A * M
1100
+ u = (B * deltAM).element_1_mod(I)
1101
+ v = (I * B).element_1_mod(deltAM)
1102
+ newb = u * b + v
1103
+ # build AB-matrix:
1104
+ # ----> extended gcd for k.ideal(a), k.ideal(newb)
1105
+ Y = k.ideal(newb).element_1_mod(k.ideal(a))
1106
+ # if xa + yb = 1, cusp = y*g /a
1107
+ Lcusps.append(NFCusp(k, Y * g, a, lreps=Lreps))
1108
+ return Lcusps
1109
+
1110
+
1111
+ def number_of_Gamma0_NFCusps(N):
1112
+ """
1113
+ Return the total number of orbits of cusps under the action of the
1114
+ congruence subgroup `\\Gamma_0(N)`.
1115
+
1116
+ INPUT:
1117
+
1118
+ - ``N`` -- a number field ideal
1119
+
1120
+ OUTPUT: integer; the number of orbits of cusps under Gamma0(N)-action
1121
+
1122
+ EXAMPLES::
1123
+
1124
+ sage: x = polygen(ZZ, 'x')
1125
+ sage: k.<a> = NumberField(x^3 + 11)
1126
+ sage: N = k.ideal(2, a+1)
1127
+ sage: from sage.modular.cusps_nf import number_of_Gamma0_NFCusps
1128
+ sage: number_of_Gamma0_NFCusps(N)
1129
+ 4
1130
+ sage: L = Gamma0_NFCusps(N)
1131
+ sage: len(L) == number_of_Gamma0_NFCusps(N)
1132
+ True
1133
+ sage: k.<a> = NumberField(x^2 + 7)
1134
+ sage: N = k.ideal(9)
1135
+ sage: number_of_Gamma0_NFCusps(N)
1136
+ 6
1137
+ sage: N = k.ideal(a*9 + 7)
1138
+ sage: number_of_Gamma0_NFCusps(N)
1139
+ 24
1140
+ """
1141
+ k = N.number_field()
1142
+ # The number of Gamma0(N)-sub-orbits for each Gamma-orbit:
1143
+ from sage.arith.misc import divisors
1144
+ Ugens = [k(u) for u in k.unit_group().gens()]
1145
+ s = sum([len((d + N / d).invertible_residues_mod(Ugens))
1146
+ for d in divisors(N)])
1147
+ # There are h Gamma-orbits, with h class number of underlying number field.
1148
+ return s * k.class_number()
1149
+
1150
+
1151
+ def NFCusps_ideal_reps_for_levelN(N, nlists=1):
1152
+ """
1153
+ Return a list of lists (``nlists`` different lists) of prime ideals,
1154
+ coprime to ``N``, representing every ideal class of the number field.
1155
+
1156
+ INPUT:
1157
+
1158
+ - ``N`` -- number field ideal
1159
+
1160
+ - ``nlists`` -- (default: 1) the number of lists of prime ideals
1161
+ we want
1162
+
1163
+ OUTPUT:
1164
+
1165
+ A list of lists of ideals representatives of the ideal classes, all coprime
1166
+ to ``N``, representing every ideal.
1167
+
1168
+ EXAMPLES::
1169
+
1170
+ sage: x = polygen(ZZ, 'x')
1171
+ sage: k.<a> = NumberField(x^3 + 11)
1172
+ sage: N = k.ideal(5, a + 1)
1173
+ sage: from sage.modular.cusps_nf import NFCusps_ideal_reps_for_levelN
1174
+ sage: NFCusps_ideal_reps_for_levelN(N)
1175
+ [(Fractional ideal (1), Fractional ideal (2, a + 1))]
1176
+ sage: L = NFCusps_ideal_reps_for_levelN(N, 3)
1177
+ sage: all(len(L[i]) == k.class_number() for i in range(len(L)))
1178
+ True
1179
+
1180
+ ::
1181
+
1182
+ sage: k.<a> = NumberField(x^4 - x^3 - 21*x^2 + 17*x + 133)
1183
+ sage: N = k.ideal(6)
1184
+ sage: from sage.modular.cusps_nf import NFCusps_ideal_reps_for_levelN
1185
+ sage: NFCusps_ideal_reps_for_levelN(N)
1186
+ [(Fractional ideal (1),
1187
+ Fractional ideal (67, -4/7*a^3 + 13/7*a^2 + 39/7*a - 43),
1188
+ Fractional ideal (127, -4/7*a^3 + 13/7*a^2 + 39/7*a - 42),
1189
+ Fractional ideal (157, -4/7*a^3 + 13/7*a^2 + 39/7*a + 48))]
1190
+ sage: L = NFCusps_ideal_reps_for_levelN(N, 5)
1191
+ sage: all(len(L[i]) == k.class_number() for i in range(len(L)))
1192
+ True
1193
+ """
1194
+ k = N.number_field()
1195
+ G = k.class_group()
1196
+ L = [[k.ideal(1)] for _ in range(nlists)]
1197
+ it = k.primes_of_degree_one_iter()
1198
+ for I in G.list():
1199
+ check = 0
1200
+ if not I.is_principal():
1201
+ Iinv = I.ideal()**(-1)
1202
+ while check < nlists:
1203
+ J = next(it)
1204
+ if (J * Iinv).is_principal() and J.is_coprime(N):
1205
+ L[check].append(J)
1206
+ check += 1
1207
+ return [tuple(l) for l in L]
1208
+
1209
+
1210
+ def units_mod_ideal(I):
1211
+ """
1212
+ Return integral elements of the number field representing the images of
1213
+ the global units modulo the ideal ``I``.
1214
+
1215
+ INPUT:
1216
+
1217
+ - ``I`` -- number field ideal
1218
+
1219
+ OUTPUT:
1220
+
1221
+ A list of integral elements of the number field representing the images of
1222
+ the global units modulo the ideal ``I``. Elements of the list might be
1223
+ equivalent to each other mod ``I``.
1224
+
1225
+ EXAMPLES::
1226
+
1227
+ sage: from sage.modular.cusps_nf import units_mod_ideal
1228
+ sage: x = polygen(ZZ, 'x')
1229
+ sage: k.<a> = NumberField(x^2 + 1)
1230
+ sage: I = k.ideal(a + 1)
1231
+ sage: units_mod_ideal(I)
1232
+ [1]
1233
+ sage: I = k.ideal(3)
1234
+ sage: units_mod_ideal(I)
1235
+ [1, a, -1, -a]
1236
+
1237
+ ::
1238
+
1239
+ sage: from sage.modular.cusps_nf import units_mod_ideal
1240
+ sage: k.<a> = NumberField(x^3 + 11)
1241
+ sage: k.unit_group()
1242
+ Unit group with structure C2 x Z of
1243
+ Number Field in a with defining polynomial x^3 + 11
1244
+ sage: I = k.ideal(5, a + 1)
1245
+ sage: units_mod_ideal(I)
1246
+ [1,
1247
+ 2*a^2 + 4*a - 1,
1248
+ ...]
1249
+
1250
+ ::
1251
+
1252
+ sage: from sage.modular.cusps_nf import units_mod_ideal
1253
+ sage: k.<a> = NumberField(x^4 - x^3 -21*x^2 + 17*x + 133)
1254
+ sage: k.unit_group()
1255
+ Unit group with structure C6 x Z of
1256
+ Number Field in a with defining polynomial x^4 - x^3 - 21*x^2 + 17*x + 133
1257
+ sage: I = k.ideal(3)
1258
+ sage: U = units_mod_ideal(I)
1259
+ sage: all(U[j].is_unit() and (U[j] not in I) for j in range(len(U)))
1260
+ True
1261
+ """
1262
+ k = I.number_field()
1263
+ Uk = k.unit_group()
1264
+ Istar = I.idealstar(2)
1265
+ ulist = Uk.gens_values()
1266
+ elist = [Istar(I.ideallog(u)).order() for u in ulist]
1267
+
1268
+ from sage.misc.mrange import xmrange
1269
+
1270
+ return [k.prod(u**e for u, e in zip(ulist, ei)) for ei in xmrange(elist)]