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,1067 @@
1
+ # sage_setup: distribution = sagemath-schemes
2
+ # distutils: sources = sage/modular/arithgroup/sl2z.cpp sage/modular/arithgroup/farey.cpp
3
+ # distutils: language = c++
4
+ # distutils: extra_compile_args = -std=c++17
5
+ # sage.doctest: needs sage.libs.pari
6
+ r"""
7
+ Farey symbol for arithmetic subgroups of `\PSL_2(\ZZ)`
8
+
9
+ AUTHORS:
10
+
11
+ - Hartmut Monien (08 - 2011)
12
+
13
+ based on the *KFarey* package by Chris Kurth. Implemented as C++ module
14
+ for speed.
15
+ """
16
+
17
+ # ****************************************************************************
18
+ # Copyright (C) 2011 Hartmut Monien <monien@th.physik.uni-bonn.de>
19
+ #
20
+ # This program is free software: you can redistribute it and/or modify
21
+ # it under the terms of the GNU General Public License as published by
22
+ # the Free Software Foundation, either version 2 of the License, or
23
+ # (at your option) any later version.
24
+ # https://www.gnu.org/licenses/
25
+ # ****************************************************************************
26
+
27
+ from cpython.object cimport PyObject_RichCompare
28
+ from itertools import groupby
29
+ from cysignals.signals cimport sig_on, sig_off
30
+
31
+ from sage.libs.gmpxx cimport *
32
+
33
+ from sage.rings.real_mpfr import RR
34
+ from sage.rings.cc import CC
35
+ from sage.rings.integer cimport Integer
36
+ from sage.rings.infinity import infinity
37
+ from .congroup_gammaH import GammaH_class
38
+ from .congroup_gamma1 import Gamma1_class
39
+ from .congroup_gamma0 import Gamma0_class
40
+ from .congroup_gamma import Gamma_class
41
+ from .congroup_sl2z import SL2Z
42
+ from sage.modular.cusps import Cusp
43
+
44
+ from sage.misc.decorators import options
45
+ from sage.misc.cachefunc import cached_method
46
+ from sage.structure.richcmp cimport richcmp_not_equal
47
+
48
+
49
+ cdef extern from "sl2z.hpp":
50
+ cppclass cpp_SL2Z "SL2Z":
51
+ cpp_SL2Z(int, int, int, int)
52
+ cpp_SL2Z(mpz_class, mpz_class, mpz_class, mpz_class)
53
+ mpz_class a()
54
+ mpz_class b()
55
+ mpz_class c()
56
+ mpz_class d()
57
+
58
+ cdef extern from "farey.hpp":
59
+ cppclass is_element_Gamma0:
60
+ is_element_Gamma0(int)
61
+ cppclass is_element_Gamma1:
62
+ is_element_Gamma1(int)
63
+ cppclass is_element_Gamma:
64
+ is_element_Gamma(int)
65
+ cppclass is_element_GammaH:
66
+ is_element_GammaH(int, object)
67
+ cppclass cpp_farey "FareySymbol":
68
+ cpp_farey()
69
+ cpp_farey(object)
70
+ cpp_farey(object, is_element_Gamma*)
71
+ cpp_farey(object, is_element_Gamma0*)
72
+ cpp_farey(object, is_element_Gamma1*)
73
+ cpp_farey(object, is_element_GammaH*)
74
+ size_t genus()
75
+ size_t index()
76
+ size_t level()
77
+ size_t nu2()
78
+ size_t nu3()
79
+ object is_element(mpz_t, mpz_t, mpz_t, mpz_t)
80
+ object word_problem(mpz_t, mpz_t, mpz_t, mpz_t, cpp_SL2Z *)
81
+ size_t get_cusp_class(mpz_t, mpz_t)
82
+ object get_cusps()
83
+ object get_cusp_widths()
84
+ object get_transformation_to_cusp(mpz_t, mpz_t)
85
+ object get_fractions()
86
+ object get_coset()
87
+ object get_generators()
88
+ object get_pairings()
89
+ object get_paired_sides()
90
+ object get_pairing_matrices()
91
+ object dumps()
92
+
93
+
94
+ cdef class Farey:
95
+ r"""
96
+ A class for calculating Farey symbols of arithmetics subgroups of
97
+ `\PSL_2(\ZZ)`.
98
+
99
+ The arithmetic subgroup can be either any of
100
+ the congruence subgroups implemented in Sage, i.e. Gamma, Gamma0,
101
+ Gamma1 and GammaH or a subgroup of `\PSL_2(\ZZ)` which is
102
+ given by a user written helper class defining membership in that
103
+ group.
104
+
105
+ REFERENCES:
106
+
107
+ - Ravi S. Kulkarni, ''An arithmetic-geometric method in the study of the
108
+ subgroups of the modular group'', `Amer. J. Math., 113(6):1053--1133,
109
+ 1991. <http://www.jstor.org/stable/2374900>`_
110
+
111
+ INPUT:
112
+
113
+ - ``G`` -- an arithmetic subgroup of `\PSL_2(\ZZ)`
114
+
115
+ EXAMPLES:
116
+
117
+ Create a Farey symbol for the group `\Gamma_0(11)`::
118
+
119
+ sage: f = FareySymbol(Gamma0(11)); f
120
+ FareySymbol(Congruence Subgroup Gamma0(11))
121
+
122
+ Calculate the generators::
123
+
124
+ sage: f.generators()
125
+ [
126
+ [1 1] [ 7 -2] [ 8 -3] [-1 0]
127
+ [0 1], [11 -3], [11 -4], [ 0 -1]
128
+ ]
129
+
130
+ Pickling the FareySymbol and recovering it::
131
+
132
+ sage: f == loads(dumps(f))
133
+ True
134
+
135
+ Calculate the index of `\Gamma_H(33, [2, 5])` in
136
+ `\PSL_2(\ZZ)` via FareySymbol::
137
+
138
+ sage: FareySymbol(GammaH(33, [2, 5])).index()
139
+ 48
140
+
141
+ Calculate the generators of `\Gamma_1(4)`::
142
+
143
+ sage: FareySymbol(Gamma1(4)).generators()
144
+ [
145
+ [1 1] [-3 1]
146
+ [0 1], [-4 1]
147
+ ]
148
+
149
+ Calculate the generators of the :meth:`example
150
+ <sage.modular.arithgroup.arithgroup_perm.HsuExample10>` of an
151
+ index 10 arithmetic subgroup given by Tim Hsu::
152
+
153
+ sage: from sage.modular.arithgroup.arithgroup_perm import HsuExample10 # needs sage.groups
154
+ sage: FareySymbol(HsuExample10()).generators() # needs sage.groups
155
+ [
156
+ [1 2] [-2 1] [ 4 -3]
157
+ [0 1], [-7 3], [ 3 -2]
158
+ ]
159
+
160
+ Calculate the generators of the group `\Gamma' =
161
+ \Gamma_0(8)\cap\Gamma_1(4)` using a helper class to define group membership::
162
+
163
+ sage: class GPrime:
164
+ ....: def __contains__(self, M):
165
+ ....: return M in Gamma0(8) and M in Gamma1(4)
166
+
167
+ sage: FareySymbol(GPrime()).generators()
168
+ [
169
+ [1 1] [ 5 -1] [ 5 -2]
170
+ [0 1], [16 -3], [ 8 -3]
171
+ ]
172
+
173
+ Calculate cusps of arithmetic subgroup defined via permutation group::
174
+
175
+ sage: # needs sage.groups
176
+ sage: L = SymmetricGroup(4)('(1, 2, 3)')
177
+ sage: R = SymmetricGroup(4)('(1, 2, 4)')
178
+ sage: FareySymbol(ArithmeticSubgroup_Permutation(L, R)).cusps()
179
+ [-1, Infinity]
180
+
181
+ Calculate the left coset representation of `\Gamma_H(8, [3])`::
182
+
183
+ sage: FareySymbol(GammaH(8, [3])).coset_reps()
184
+ [
185
+ [1 0] [ 4 -1] [ 3 -1] [ 2 -1] [ 1 -1] [ 3 -1] [ 2 -1] [-1 0]
186
+ [0 1], [ 1 0], [ 1 0], [ 1 0], [ 1 0], [ 4 -1], [ 3 -1], [ 3 -1],
187
+ [ 1 -1] [-1 0] [ 0 -1] [-1 0]
188
+ [ 2 -1], [ 2 -1], [ 1 -1], [ 1 -1]
189
+ ]
190
+ """
191
+ cdef cpp_farey *this_ptr
192
+ cdef object group
193
+
194
+ def __cinit__(self, group, data=None):
195
+ r"""
196
+ Initialize FareySymbol::
197
+
198
+ sage: FareySymbol(Gamma0(23))
199
+ FareySymbol(Congruence Subgroup Gamma0(23))
200
+ """
201
+ self.group = group
202
+ # if data is present we want to restore
203
+ if data is not None:
204
+ sig_on()
205
+ self.this_ptr = new cpp_farey(data)
206
+ sig_off()
207
+ return
208
+ # to accelerate the calculation of the FareySymbol
209
+ # we implement the tests for the standard congruence groups
210
+ # in the c++ module. For a general group the test if an element
211
+ # of SL2Z is in the group the python __contains__ attribute
212
+ # of the group is called
213
+ cdef int p
214
+ if hasattr(group, "level"):
215
+ p = group.level()
216
+ if group == SL2Z:
217
+ sig_on()
218
+ self.this_ptr = new cpp_farey()
219
+ sig_off()
220
+ elif isinstance(group, Gamma0_class):
221
+ sig_on()
222
+ self.this_ptr = new cpp_farey(group, new is_element_Gamma0(p))
223
+ sig_off()
224
+ elif isinstance(group, Gamma1_class):
225
+ sig_on()
226
+ self.this_ptr = new cpp_farey(group, new is_element_Gamma1(p))
227
+ sig_off()
228
+ elif isinstance(group, Gamma_class):
229
+ sig_on()
230
+ self.this_ptr = new cpp_farey(group, new is_element_Gamma(p))
231
+ sig_off()
232
+ elif isinstance(group, GammaH_class):
233
+ sig_on()
234
+ l = group._GammaH_class__H
235
+ self.this_ptr = new cpp_farey(group, new is_element_GammaH(p, l))
236
+ sig_off()
237
+ else:
238
+ sig_on()
239
+ self.this_ptr = new cpp_farey(group)
240
+ sig_off()
241
+
242
+ def __dealloc__(self):
243
+ r"""
244
+ Remove reference to FareySymbol.
245
+
246
+ TESTS::
247
+
248
+ sage: F = FareySymbol(Gamma0(23))
249
+ sage: del F
250
+ """
251
+ del self.this_ptr
252
+
253
+ @cached_method
254
+ def pairing_matrices_to_tietze_index(self):
255
+ r"""
256
+ Obtain the translation table from pairing matrices
257
+ to generators.
258
+
259
+ The result is cached.
260
+
261
+ OUTPUT:
262
+
263
+ a list where the `i`-th entry is a nonzero integer `k`,
264
+ such that if `k > 0` then the `i`-th pairing matrix is (up to sign)
265
+ the `(k-1)`-th generator and, if `k < 0`, then the `i`-th pairing
266
+ matrix is (up to sign) the inverse of the `(-k-1)`-th generator.
267
+
268
+ EXAMPLES::
269
+
270
+ sage: F = Gamma0(40).farey_symbol()
271
+ sage: table = F.pairing_matrices_to_tietze_index()
272
+ sage: table[12]
273
+ (-2, -1)
274
+ sage: F.pairing_matrices()[12]
275
+ [ 3 -1]
276
+ [ 40 -13]
277
+ sage: F.generators()[1]**-1
278
+ [ -3 1]
279
+ [-40 13]
280
+ """
281
+ gens_dict = {g: i+1 for i, g in enumerate(self.generators())}
282
+ ans = []
283
+ for pm in self.pairing_matrices():
284
+ a, b, c, d = pm.matrix().list()
285
+ newval = gens_dict.get(SL2Z([a, b, c, d]))
286
+ if newval is not None:
287
+ ans.append((newval, 1))
288
+ continue
289
+ newval = gens_dict.get(SL2Z([-a, -b, -c, -d]))
290
+ if newval is not None:
291
+ ans.append((newval, -1))
292
+ continue
293
+ newval = gens_dict.get(SL2Z([d, -b, -c, a]))
294
+ if newval is not None:
295
+ ans.append((-newval, 1))
296
+ continue
297
+ newval = gens_dict.get(SL2Z([-d, b, c, -a]))
298
+ if newval is not None:
299
+ ans.append((-newval, -1))
300
+ continue
301
+ raise RuntimeError("This should have not happened")
302
+ return ans
303
+
304
+ @cached_method
305
+ def _get_minus_one(self):
306
+ r"""
307
+ If -I belongs to ``self``, return a Tietze word representing it.
308
+ Otherwise return ``[]``.
309
+
310
+ EXAMPLES::
311
+
312
+ sage: Gamma1(30).farey_symbol()._get_minus_one()
313
+ []
314
+ sage: G = Gamma0(30).farey_symbol()
315
+ sage: G._get_minus_one()
316
+ [14]
317
+ sage: g = G.generators()[13]
318
+ sage: (-g.matrix()).is_one()
319
+ True
320
+ sage: G = Gamma(1).farey_symbol()
321
+ sage: G._get_minus_one()
322
+ [1, 1]
323
+ sage: g = G.generators()[0]**2
324
+ sage: (-g.matrix()).is_one()
325
+ True
326
+ sage: G = Gamma0(3).farey_symbol()
327
+ sage: G._get_minus_one()
328
+ [2, 2, 2]
329
+ sage: g = G.generators()[1]**3
330
+ sage: (-g.matrix()).is_one()
331
+ True
332
+ """
333
+ for i, g in enumerate(self.generators()):
334
+ m = g.matrix()
335
+ if (-m).is_one():
336
+ return [i + 1]
337
+ t = m.trace()
338
+ if t == 0: # order = 4
339
+ return 2 * [i + 1]
340
+ elif t == 1: # order = 6
341
+ return 3 * [i + 1]
342
+ return []
343
+
344
+ def word_problem(self, M, output='standard', check=True):
345
+ r"""
346
+ Solve the word problem (up to sign) using this Farey symbol.
347
+
348
+ INPUT:
349
+
350
+ - ``M`` -- an element `M` of `\SL_2(\ZZ)`
351
+
352
+ - ``output`` -- (default: ``'standard'``) should be one of
353
+ ``'standard'``, ``'syllables'``, ``'gens'``.
354
+
355
+ - ``check`` -- boolean (default: ``True``); whether to check for
356
+ correct input and output
357
+
358
+ OUTPUT:
359
+
360
+ A solution to the word problem for the matrix `M`.
361
+ The format depends on the ``output`` parameter, as follows.
362
+
363
+ - ``'standard'`` returns the so called Tietze representation,
364
+ which consists of a tuple of nonzero integers. A positive
365
+ integer `i` indicates the `i`-th generator (that is,
366
+ ``self.generators()[i-1]``), while a negative integer `i`
367
+ indicates the inverse of the `i`-th generator.
368
+ - ``'syllables'`` returns a tuple of tuples of the form
369
+ `(i, n)`, where `(i, n)` represents ``self.generators()[i] ^ n``,
370
+ whose product equals `M` up to sign.
371
+ - ``'gens'`` returns a tuple of pairs `(g, n)`, where `g` is a
372
+ matrix and `n` an integer, such that the product of the
373
+ matrices `g^n` equals `M` up to sign.
374
+
375
+ EXAMPLES::
376
+
377
+ sage: F = Gamma0(30).farey_symbol()
378
+ sage: gens = F.generators()
379
+ sage: g = gens[3] * gens[10] * gens[8]^-1 * gens[5]
380
+ sage: g
381
+ [-628597 73008]
382
+ [-692130 80387]
383
+ sage: F.word_problem(g)
384
+ (4, 11, -9, 6)
385
+ sage: g = gens[3] * gens[10]^2 * gens[8]^-1 * gens[5]
386
+ sage: g
387
+ [-5048053 586303]
388
+ [-5558280 645563]
389
+ sage: F.word_problem(g, output='gens')
390
+ ((
391
+ [109 -10]
392
+ [120 -11], 1
393
+ ),
394
+ (
395
+ [ 19 -7]
396
+ [ 30 -11], 2
397
+ ),
398
+ (
399
+ [ 49 -9]
400
+ [ 60 -11], -1
401
+ ),
402
+ (
403
+ [17 -2]
404
+ [60 -7], 1
405
+ ))
406
+ sage: F.word_problem(g, output='syllables')
407
+ ((3, 1), (10, 2), (8, -1), (5, 1))
408
+
409
+ TESTS:
410
+
411
+ Check that problem with forgotten generator is fixed::
412
+
413
+ sage: from sage.misc.misc_c import prod
414
+ sage: G = Gamma0(10)
415
+ sage: F = G.farey_symbol()
416
+ sage: g = G([-701,-137,4600,899])
417
+ sage: g1 = prod(F.generators()[i]**a for i, a in F.word_problem(g, output='syllables'))
418
+ sage: g == g1
419
+ True
420
+
421
+ Check that it works for GammaH as well (:issue:`19660`)::
422
+
423
+ sage: G = GammaH(147, [8])
424
+ sage: G.farey_symbol().word_problem(G([1,1,0,1]))
425
+ (1,)
426
+
427
+ Check that :issue:`20347` is solved::
428
+
429
+ sage: # needs sage.groups
430
+ sage: from sage.misc.misc_c import prod
431
+ sage: G = ArithmeticSubgroup_Permutation(S2="(1,2)(3,4)", S3="(1,2,3)")
432
+ sage: S = G.farey_symbol()
433
+ sage: g1, g2 = S.generators()
434
+ sage: g = g1^3 * g2^-2 * g1 * g2
435
+ sage: S.word_problem(g)
436
+ (2, 2, 2, 1, 1, 1, 2, 1, 2)
437
+ sage: h = prod(S.generators()[i]**a for i, a in S.word_problem(g, output='syllables'))
438
+ sage: g == h
439
+ True
440
+
441
+ """
442
+ if output not in ['standard', 'syllables', 'gens']:
443
+ raise ValueError('Unrecognized output format')
444
+ if check:
445
+ if M not in self.group:
446
+ raise ValueError("Matrix ( %s ) is not in group ( %s )" % (M, self.group))
447
+ cdef Integer a = M.d()
448
+ cdef Integer b = -M.b()
449
+ cdef Integer c = -M.c()
450
+ cdef Integer d = M.a()
451
+ cdef cpp_SL2Z *cpp_beta = new cpp_SL2Z(1, 0, 0, 1)
452
+ sig_on()
453
+ result = self.this_ptr.word_problem(a.value, b.value, c.value, d.value, cpp_beta)
454
+ sig_off()
455
+ beta = convert_to_SL2Z(cpp_beta[0])**-1
456
+ mbeta = SL2Z([-beta.a(), -beta.b(), -beta.c(), -beta.d()])
457
+ V = self.pairing_matrices_to_tietze_index()
458
+ sgn = 1
459
+ tietze = []
460
+ for o in result:
461
+ if o > 0:
462
+ tietze.append(V[o-1][0])
463
+ sgn *= V[o-1][1]
464
+ else:
465
+ tietze.append(-V[-o-1][0])
466
+ sgn *= V[-o-1][1]
467
+ if sgn == -1:
468
+ beta, mbeta = mbeta, beta
469
+
470
+ gens_dict = {g: i+1 for i, g in enumerate(self.generators())}
471
+ extra_tietze = []
472
+ if beta.is_one():
473
+ found = True
474
+ elif mbeta.is_one():
475
+ found = True
476
+ extra_tietze = self._get_minus_one()
477
+ else:
478
+ found = False
479
+ if not found:
480
+ newval = gens_dict.get(beta)
481
+ if newval is not None:
482
+ found = True
483
+ extra_tietze = [newval]
484
+ if not found:
485
+ newval = gens_dict.get(beta**-1)
486
+ if newval is not None:
487
+ found = True
488
+ extra_tietze = [-newval]
489
+ if not found:
490
+ newval = gens_dict.get(mbeta)
491
+ if newval is not None:
492
+ found = True
493
+ extra_tietze = [newval] + self._get_minus_one()
494
+ if not found:
495
+ newval = gens_dict.get(mbeta**-1)
496
+ if newval is not None:
497
+ found = True
498
+ extra_tietze = [-newval] + self._get_minus_one()
499
+ tietze.extend(extra_tietze)
500
+ tietze.reverse()
501
+ gens = self.generators()
502
+ if check:
503
+ tmp = SL2Z([1, 0, 0, 1])
504
+ for i in range(len(tietze)):
505
+ t = tietze[i]
506
+ tmp = tmp * gens[t-1] if t > 0 else tmp * gens[-t-1]**-1
507
+ assert tmp.matrix() == M.matrix(), '%s %s %s' % (tietze, tmp.matrix(), M.matrix())
508
+ if output == 'standard':
509
+ return tuple(tietze)
510
+ if output == 'syllables':
511
+ return tuple((a-1, len(list(g))) if a > 0 else (-a-1, -len(list(g))) for a, g in groupby(tietze))
512
+ else: # output == 'gens'
513
+ return tuple((gens[a-1], len(list(g))) if a > 0 else (gens[-a-1], -len(list(g))) for a, g in groupby(tietze))
514
+
515
+ def __contains__(self, M) -> bool:
516
+ r"""
517
+ Test if element is in the arithmetic group of the Farey symbol
518
+ via LLT algorithm.
519
+
520
+ EXAMPLES::
521
+
522
+ sage: SL2Z([0, -1, 1, 0]) in FareySymbol(Gamma0(6))
523
+ False
524
+
525
+ sage: SL2Z([1, 1, 0, 1]) in FareySymbol(Gamma0(6))
526
+ True
527
+ """
528
+ cdef Integer a = M.a()
529
+ cdef Integer b = M.b()
530
+ cdef Integer c = M.c()
531
+ cdef Integer d = M.d()
532
+ sig_on()
533
+ result = self.this_ptr.is_element(a.value, b.value, c.value, d.value)
534
+ sig_off()
535
+ return result
536
+
537
+ def __richcmp__(self, other, op) -> bool:
538
+ r"""
539
+ Compare ``self`` to ``other``.
540
+
541
+ EXAMPLES::
542
+
543
+ sage: FareySymbol(Gamma(2)) == FareySymbol(Gamma0(7))
544
+ False
545
+
546
+ sage: FareySymbol(Gamma0(23)) == loads(dumps(FareySymbol(Gamma0(23))))
547
+ True
548
+ """
549
+ if not isinstance(other, Farey):
550
+ return NotImplemented
551
+
552
+ cosetA = self.coset_reps()
553
+ cosetB = other.coset_reps()
554
+ if cosetA != cosetB:
555
+ return richcmp_not_equal(cosetA, cosetB, op)
556
+
557
+ cuspA = self.cusps()
558
+ cuspB = other.cusps()
559
+ if cuspA != cuspB:
560
+ return richcmp_not_equal(cuspA, cuspB, op)
561
+
562
+ return PyObject_RichCompare(self.fractions(), other.fractions(), op)
563
+
564
+ def __reduce__(self):
565
+ r"""
566
+ Serialization for pickling::
567
+
568
+ sage: FareySymbol(Gamma0(4)).__reduce__()
569
+ (<class 'sage.modular.arithgroup.farey_symbol.Farey'>, ...))
570
+ """
571
+ return Farey, (self.group, self.this_ptr.dumps())
572
+
573
+ def __repr__(self) -> str:
574
+ r"""
575
+ Return the string representation of ``self``.
576
+
577
+ EXAMPLES::
578
+
579
+ sage: FareySymbol(Gamma0(23)).__repr__()
580
+ 'FareySymbol(Congruence Subgroup Gamma0(23))'
581
+ """
582
+ if hasattr(self.group, "_repr_"):
583
+ return "FareySymbol(%s)" % self.group._repr_()
584
+ elif hasattr(self.group, "__repr__"):
585
+ return "FareySymbol(%r)" % self.group
586
+ else:
587
+ return "FareySymbol(?)"
588
+
589
+ def _latex_(self, forced_format=None):
590
+ r"""
591
+ Return the LaTeX representation of ``self``.
592
+
593
+ INPUT:
594
+
595
+ - ``forced_format`` -- a format string ('plain' or 'xymatrix')
596
+ or ``None``
597
+
598
+ EXAMPLES::
599
+
600
+ sage: FareySymbol(Gamma0(11))._latex_(forced_format='plain')
601
+ '\\left( -\\infty\\underbrace{\\quad}_{1} 0\\underbrace{\\quad}_{2} \\frac{1}{3}\\underbrace{\\quad}_{3} \\frac{1}{2}\\underbrace{\\quad}_{2} \\frac{2}{3}\\underbrace{\\quad}_{3} 1\\underbrace{\\quad}_{1} \\infty\\right)'
602
+ sage: FareySymbol(Gamma0(11))._latex_(forced_format='xymatrix')
603
+ '\\begin{xy}\\xymatrix{& -\\infty \\ar@{-}@/_1pc/[r]_{1}& 0 \\ar@{-}@/_1pc/[r]_{2}& \\frac{1}{3} \\ar@{-}@/_1pc/[r]_{3}& \\frac{1}{2} \\ar@{-}@/_1pc/[r]_{2}& \\frac{2}{3} \\ar@{-}@/_1pc/[r]_{3}& 1 \\ar@{-}@/_1pc/[r]_{1}& \\infty }\\end{xy}'
604
+
605
+ sage: 'xymatrix' in FareySymbol(Gamma0(11))._latex_()
606
+ True
607
+ """
608
+ if forced_format == 'plain':
609
+ # output not using xymatrix
610
+ s = r'\left( -\infty'
611
+ a = [x._latex_() for x in self.fractions()] + [r'\infty']
612
+ b = self.pairings()
613
+ for i in range(len(a)):
614
+ u = b[i]
615
+ if u == -3:
616
+ u = r'\bullet'
617
+ elif u == -2:
618
+ u = r'\circ'
619
+ s += r'\underbrace{\quad}_{%s} %s' % (u, a[i])
620
+ return s + r'\right)'
621
+ else:
622
+ # output using xymatrix
623
+ s = r'\begin{xy}\xymatrix{& -\infty '
624
+ f = [x._latex_() for x in self.fractions()] + [r'\infty']
625
+ f.reverse()
626
+ for p in self.pairings():
627
+ if p >= 0:
628
+ s += r'\ar@{-}@/_1pc/[r]_{%s}' % p
629
+ elif p == -2:
630
+ s += r'\ar@{-}@/_1pc/[r]_{\circ}'
631
+ elif p == -3:
632
+ s += r'\ar@{-}@/_1pc/[r]_{\bullet}'
633
+ s += r'& %s ' % f.pop()
634
+ s += r'}\end{xy}'
635
+ return s
636
+
637
+ def index(self):
638
+ r"""
639
+ Return the index of the arithmetic group of the FareySymbol
640
+ in `\PSL_2(\ZZ)`.
641
+
642
+ EXAMPLES::
643
+
644
+ sage: [FareySymbol(Gamma0(n)).index() for n in range(1, 16)]
645
+ [1, 3, 4, 6, 6, 12, 8, 12, 12, 18, 12, 24, 14, 24, 24]
646
+ """
647
+ return self.this_ptr.index()
648
+
649
+ def genus(self):
650
+ r"""
651
+ Return the genus of the arithmetic group of the FareySymbol.
652
+
653
+ EXAMPLES::
654
+
655
+ sage: [FareySymbol(Gamma0(n)).genus() for n in range(16, 32)]
656
+ [0, 1, 0, 1, 1, 1, 2, 2, 1, 0, 2, 1, 2, 2, 3, 2]
657
+ """
658
+ return self.this_ptr.genus()
659
+
660
+ def level(self):
661
+ r"""
662
+ Return the level of the arithmetic group of the FareySymbol.
663
+
664
+ EXAMPLES::
665
+
666
+ sage: [FareySymbol(Gamma0(n)).level() for n in range(1, 16)]
667
+ [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]
668
+ """
669
+ return self.this_ptr.level()
670
+
671
+ def nu2(self):
672
+ r"""
673
+ Return the number of elliptic points of order two.
674
+
675
+ EXAMPLES::
676
+
677
+ sage: [FareySymbol(Gamma0(n)).nu2() for n in range(1, 16)]
678
+ [1, 1, 0, 0, 2, 0, 0, 0, 0, 2, 0, 0, 2, 0, 0]
679
+ """
680
+ return self.this_ptr.nu2()
681
+
682
+ def nu3(self):
683
+ r"""
684
+ Return the number of elliptic points of order three.
685
+
686
+ EXAMPLES::
687
+
688
+ sage: [FareySymbol(Gamma0(n)).nu3() for n in range(1, 16)]
689
+ [1, 0, 1, 0, 0, 0, 2, 0, 0, 0, 0, 0, 2, 0, 0]
690
+ """
691
+ return self.this_ptr.nu3()
692
+
693
+ def coset_reps(self):
694
+ r"""
695
+ Left coset of the arithmetic group of the FareySymbol.
696
+
697
+ EXAMPLES:
698
+
699
+ Calculate the left coset of `\Gamma_0(6)`::
700
+
701
+ sage: FareySymbol(Gamma0(6)).coset_reps()
702
+ [
703
+ [1 0] [ 3 -1] [ 2 -1] [ 1 -1] [ 2 -1] [ 3 -2] [ 1 -1] [-1 0]
704
+ [0 1], [ 1 0], [ 1 0], [ 1 0], [ 3 -1], [ 2 -1], [ 2 -1], [ 2 -1],
705
+ [ 1 -1] [ 0 -1] [-1 0] [-2 1]
706
+ [ 3 -2], [ 1 -1], [ 1 -1], [ 1 -1]
707
+ ]
708
+ """
709
+ return self.this_ptr.get_coset()
710
+
711
+ def generators(self):
712
+ r"""
713
+ Minimal set of generators of the group of the FareySymbol.
714
+
715
+ EXAMPLES:
716
+
717
+ Calculate the generators of `\Gamma_0(6)`::
718
+
719
+ sage: FareySymbol(Gamma0(6)).generators()
720
+ [
721
+ [1 1] [ 5 -1] [ 7 -3] [-1 0]
722
+ [0 1], [ 6 -1], [12 -5], [ 0 -1]
723
+ ]
724
+
725
+ Calculate the generators of `\SL_2(\ZZ)`::
726
+
727
+ sage: FareySymbol(SL2Z).generators()
728
+ [
729
+ [ 0 -1] [ 0 -1]
730
+ [ 1 0], [ 1 -1]
731
+ ]
732
+
733
+ The unique index 2 even subgroup and index 4 odd subgroup each get handled correctly::
734
+
735
+ sage: # needs sage.groups
736
+ sage: FareySymbol(ArithmeticSubgroup_Permutation(S2="(1,2)", S3="()")).generators()
737
+ [
738
+ [ 0 1] [-1 1]
739
+ [-1 -1], [-1 0]
740
+ ]
741
+ sage: FareySymbol(ArithmeticSubgroup_Permutation(S2="(1,2, 3, 4)", S3="(1,3)(2,4)")).generators()
742
+ [
743
+ [ 0 1] [-1 1]
744
+ [-1 -1], [-1 0]
745
+ ]
746
+ """
747
+ return self.this_ptr.get_generators()
748
+
749
+ def fractions(self):
750
+ r"""
751
+ Fractions of the FareySymbol.
752
+
753
+ EXAMPLES::
754
+
755
+ sage: FareySymbol(Gamma(4)).fractions()
756
+ [0, 1/2, 1, 3/2, 2, 5/2, 3, 7/2, 4]
757
+ """
758
+ return self.this_ptr.get_fractions()
759
+
760
+ def pairings(self):
761
+ r"""
762
+ Pairings of the sides of the fundamental domain of the Farey symbol
763
+ of the arithmetic group.
764
+
765
+ The sides of the hyperbolic polygon are
766
+ numbered 0, 1, ... from left to right. Conventions: even pairings are
767
+ denoted by -2, odd pairings by -3 while free pairings are denoted by
768
+ an integer number greater than zero.
769
+
770
+ EXAMPLES:
771
+
772
+ Odd pairings::
773
+
774
+ sage: FareySymbol(Gamma0(7)).pairings()
775
+ [1, -3, -3, 1]
776
+
777
+ Even and odd pairings::
778
+
779
+ FareySymbol(Gamma0(13)).pairings()
780
+ [1, -3, -2, -2, -3, 1]
781
+
782
+ Only free pairings::
783
+
784
+ sage: FareySymbol(Gamma0(23)).pairings()
785
+ [1, 2, 3, 5, 3, 4, 2, 4, 5, 1]
786
+ """
787
+ return self.this_ptr.get_pairings()
788
+
789
+ def paired_sides(self):
790
+ r"""
791
+ Pairs of index of the sides of the fundamental domain of the
792
+ Farey symbol of the arithmetic group. The sides of the
793
+ hyperbolic polygon are numbered 0, 1, ... from left to right.
794
+
795
+ .. image:: ../../../media/pairing.png
796
+
797
+ EXAMPLES::
798
+
799
+ sage: FareySymbol(Gamma0(11)).paired_sides()
800
+ [(0, 5), (1, 3), (2, 4)]
801
+
802
+ indicating that the side 0 is paired with 5, 1 with 3 and 2 with 4.
803
+ """
804
+ return self.this_ptr.get_paired_sides()
805
+
806
+ def pairing_matrices(self):
807
+ r"""
808
+ Pairing matrices of the sides of the fundamental domain. The sides
809
+ of the hyperbolic polygon are numbered 0, 1, ... from left to right.
810
+
811
+ EXAMPLES::
812
+
813
+ sage: FareySymbol(Gamma0(6)).pairing_matrices()
814
+ [
815
+ [1 1] [ 5 -1] [ 7 -3] [ 5 -3] [ 1 -1] [-1 1]
816
+ [0 1], [ 6 -1], [12 -5], [12 -7], [ 6 -5], [ 0 -1]
817
+ ]
818
+ """
819
+
820
+ return self.this_ptr.get_pairing_matrices()
821
+
822
+ def cusps(self):
823
+ r"""
824
+ Cusps of the FareySymbol.
825
+
826
+ EXAMPLES::
827
+
828
+ sage: FareySymbol(Gamma0(6)).cusps()
829
+ [0, 1/3, 1/2, Infinity]
830
+ """
831
+ return self.this_ptr.get_cusps()+[Cusp(infinity)]
832
+
833
+ def cusp_widths(self):
834
+ r"""
835
+ Cusps widths of the FareySymbol.
836
+
837
+ EXAMPLES::
838
+
839
+ sage: FareySymbol(Gamma0(6)).cusp_widths()
840
+ [6, 2, 3, 1]
841
+ """
842
+ return self.this_ptr.get_cusp_widths()
843
+
844
+ def cusp_class(self, c):
845
+ r"""
846
+ Cusp class of a cusp in the FareySymbol.
847
+
848
+ INPUT:
849
+
850
+ - ``c`` -- a cusp
851
+
852
+ EXAMPLES::
853
+
854
+ sage: FareySymbol(Gamma0(12)).cusp_class(Cusp(1, 12))
855
+ 5
856
+ """
857
+ cusp = Cusp(c)
858
+ cdef Integer p = cusp.numerator()
859
+ cdef Integer q = cusp.denominator()
860
+ sig_on()
861
+ result = self.this_ptr.get_cusp_class(p.value, q.value)
862
+ sig_off()
863
+ return result
864
+
865
+ def reduce_to_cusp(self, r):
866
+ r"""
867
+ Transformation of a rational number to cusp representative.
868
+
869
+ INPUT:
870
+
871
+ - ``r`` -- a rational number
872
+
873
+ EXAMPLES::
874
+
875
+ sage: FareySymbol(Gamma0(12)).reduce_to_cusp(5/8)
876
+ [ 5 -3]
877
+ [12 -7]
878
+
879
+ Reduce 11/17 to a cusp of for HsuExample10()::
880
+
881
+ sage: # needs sage.groups
882
+ sage: from sage.modular.arithgroup.arithgroup_perm import HsuExample10
883
+ sage: f = FareySymbol(HsuExample10())
884
+ sage: f.reduce_to_cusp(11/17)
885
+ [14 -9]
886
+ [-3 2]
887
+ sage: _.acton(11/17)
888
+ 1
889
+ sage: f.cusps()[f.cusp_class(11/17)]
890
+ 1
891
+ """
892
+ cdef Integer p = r.numerator()
893
+ cdef Integer q = r.denominator()
894
+ sig_on()
895
+ result = self.this_ptr.get_transformation_to_cusp(p.value, q.value)
896
+ sig_off()
897
+ return result
898
+
899
+ @options(alpha=1, fill=True, thickness=1, color='lightgray',
900
+ color_even='white',
901
+ zorder=2, linestyle='solid', show_pairing=True,
902
+ tesselation='Dedekind', ymax=1)
903
+ def fundamental_domain(self, **options):
904
+ r"""
905
+ Plot a fundamental domain of an arithmetic subgroup of
906
+ `\PSL_2(\ZZ)` corresponding to the Farey symbol.
907
+
908
+ OPTIONS:
909
+
910
+ - ``fill`` -- boolean (default: ``True``); fill the fundamental domain
911
+
912
+ - ``linestyle`` -- string (default: ``'solid'``); the style of the line,
913
+ which is one of 'dashed', 'dotted', 'solid', 'dashdot', or '--',
914
+ ':', '-', '-.', respectively
915
+
916
+ - ``color`` -- (default: ``'lightgray'``) fill color for odd part of
917
+ Dedekind tesselation
918
+
919
+ - ``show_pairing`` -- boolean (default: ``True``); flag for pairing
920
+
921
+ - ``tesselation`` -- (default: ``'Dedekind'``) the type of
922
+ hyperbolic tesselation which is one of
923
+ ``'coset'``, ``'Dedekind'`` or ``None`` respectively
924
+
925
+ - ``color_even`` -- fill color for even parts of Dedekind
926
+ tesselation (default: ``'white'``); ignored for other tesselations
927
+
928
+ - ``thickness`` -- float (default: `1`) the thickness of the line
929
+
930
+ - ``ymax`` -- float (default: `1`) maximal height
931
+
932
+ EXAMPLES:
933
+
934
+ For example, to plot the fundamental domain of `\Gamma_0(11)`
935
+ with pairings use the following command::
936
+
937
+ sage: FareySymbol(Gamma0(11)).fundamental_domain() # needs sage.plot sage.symbolic
938
+ Graphics object consisting of 54 graphics primitives
939
+
940
+ indicating that side 1 is paired with side 3 and side 2 is
941
+ paired with side 4, see also :meth:`.paired_sides`.
942
+
943
+ To plot the fundamental domain of `\Gamma(3)` without pairings
944
+ use the following command::
945
+
946
+ sage: FareySymbol(Gamma(3)).fundamental_domain(show_pairing=False) # needs sage.plot sage.symbolic
947
+ Graphics object consisting of 48 graphics primitives
948
+
949
+ Plot the fundamental domain of `\Gamma_0(23)` showing the left
950
+ coset representatives::
951
+
952
+ sage: FareySymbol(Gamma0(23)).fundamental_domain(tesselation='coset') # needs sage.plot sage.symbolic
953
+ Graphics object consisting of 58 graphics primitives
954
+
955
+ The same as above but with a custom linestyle::
956
+
957
+ sage: FareySymbol(Gamma0(23)).fundamental_domain(tesselation='coset', # needs sage.plot sage.symbolic
958
+ ....: linestyle=':',
959
+ ....: thickness='2')
960
+ Graphics object consisting of 58 graphics primitives
961
+ """
962
+ from sage.plot.graphics import Graphics
963
+ from sage.plot.colors import rainbow
964
+ from sage.plot.hyperbolic_arc import hyperbolic_arc
965
+ from sage.plot.hyperbolic_polygon import hyperbolic_triangle
966
+
967
+ I = CC(0, 1)
968
+ w = RR(3).sqrt()
969
+ L = 1000
970
+ g = Graphics()
971
+ # show coset
972
+ for x in self.coset_reps():
973
+ a, b, c, d = x[1, 1], -x[0, 1], -x[1, 0], x[0, 0]
974
+ A, B = CC(0, L), CC(0, L)
975
+ if d != 0:
976
+ A = b / d
977
+ if c != 0:
978
+ B = a / c
979
+ C = (a*c+b*d+(a*d+b*c)/2+I*w/2)/(c*c+c*d+d*d)
980
+ D = (a*c+b*d + CC(0, 1))/(c*c+d*d)
981
+ if options['tesselation'] == 'Dedekind':
982
+ g += hyperbolic_triangle(A, D, C,
983
+ alpha=options['alpha'],
984
+ color=options['color'],
985
+ fill=options['fill'],
986
+ linestyle=options['linestyle'],
987
+ thickness=options['thickness'])
988
+ g += hyperbolic_triangle(D, C, B,
989
+ alpha=options['alpha'],
990
+ color=options['color_even'],
991
+ fill=options['fill'],
992
+ linestyle=options['linestyle'],
993
+ thickness=options['thickness'])
994
+ g += hyperbolic_triangle(A, D, C, color='gray')
995
+ g += hyperbolic_triangle(D, C, B, color='gray')
996
+ elif options['tesselation'] == 'coset':
997
+ g += hyperbolic_triangle(A, B, C,
998
+ alpha=options['alpha'],
999
+ color=options['color'],
1000
+ fill=options['fill'],
1001
+ linestyle=options['linestyle'],
1002
+ thickness=options['thickness'])
1003
+ g += hyperbolic_triangle(A, B, C, color='gray',
1004
+ linestyle=options['linestyle'],
1005
+ thickness=options['thickness'])
1006
+ else:
1007
+ g += hyperbolic_triangle(A, B, C,
1008
+ alpha=options['alpha'],
1009
+ color=options['color'],
1010
+ fill=options['fill'],
1011
+ linestyle=options['linestyle'],
1012
+ thickness=options['thickness'])
1013
+ # show pairings
1014
+ p = self.pairings()
1015
+ x = self.fractions()
1016
+ if options['show_pairing']:
1017
+ rc = rainbow(max(p)-min(p)+1)
1018
+ if p[0] > 0:
1019
+ g += hyperbolic_arc(CC(0, L), x[0], color=rc[p[0]-min(p)],
1020
+ linestyle=options['linestyle'],
1021
+ thickness=options['thickness'])
1022
+ if p[-1] > 0:
1023
+ g += hyperbolic_arc(CC(0, L), x[-1], color=rc[p[-1]-min(p)],
1024
+ linestyle=options['linestyle'],
1025
+ thickness=options['thickness'])
1026
+ for i in range(len(x)-1):
1027
+ if p[i+1] > 0:
1028
+ g += hyperbolic_arc(x[i], x[i+1], color=rc[p[i+1]-min(p)],
1029
+ linestyle=options['linestyle'],
1030
+ thickness=options['thickness'])
1031
+ d = g.get_minmax_data()
1032
+ g.set_axes_range(d['xmin'], d['xmax'], 0, options['ymax'])
1033
+ g.set_aspect_ratio(1)
1034
+ return g
1035
+
1036
+
1037
+ # ----- conversions ---------------------------------
1038
+
1039
+ cdef public long convert_to_long(n) noexcept:
1040
+ cdef long m = n
1041
+ return m
1042
+
1043
+ cdef public object convert_to_Integer(mpz_class a):
1044
+ A = Integer()
1045
+ A.set_from_mpz(a.get_mpz_t())
1046
+ return A
1047
+
1048
+ cdef public object convert_to_rational(mpq_class r):
1049
+ a = Integer()
1050
+ a.set_from_mpz(r.get_num_mpz_t())
1051
+ b = Integer()
1052
+ b.set_from_mpz(r.get_den_mpz_t())
1053
+ return a/b
1054
+
1055
+ cdef public object convert_to_cusp(mpq_class r):
1056
+ a = Integer()
1057
+ a.set_from_mpz(r.get_num_mpz_t())
1058
+ b = Integer()
1059
+ b.set_from_mpz(r.get_den_mpz_t())
1060
+ return Cusp(a/b)
1061
+
1062
+ cdef public object convert_to_SL2Z(cpp_SL2Z M):
1063
+ a = convert_to_Integer(M.a())
1064
+ b = convert_to_Integer(M.b())
1065
+ c = convert_to_Integer(M.c())
1066
+ d = convert_to_Integer(M.d())
1067
+ return SL2Z([a, b, c, d])