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,334 @@
1
+ # sage_setup: distribution = sagemath-schemes
2
+ r"""
3
+ Helper functions for congruence subgroups
4
+
5
+ This file contains optimized Cython implementations of a few functions related
6
+ to the standard congruence subgroups `\Gamma_0, \Gamma_1, \Gamma_H`. These
7
+ functions are for internal use by routines elsewhere in the Sage library.
8
+ """
9
+
10
+ # ****************************************************************************
11
+ # This program is free software: you can redistribute it and/or modify
12
+ # it under the terms of the GNU General Public License as published by
13
+ # the Free Software Foundation, either version 2 of the License, or
14
+ # (at your option) any later version.
15
+ # https://www.gnu.org/licenses/
16
+ # ****************************************************************************
17
+
18
+ from cysignals.memory cimport check_allocarray, sig_free
19
+
20
+ from sage.matrix.matrix_dense cimport Matrix_dense
21
+
22
+ try:
23
+ from sage.matrix.matrix_integer_dense import Matrix_integer_dense as MatrixClass
24
+ except ImportError:
25
+ from sage.matrix.matrix_generic_dense import Matrix_generic_dense as MatrixClass
26
+
27
+ import random
28
+ from .congroup_gamma1 import Gamma1_constructor as Gamma1
29
+ from .congroup_gamma0 import Gamma0_constructor as Gamma0
30
+
31
+ cimport sage.rings.fast_arith
32
+ import sage.rings.fast_arith
33
+ cdef sage.rings.fast_arith.arith_int arith_int
34
+ arith_int = sage.rings.fast_arith.arith_int()
35
+ from sage.modular.modsym.p1list import lift_to_sl2z
36
+ from sage.matrix.matrix_space import MatrixSpace
37
+ from sage.rings.integer_ring import ZZ
38
+ Mat2Z = MatrixSpace(ZZ, 2)
39
+
40
+ cdef Matrix_dense genS, genT, genI
41
+
42
+ genS = MatrixClass(Mat2Z, [0, -1, 1, 0], True, True)
43
+ genT = MatrixClass(Mat2Z, [1, 1, 0, 1], True, True)
44
+ genI = MatrixClass(Mat2Z, [1, 0, 0, 1], True, True)
45
+
46
+
47
+ # This is the C version of a function formerly implemented in python in
48
+ # sage.modular.congroup. It is orders of magnitude faster (e.g., 30
49
+ # times). The key speedup is in replacing looping through the
50
+ # elements of the Python list R with looping through the elements of a
51
+ # C-array.
52
+
53
+ def degeneracy_coset_representatives_gamma0(int N, int M, int t):
54
+ r"""
55
+ Let `N` be a positive integer and `M` a divisor of `N`. Let `t` be a
56
+ divisor of `N/M`, and let `T` be the `2 \times 2` matrix `(1, 0; 0, t)`.
57
+ This function returns representatives for the orbit set `\Gamma_0(N)
58
+ \backslash T \Gamma_0(M)`, where `\Gamma_0(N)` acts on the left on `T
59
+ \Gamma_0(M)`.
60
+
61
+ INPUT:
62
+
63
+ - ``N`` -- integer
64
+ - ``M`` -- integer (divisor of `N`)
65
+ - ``t`` -- integer (divisor of `N/M`)
66
+
67
+ OUTPUT:
68
+
69
+ list -- list of lists ``[a,b,c,d]``, where ``[a,b,c,d]`` should be viewed
70
+ as a 2x2 matrix.
71
+
72
+ This function is used for computation of degeneracy maps between
73
+ spaces of modular symbols, hence its name.
74
+
75
+ We use that `T^{-1} \cdot (a,b;c,d) \cdot T = (a,bt; c/t,d)`, that the
76
+ group `T^{-1} \Gamma_0(N) T` is contained in `\Gamma_0(M)`, and that
77
+ `\Gamma_0(N) T` is contained in `T \Gamma_0(M)`.
78
+
79
+ ALGORITHM:
80
+
81
+ 1. Compute representatives for `\Gamma_0(N/t,t)` inside of `\Gamma_0(M)`:
82
+
83
+ + COSET EQUIVALENCE: Two right cosets represented by `[a,b;c,d]` and
84
+ `[a',b';c',d']` of `\Gamma_0(N/t,t)` in `\SL_2(\ZZ)` are equivalent if
85
+ and only if `(a,b)=(a',b')` as points of `\mathbf{P}^1(\ZZ/t\ZZ)`,
86
+ i.e., `ab' \cong ba' \pmod{t}`, and `(c,d) = (c',d')` as points of
87
+ `\mathbf{P}^1(\ZZ/(N/t)\ZZ)`.
88
+
89
+ + ALGORITHM to list all cosets:
90
+
91
+ a) Compute the number of cosets.
92
+ b) Compute a random element `x` of `\Gamma_0(M)`.
93
+ c) Check if x is equivalent to anything generated so far; if not, add x
94
+ to the list.
95
+ d) Continue until the list is as long as the bound
96
+ computed in step (a).
97
+
98
+ 2. There is a bijection between `\Gamma_0(N)\backslash T \Gamma_0(M)` and
99
+ `\Gamma_0(N/t,t) \backslash \Gamma_0(M)` given by `T r \leftrightarrow
100
+ r`. Consequently we obtain coset representatives for
101
+ `\Gamma_0(N)\backslash T \Gamma_0(M)` by left multiplying by `T` each
102
+ coset representative of `\Gamma_0(N/t,t) \backslash \Gamma_0(M)` found
103
+ in step 1.
104
+
105
+ EXAMPLES::
106
+
107
+ sage: from sage.modular.arithgroup.all import degeneracy_coset_representatives_gamma0
108
+ sage: len(degeneracy_coset_representatives_gamma0(13, 1, 1))
109
+ 14
110
+ sage: len(degeneracy_coset_representatives_gamma0(13, 13, 1))
111
+ 1
112
+ sage: len(degeneracy_coset_representatives_gamma0(13, 1, 13))
113
+ 14
114
+ """
115
+ if N % M != 0:
116
+ raise ArithmeticError(f"M (={M}) must be a divisor of N (={N})")
117
+
118
+ if (N // M) % t != 0:
119
+ raise ArithmeticError(f"t (={t}) must be a divisor of N/M (={N//M})")
120
+
121
+ cdef int n, i, j, k, aa, bb, cc, dd, g, Ndivt, halfmax, is_new
122
+ cdef int* R
123
+
124
+ # total number of coset representatives that we'll find
125
+ n = Gamma0(N).index() / Gamma0(M).index()
126
+ k = 0 # number found so far
127
+ Ndivt = N // t
128
+ R = <int*>check_allocarray(4 * n, sizeof(int))
129
+ halfmax = 2*(n+10)
130
+ while k < n:
131
+ # try to find another coset representative.
132
+ cc = M*random.randrange(-halfmax, halfmax+1)
133
+ dd = random.randrange(-halfmax, halfmax+1)
134
+ g = arith_int.c_xgcd_int(-cc, dd, &bb, &aa)
135
+ if g == 0:
136
+ continue
137
+ cc = cc // g
138
+ if cc % M != 0:
139
+ continue
140
+ dd = dd // g
141
+ # Test if we've found a new coset representative.
142
+ is_new = 1
143
+ for i in range(k):
144
+ j = 4*i
145
+ if (R[j+1]*aa - R[j]*bb) % t == 0 and \
146
+ (R[j+3]*cc - R[j+2]*dd) % Ndivt == 0:
147
+ is_new = 0
148
+ break
149
+ # If our matrix is new add it to the list.
150
+ if is_new:
151
+ R[4*k] = aa
152
+ R[4*k+1] = bb
153
+ R[4*k+2] = cc
154
+ R[4*k+3] = dd
155
+ k = k + 1
156
+
157
+ # Return the list left multiplied by T.
158
+ S = []
159
+ for i in range(k):
160
+ j = 4*i
161
+ S.append([R[j], R[j+1], R[j+2]*t, R[j+3]*t])
162
+ sig_free(R)
163
+ return S
164
+
165
+
166
+ def degeneracy_coset_representatives_gamma1(int N, int M, int t):
167
+ r"""
168
+ Let `N` be a positive integer and `M` a divisor of `N`. Let `t` be a
169
+ divisor of `N/M`, and let `T` be the `2 \times 2` matrix `(1,0; 0,t)`.
170
+ This function returns representatives for the orbit set `\Gamma_1(N)
171
+ \backslash T \Gamma_1(M)`, where `\Gamma_1(N)` acts on the left on `T
172
+ \Gamma_1(M)`.
173
+
174
+ INPUT:
175
+
176
+ - ``N`` -- integer
177
+ - ``M`` -- integer (divisor of `N`)
178
+ - ``t`` -- integer (divisor of `N/M`)
179
+
180
+ OUTPUT:
181
+
182
+ list -- list of lists ``[a,b,c,d]``, where ``[a,b,c,d]`` should be viewed
183
+ as a 2x2 matrix.
184
+
185
+ This function is used for computation of degeneracy maps between
186
+ spaces of modular symbols, hence its name.
187
+
188
+ ALGORITHM:
189
+
190
+ Everything is the same as for
191
+ :func:`~degeneracy_coset_representatives_gamma0`, except for coset
192
+ equivalence. Here `\Gamma_1(N/t,t)` consists of matrices that are of the
193
+ form `(1,*; 0,1) \bmod N/t` and `(1,0; *,1) \bmod t`.
194
+
195
+ COSET EQUIVALENCE: Two right cosets represented by `[a,b;c,d]` and
196
+ `[a',b';c',d']` of `\Gamma_1(N/t,t)` in `\SL_2(\ZZ)` are equivalent if
197
+ and only if
198
+
199
+ .. MATH::
200
+
201
+ a \cong a' \pmod{t},
202
+ b \cong b' \pmod{t},
203
+ c \cong c' \pmod{N/t},
204
+ d \cong d' \pmod{N/t}.
205
+
206
+ EXAMPLES::
207
+
208
+ sage: from sage.modular.arithgroup.all import degeneracy_coset_representatives_gamma1
209
+ sage: len(degeneracy_coset_representatives_gamma1(13, 1, 1))
210
+ 168
211
+ sage: len(degeneracy_coset_representatives_gamma1(13, 13, 1))
212
+ 1
213
+ sage: len(degeneracy_coset_representatives_gamma1(13, 1, 13))
214
+ 168
215
+ """
216
+ if N % M != 0:
217
+ raise ArithmeticError(f"M (={M}) must be a divisor of N (={N})")
218
+
219
+ if (N // M) % t != 0:
220
+ raise ArithmeticError(f"t (={t}) must be a divisor of N/M (={N//M})")
221
+
222
+ cdef int d, g, i, j, k, n, aa, bb, cc, dd, Ndivt, halfmax, is_new
223
+ cdef int* R
224
+
225
+ # total number of coset representatives that we'll find
226
+ n = Gamma1(N).index() / Gamma1(M).index()
227
+ d = arith_int.c_gcd_int(t, N // t)
228
+ n = n // d
229
+ k = 0 # number found so far
230
+ Ndivt = N // t
231
+ R = <int*>check_allocarray(4 * n, sizeof(int))
232
+ halfmax = 2*(n+10)
233
+ while k < n:
234
+ # try to find another coset representative.
235
+ cc = M * random.randrange(-halfmax, halfmax + 1)
236
+ dd = 1 + M * random.randrange(-halfmax, halfmax + 1)
237
+ g = arith_int.c_xgcd_int(-cc, dd, &bb, &aa)
238
+ if g == 0:
239
+ continue
240
+ cc = cc // g
241
+ if cc % M != 0:
242
+ continue
243
+ dd = dd // g
244
+ if M != 1 and dd % M != 1:
245
+ continue
246
+ # Test if we've found a new coset representative.
247
+ is_new = 1
248
+ for i in range(k):
249
+ j = 4*i
250
+ if (R[j] - aa) % t == 0 and \
251
+ (R[j+1] - bb) % t == 0 and \
252
+ (R[j+2] - cc) % Ndivt == 0 and \
253
+ (R[j+3] - dd) % Ndivt == 0:
254
+ is_new = 0
255
+ break
256
+ # If our matrix is new add it to the list.
257
+ if is_new:
258
+ if k > n:
259
+ sig_free(R)
260
+ raise RuntimeError("bug!!")
261
+ R[4*k] = aa
262
+ R[4*k+1] = bb
263
+ R[4*k+2] = cc
264
+ R[4*k+3] = dd
265
+ k = k + 1
266
+
267
+ # Return the list left multiplied by T.
268
+ S = []
269
+ for i in range(k):
270
+ j = 4*i
271
+ S.append([R[j], R[j+1], R[j+2]*t, R[j+3]*t])
272
+ sig_free(R)
273
+ return S
274
+
275
+
276
+ def generators_helper(coset_reps, level):
277
+ r"""
278
+ Helper function for generators of Gamma0, Gamma1 and GammaH.
279
+
280
+ These are computed using coset representatives, via an "inverse
281
+ Todd-Coxeter" algorithm, and generators for `\SL_2(\ZZ)`.
282
+
283
+ ALGORITHM: Given coset representatives for a finite index subgroup `G` of
284
+ `\SL_2(\ZZ)` we compute generators for `G` as follows. Let `R` be a set of
285
+ coset representatives for `G`. Let `S, T \in \SL_2(\ZZ)` be defined by
286
+ `(0,-1; 1,0)` and `(1,1,0,1)`, respectively.
287
+ Define maps `s, t: R \to G` as follows. If `r \in R`, then there exists a
288
+ unique `r' \in R` such that `GrS = Gr'`. Let `s(r) = rSr'^{-1}`. Likewise,
289
+ there is a unique `r'` such that `GrT = Gr'` and we let `t(r) = rTr'^{-1}`.
290
+ Note that `s(r)` and `t(r)` are in `G` for all `r`. Then `G` is generated
291
+ by `s(R)\cup t(R)`.
292
+
293
+ There are more sophisticated algorithms using group actions on trees (and
294
+ Farey symbols) that give smaller generating sets -- this code is now
295
+ deprecated in favour of the newer implementation based on Farey symbols.
296
+
297
+ EXAMPLES::
298
+
299
+ sage: Gamma0(7).generators(algorithm='todd-coxeter') # indirect doctest
300
+ [
301
+ [1 1] [-1 0] [ 1 -1] [1 0] [1 1] [-3 -1] [-2 -1] [-5 -1]
302
+ [0 1], [ 0 -1], [ 0 1], [7 1], [0 1], [ 7 2], [ 7 3], [21 4],
303
+ <BLANKLINE>
304
+ [-4 -1] [-1 0] [ 1 0]
305
+ [21 5], [ 7 -1], [-7 1]
306
+ ]
307
+ """
308
+ cdef Matrix_dense x, y, z, v, vSmod, vTmod
309
+
310
+ crs = coset_reps.list()
311
+ try:
312
+ reps = [MatrixClass(Mat2Z, lift_to_sl2z(c, d, level),
313
+ False, True) for c, d in crs]
314
+ except Exception:
315
+ raise ArithmeticError("Error lifting to SL2Z: level=%s crs=%s" % (level, crs))
316
+ ans = []
317
+ cdef Py_ssize_t i
318
+ for i in range(len(crs)):
319
+ x = reps[i]
320
+ v = MatrixClass(Mat2Z, [crs[i][0], crs[i][1], 0, 0],
321
+ False, True)
322
+ vSmod = (v*genS)
323
+ vTmod = (v*genT)
324
+ y_index = coset_reps.normalize(vSmod[0, 0], vSmod[0, 1])
325
+ z_index = coset_reps.normalize(vTmod[0, 0], vTmod[0, 1])
326
+ y_index = crs.index(y_index)
327
+ z_index = crs.index(z_index)
328
+ y = reps[y_index]
329
+ z = reps[z_index]
330
+ y = y.inverse_of_unit()
331
+ z = z.inverse_of_unit()
332
+ ans.append(x*genS*y)
333
+ ans.append(x*genT*z)
334
+ return [x for x in ans if x != genI]
@@ -0,0 +1,361 @@
1
+ # sage_setup: distribution = sagemath-schemes
2
+ r"""
3
+ Congruence subgroup `\Gamma(N)`
4
+ """
5
+
6
+ # ****************************************************************************
7
+ # This program is free software: you can redistribute it and/or modify
8
+ # it under the terms of the GNU General Public License as published by
9
+ # the Free Software Foundation, either version 2 of the License, or
10
+ # (at your option) any later version.
11
+ # https://www.gnu.org/licenses/
12
+ # ****************************************************************************
13
+
14
+ from sage.arith.misc import gcd
15
+ from sage.groups.matrix_gps.finitely_generated import MatrixGroup
16
+ from sage.matrix.constructor import matrix
17
+ from sage.misc.misc_c import prod
18
+ from sage.modular.arithgroup.congroup_generic import CongruenceSubgroup
19
+ from sage.modular.arithgroup.congroup_sl2z import SL2Z
20
+ from sage.modular.cusps import Cusp
21
+ from sage.rings.finite_rings.integer_mod_ring import Zmod
22
+ from sage.rings.integer import GCD_list
23
+ from sage.rings.integer_ring import ZZ
24
+ from sage.rings.rational_field import QQ
25
+ from sage.structure.richcmp import richcmp, richcmp_method
26
+
27
+ _gamma_cache = {}
28
+
29
+
30
+ def Gamma_constructor(N):
31
+ r"""
32
+ Return the congruence subgroup `\Gamma(N)`.
33
+
34
+ EXAMPLES::
35
+
36
+ sage: Gamma(5) # indirect doctest
37
+ Congruence Subgroup Gamma(5)
38
+ sage: G = Gamma(23)
39
+ sage: G is Gamma(23)
40
+ True
41
+ sage: TestSuite(G).run()
42
+
43
+ Test global uniqueness::
44
+
45
+ sage: G = Gamma(17)
46
+ sage: G is loads(dumps(G))
47
+ True
48
+ sage: G2 = sage.modular.arithgroup.congroup_gamma.Gamma_class(17)
49
+ sage: G == G2
50
+ True
51
+ sage: G is G2
52
+ False
53
+ """
54
+ if N == 1:
55
+ return SL2Z
56
+ try:
57
+ return _gamma_cache[N]
58
+ except KeyError:
59
+ _gamma_cache[N] = Gamma_class(N)
60
+ return _gamma_cache[N]
61
+
62
+
63
+ @richcmp_method
64
+ class Gamma_class(CongruenceSubgroup):
65
+ r"""
66
+ The principal congruence subgroup `\Gamma(N)`.
67
+ """
68
+ def _repr_(self):
69
+ """
70
+ Return the string representation of ``self``.
71
+
72
+ EXAMPLES::
73
+
74
+ sage: Gamma(133)._repr_()
75
+ 'Congruence Subgroup Gamma(133)'
76
+ """
77
+ return "Congruence Subgroup Gamma(%s)" % self.level()
78
+
79
+ def _latex_(self):
80
+ r"""
81
+ Return the \LaTeX representation of ``self``.
82
+
83
+ EXAMPLES::
84
+
85
+ sage: Gamma(20)._latex_()
86
+ '\\Gamma(20)'
87
+ sage: latex(Gamma(20))
88
+ \Gamma(20)
89
+ """
90
+ return "\\Gamma(%s)" % self.level()
91
+
92
+ def __reduce__(self):
93
+ """
94
+ Used for pickling ``self``.
95
+
96
+ EXAMPLES::
97
+
98
+ sage: Gamma(5).__reduce__()
99
+ (<function Gamma_constructor at ...>, (5,))
100
+ """
101
+ return Gamma_constructor, (self.level(),)
102
+
103
+ def __richcmp__(self, other, op):
104
+ r"""
105
+ Compare ``self`` to ``other``.
106
+
107
+ EXAMPLES::
108
+
109
+ sage: Gamma(3) == SymmetricGroup(8) # needs sage.groups
110
+ False
111
+ sage: Gamma(3) == Gamma1(3)
112
+ False
113
+ sage: Gamma(5) < Gamma(6)
114
+ True
115
+ sage: Gamma(5) == Gamma(5)
116
+ True
117
+ sage: Gamma(3) == Gamma(3).as_permutation_group() # needs sage.groups
118
+ True
119
+ """
120
+ if isinstance(other, Gamma_class):
121
+ return richcmp(self.level(), other.level(), op)
122
+ else:
123
+ return NotImplemented
124
+
125
+ def index(self):
126
+ r"""
127
+ Return the index of ``self`` in the full modular group. This is given by
128
+
129
+ .. MATH::
130
+
131
+ \prod_{\substack{p \mid N \\ \text{$p$ prime}}}\left(p^{3e}-p^{3e-2}\right).
132
+
133
+ EXAMPLES::
134
+
135
+ sage: [Gamma(n).index() for n in [1..19]]
136
+ [1, 6, 24, 48, 120, 144, 336, 384, 648, 720, 1320, 1152, 2184, 2016, 2880, 3072, 4896, 3888, 6840]
137
+ sage: Gamma(32041).index()
138
+ 32893086819240
139
+ """
140
+ return prod([p**(3*e-2)*(p*p-1) for (p,e) in self.level().factor()])
141
+
142
+ def _contains_sl2(self, a, b, c, d):
143
+ r"""
144
+ EXAMPLES::
145
+
146
+ sage: G = Gamma(5)
147
+ sage: [1, 0, -10, 1] in G
148
+ True
149
+ sage: 1 in G
150
+ True
151
+ sage: SL2Z([26, 5, 5, 1]) in G
152
+ True
153
+ sage: SL2Z([1, 1, 6, 7]) in G
154
+ False
155
+ """
156
+ N = self.level()
157
+ # don't need to check d == 1 as this is automatic from det
158
+ return ((a % N == 1) and (b % N == 0) and (c % N == 0))
159
+
160
+ def ncusps(self):
161
+ r"""
162
+ Return the number of cusps of this subgroup `\Gamma(N)`.
163
+
164
+ EXAMPLES::
165
+
166
+ sage: [Gamma(n).ncusps() for n in [1..19]]
167
+ [1, 3, 4, 6, 12, 12, 24, 24, 36, 36, 60, 48, 84, 72, 96, 96, 144, 108, 180]
168
+ sage: Gamma(30030).ncusps()
169
+ 278691840
170
+ sage: Gamma(2^30).ncusps()
171
+ 432345564227567616
172
+ """
173
+ n = self.level()
174
+ if n == 1:
175
+ return ZZ(1)
176
+ if n == 2:
177
+ return ZZ(3)
178
+ return prod([p**(2*e) - p**(2*e-2) for (p,e) in n.factor()])//2
179
+
180
+ def nirregcusps(self):
181
+ r"""
182
+ Return the number of irregular cusps of ``self``. For principal
183
+ congruence subgroups this is always 0.
184
+
185
+ EXAMPLES::
186
+
187
+ sage: Gamma(17).nirregcusps()
188
+ 0
189
+ """
190
+ return 0
191
+
192
+ def _find_cusps(self):
193
+ r"""
194
+ Calculate the reduced representatives of the equivalence classes of
195
+ cusps for this group. Adapted from code by Ron Evans.
196
+
197
+ EXAMPLES::
198
+
199
+ sage: Gamma(8).cusps() # indirect doctest
200
+ [0, 1/4, 1/3, 3/8, 1/2, 2/3, 3/4, 1, 4/3, 3/2, 5/3, 2, 7/3, 5/2, 8/3, 3, 7/2, 11/3, 4, 14/3, 5, 6, 7, Infinity]
201
+ """
202
+ n = self.level()
203
+ C = [QQ(x) for x in range(n)]
204
+
205
+ n0 = n//2
206
+ n1 = (n+1)//2
207
+
208
+ for r in range(1, n1):
209
+ if r > 1 and gcd(r,n) == 1:
210
+ C.append(ZZ(r)/ZZ(n))
211
+ if n0 == n/2 and gcd(r,n0) == 1:
212
+ C.append(ZZ(r)/ZZ(n0))
213
+
214
+ for s in range(2,n1):
215
+ for r in range(1, 1+n):
216
+ if GCD_list([s,r,n]) == 1:
217
+ # GCD_list is ~40x faster than gcd, since gcd wastes loads
218
+ # of time initialising a Sequence type.
219
+ u,v = _lift_pair(r,s,n)
220
+ C.append(ZZ(u)/ZZ(v))
221
+
222
+ return [Cusp(x) for x in sorted(C)] + [Cusp(1,0)]
223
+
224
+ def reduce_cusp(self, c):
225
+ r"""
226
+ Calculate the unique reduced representative of the equivalence of the
227
+ cusp `c` modulo this group. The reduced representative of an
228
+ equivalence class is the unique cusp in the class of the form `u/v`
229
+ with `u, v \ge 0` coprime, `v` minimal, and `u` minimal for that `v`.
230
+
231
+ EXAMPLES::
232
+
233
+ sage: Gamma(5).reduce_cusp(1/5)
234
+ Infinity
235
+ sage: Gamma(5).reduce_cusp(7/8)
236
+ 3/2
237
+ sage: Gamma(6).reduce_cusp(4/3)
238
+ 2/3
239
+
240
+ TESTS::
241
+
242
+ sage: G = Gamma(50)
243
+ sage: all(c == G.reduce_cusp(c) for c in G.cusps())
244
+ True
245
+
246
+ We test that :issue:`36163` is fixed::
247
+
248
+ sage: Gamma(7).reduce_cusp(Cusp(6,7))
249
+ Infinity
250
+ """
251
+ N = self.level()
252
+ c = Cusp(c)
253
+ u,v = c.numerator() % N, c.denominator() % N
254
+ if (v > N//2) or (2*v == N and u > N//2):
255
+ u,v = -u,-v
256
+ u,v = _lift_pair(u,v,N)
257
+ return Cusp(u,v)
258
+
259
+ def are_equivalent(self, x, y, trans=False):
260
+ r"""
261
+ Check if the cusps `x` and `y` are equivalent under the action of this group.
262
+
263
+ ALGORITHM: The cusps `u_1 / v_1` and `u_2 / v_2` are equivalent modulo
264
+ `\Gamma(N)` if and only if `(u_1, v_1) = \pm (u_2, v_2) \bmod N`.
265
+
266
+ EXAMPLES::
267
+
268
+ sage: Gamma(7).are_equivalent(Cusp(2/3), Cusp(5/4))
269
+ True
270
+ """
271
+ if trans:
272
+ return CongruenceSubgroup.are_equivalent(self, x,y,trans=trans)
273
+ N = self.level()
274
+ u1,v1 = (x.numerator() % N, x.denominator() % N)
275
+ u2,v2 = (y.numerator(), y.denominator())
276
+
277
+ return ((u1,v1) == (u2 % N, v2 % N)) or ((u1,v1) == (-u2 % N, -v2 % N))
278
+
279
+ def nu3(self):
280
+ r"""
281
+ Return the number of elliptic points of order 3 for this arithmetic
282
+ subgroup. Since this subgroup is `\Gamma(N)` for `N \ge 2`, there are
283
+ no such points, so we return 0.
284
+
285
+ EXAMPLES::
286
+
287
+ sage: Gamma(89).nu3()
288
+ 0
289
+ """
290
+ return 0
291
+
292
+ # We don't need to override nu2, since the default nu2 implementation knows
293
+ # that nu2 = 0 for odd subgroups.
294
+
295
+ def image_mod_n(self):
296
+ r"""
297
+ Return the image of this group modulo `N`, as a subgroup of `SL(2, \ZZ
298
+ / N\ZZ)`. This is just the trivial subgroup.
299
+
300
+ EXAMPLES::
301
+
302
+ sage: Gamma(3).image_mod_n()
303
+ Matrix group over Ring of integers modulo 3 with 1 generators (
304
+ [1 0]
305
+ [0 1]
306
+ )
307
+ """
308
+ return MatrixGroup([matrix(Zmod(self.level()), 2, 2, 1)])
309
+
310
+
311
+ def is_Gamma(x):
312
+ r"""
313
+ Return ``True`` if x is a congruence subgroup of type Gamma.
314
+
315
+ EXAMPLES::
316
+
317
+ sage: from sage.modular.arithgroup.congroup_gamma import Gamma_class
318
+ sage: isinstance(Gamma0(13), Gamma_class)
319
+ False
320
+ sage: isinstance(Gamma(4), Gamma_class)
321
+ True
322
+ """
323
+ from sage.misc.superseded import deprecation
324
+ deprecation(38035, "The function is_Gamma is deprecated; use 'isinstance(..., Gamma_class)' instead.")
325
+ return isinstance(x, Gamma_class)
326
+
327
+
328
+ def _lift_pair(U, V, N):
329
+ r"""
330
+ Utility function. Given integers ``U, V, N``, with `N \ge 1` and `{\rm
331
+ gcd}(U, V, N) = 1`, return a pair `(u, v)` congruent to `(U, V) \bmod N`,
332
+ such that `{\rm gcd}(u,v) = 1`, `u, v \ge 0`, `v` is as small as possible,
333
+ and `u` is as small as possible for that `v`.
334
+
335
+ *Warning*: As this function is for internal use, it does not do a
336
+ preliminary sanity check on its input, for efficiency. It will recover
337
+ reasonably gracefully if ``(U, V, N)`` are not coprime, but only after
338
+ wasting quite a lot of cycles!
339
+
340
+ EXAMPLES::
341
+
342
+ sage: from sage.modular.arithgroup.congroup_gamma import _lift_pair
343
+ sage: _lift_pair(2,4,7)
344
+ (9, 4)
345
+ sage: _lift_pair(2,4,8) # don't do this
346
+ Traceback (most recent call last):
347
+ ...
348
+ ValueError: (U, V, N) must be coprime
349
+ """
350
+ u = U % N
351
+ v = V % N
352
+ if v == 0:
353
+ if u == 1 or u == N-1:
354
+ return (1,0)
355
+ else:
356
+ v = N
357
+ while gcd(u, v) > 1:
358
+ u = u+N
359
+ if u > N*v:
360
+ raise ValueError("(U, V, N) must be coprime")
361
+ return (u, v)