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,3310 @@
1
+ # sage_setup: distribution = sagemath-schemes
2
+ # sage.doctest: needs sage.libs.pari
3
+ r"""
4
+ Dirichlet characters
5
+
6
+ A :class:`DirichletCharacter` is the extension of a homomorphism
7
+
8
+ .. MATH::
9
+
10
+ (\ZZ/N\ZZ)^* \to R^*,
11
+
12
+ for some ring `R`, to the map `\ZZ/N\ZZ \to R` obtained by sending
13
+ those `x\in\ZZ/N\ZZ` with `\gcd(N,x)>1` to `0`.
14
+
15
+ EXAMPLES::
16
+
17
+ sage: G = DirichletGroup(35)
18
+ sage: x = G.gens()
19
+ sage: e = x[0]*x[1]^2; e
20
+ Dirichlet character modulo 35 of conductor 35
21
+ mapping 22 |--> zeta12^3, 31 |--> zeta12^2 - 1
22
+ sage: e.order()
23
+ 12
24
+
25
+ This illustrates a canonical coercion::
26
+
27
+ sage: e = DirichletGroup(5, QQ).0
28
+ sage: f = DirichletGroup(5, CyclotomicField(4)).0
29
+ sage: e*f
30
+ Dirichlet character modulo 5 of conductor 5 mapping 2 |--> -zeta4
31
+
32
+ AUTHORS:
33
+
34
+ - William Stein (2005-09-02): Fixed bug in comparison of Dirichlet
35
+ characters. It was checking that their values were the same, but
36
+ not checking that they had the same level!
37
+
38
+ - William Stein (2006-01-07): added more examples
39
+
40
+ - William Stein (2006-05-21): added examples of everything; fix a
41
+ *lot* of tiny bugs and design problem that became clear when
42
+ creating examples.
43
+
44
+ - Craig Citro (2008-02-16): speed up __call__ method for
45
+ Dirichlet characters, miscellaneous fixes
46
+
47
+ - Julian Rueth (2014-03-06): use UniqueFactory to cache DirichletGroups
48
+ """
49
+
50
+ # ****************************************************************************
51
+ # Copyright (C) 2004-2006 William Stein <wstein@gmail.com>
52
+ # Copyright (C) 2014 Julian Rueth <julian.rueth@fsfe.org>
53
+ #
54
+ # This program is free software: you can redistribute it and/or modify
55
+ # it under the terms of the GNU General Public License as published by
56
+ # the Free Software Foundation, either version 2 of the License, or
57
+ # (at your option) any later version.
58
+ # https://www.gnu.org/licenses/
59
+ # ****************************************************************************
60
+
61
+ import sage.misc.prandom as random
62
+ import sage.modules.free_module_element as free_module_element
63
+ import sage.rings.abc
64
+
65
+ from sage.arith.functions import lcm
66
+ from sage.arith.misc import bernoulli, factorial, kronecker, factor, gcd, fundamental_discriminant, euler_phi, valuation
67
+ from sage.categories.map import Map
68
+ from sage.categories.objects import Objects
69
+ from sage.categories.rings import Rings
70
+ from sage.misc.cachefunc import cached_method
71
+ from sage.misc.fast_methods import WithEqualityById
72
+ from sage.misc.functional import round
73
+ from sage.misc.lazy_import import lazy_import
74
+ from sage.misc.misc_c import prod
75
+ from sage.modules.free_module import FreeModule
76
+ from sage.rings.finite_rings.integer_mod import Mod
77
+ from sage.rings.finite_rings.integer_mod_ring import IntegerModRing
78
+ from sage.rings.integer import Integer
79
+ from sage.rings.integer_ring import ZZ
80
+ from sage.rings.power_series_ring import PowerSeriesRing
81
+ from sage.rings.rational_field import QQ, RationalField
82
+ from sage.structure.element import MultiplicativeGroupElement
83
+ from sage.structure.factory import UniqueFactory
84
+ from sage.structure.gens_py import multiplicative_iterator
85
+ from sage.structure.parent import Parent
86
+ from sage.structure.richcmp import richcmp
87
+ from sage.structure.sequence import Sequence
88
+
89
+ lazy_import('sage.libs.pari', 'pari')
90
+ lazy_import('sage.rings.number_field.number_field', ['CyclotomicField', 'NumberField', 'NumberField_generic'])
91
+
92
+
93
+ def trivial_character(N, base_ring=QQ):
94
+ r"""
95
+ Return the trivial character of the given modulus, with values in the given
96
+ base ring.
97
+
98
+ EXAMPLES::
99
+
100
+ sage: t = trivial_character(7)
101
+ sage: [t(x) for x in [0..20]]
102
+ [0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1]
103
+ sage: t(1).parent()
104
+ Rational Field
105
+ sage: trivial_character(7, Integers(3))(1).parent()
106
+ Ring of integers modulo 3
107
+ """
108
+ return DirichletGroup(N, base_ring)(1)
109
+
110
+
111
+ TrivialCharacter = trivial_character
112
+
113
+
114
+ def kronecker_character(d):
115
+ """
116
+ Return the quadratic Dirichlet character (d/.) of minimal
117
+ conductor.
118
+
119
+ EXAMPLES::
120
+
121
+ sage: kronecker_character(97*389*997^2)
122
+ Dirichlet character modulo 37733 of conductor 37733
123
+ mapping 1557 |--> -1, 37346 |--> -1
124
+
125
+ ::
126
+
127
+ sage: a = kronecker_character(1)
128
+ sage: b = DirichletGroup(2401,QQ)(a) # NOTE -- over QQ!
129
+ sage: b.modulus()
130
+ 2401
131
+
132
+ AUTHORS:
133
+
134
+ - Jon Hanke (2006-08-06)
135
+ """
136
+ d = Integer(d)
137
+ if d == 0:
138
+ raise ValueError("d must be nonzero")
139
+
140
+ D = fundamental_discriminant(d)
141
+ G = DirichletGroup(abs(D), QQ)
142
+ return G([kronecker(D, u) for u in G.unit_gens()])
143
+
144
+
145
+ def kronecker_character_upside_down(d):
146
+ """
147
+ Return the quadratic Dirichlet character (./d) of conductor d, for
148
+ d > 0.
149
+
150
+ EXAMPLES::
151
+
152
+ sage: kronecker_character_upside_down(97*389*997^2)
153
+ Dirichlet character modulo 37506941597 of conductor 37733
154
+ mapping 13533432536 |--> -1, 22369178537 |--> -1, 14266017175 |--> 1
155
+
156
+ AUTHORS:
157
+
158
+ - Jon Hanke (2006-08-06)
159
+ """
160
+ d = Integer(d)
161
+ if d <= 0:
162
+ raise ValueError("d must be positive")
163
+
164
+ G = DirichletGroup(d, QQ)
165
+ return G([kronecker(u.lift(), d) for u in G.unit_gens()])
166
+
167
+
168
+ def is_DirichletCharacter(x) -> bool:
169
+ r"""
170
+ Return ``True`` if ``x`` is of type ``DirichletCharacter``.
171
+
172
+ EXAMPLES::
173
+
174
+ sage: from sage.modular.dirichlet import is_DirichletCharacter
175
+ sage: is_DirichletCharacter(trivial_character(3))
176
+ doctest:warning...
177
+ DeprecationWarning: The function is_DirichletCharacter is deprecated;
178
+ use 'isinstance(..., DirichletCharacter)' instead.
179
+ See https://github.com/sagemath/sage/issues/38184 for details.
180
+ True
181
+ sage: is_DirichletCharacter([1])
182
+ False
183
+ """
184
+ from sage.misc.superseded import deprecation
185
+ deprecation(38184,
186
+ "The function is_DirichletCharacter is deprecated; "
187
+ "use 'isinstance(..., DirichletCharacter)' instead.")
188
+ return isinstance(x, DirichletCharacter)
189
+
190
+
191
+ class DirichletCharacter(MultiplicativeGroupElement):
192
+ """
193
+ A Dirichlet character.
194
+ """
195
+ def __init__(self, parent, x, check=True) -> None:
196
+ r"""
197
+ Create a Dirichlet character with specified values on
198
+ generators of `(\ZZ/n\ZZ)^*`.
199
+
200
+ INPUT:
201
+
202
+ - ``parent`` -- :class:`DirichletGroup`, a group of Dirichlet
203
+ characters
204
+
205
+ - ``x`` -- one of the following:
206
+
207
+ - tuple or list of ring elements: the values of the
208
+ Dirichlet character on the standard generators of
209
+ `(\ZZ/N\ZZ)^*` as returned by
210
+ :meth:`sage.rings.finite_rings.integer_mod_ring.IntegerModRing_generic.unit_gens`.
211
+
212
+ - vector over `\ZZ/e\ZZ`, where `e` is the order of the
213
+ standard root of unity for ``parent``.
214
+
215
+ In both cases, the orders of the elements must divide the
216
+ orders of the respective generators of `(\ZZ/N\ZZ)^*`.
217
+
218
+ OUTPUT:
219
+
220
+ The Dirichlet character defined by `x` (type
221
+ :class:`DirichletCharacter`).
222
+
223
+ EXAMPLES::
224
+
225
+ sage: G.<e> = DirichletGroup(13)
226
+ sage: G
227
+ Group of Dirichlet characters modulo 13 with values
228
+ in Cyclotomic Field of order 12 and degree 4
229
+ sage: e
230
+ Dirichlet character modulo 13 of conductor 13 mapping 2 |--> zeta12
231
+ sage: loads(e.dumps()) == e
232
+ True
233
+
234
+ ::
235
+
236
+ sage: G, x = DirichletGroup(35).objgens()
237
+ sage: e = x[0]*x[1]; e
238
+ Dirichlet character modulo 35 of conductor 35
239
+ mapping 22 |--> zeta12^3, 31 |--> zeta12^2
240
+ sage: e.order()
241
+ 12
242
+ sage: loads(e.dumps()) == e
243
+ True
244
+
245
+ TESTS::
246
+
247
+ sage: G = DirichletGroup(10)
248
+ sage: TestSuite(G[1]).run()
249
+
250
+ It is checked that the orders of the elements in `x` are
251
+ admissible (see :issue:`17283`)::
252
+
253
+ sage: k.<i> = CyclotomicField(4)
254
+ sage: G = DirichletGroup(192)
255
+ sage: G([i, -1, -1])
256
+ Traceback (most recent call last):
257
+ ...
258
+ ValueError: values (= (zeta16^4, -1, -1)) must have
259
+ multiplicative orders dividing (2, 16, 2), respectively
260
+
261
+ sage: from sage.modular.dirichlet import DirichletCharacter
262
+ sage: M = FreeModule(Zmod(16), 3)
263
+ sage: DirichletCharacter(G, M([4, 8, 8]))
264
+ Traceback (most recent call last):
265
+ ...
266
+ ValueError: values (= (4, 8, 8) modulo 16) must have
267
+ additive orders dividing (2, 16, 2), respectively
268
+ """
269
+ MultiplicativeGroupElement.__init__(self, parent)
270
+ if check:
271
+ orders = parent.integers_mod().unit_group().gens_orders()
272
+ if len(x) != len(orders):
273
+ raise ValueError("wrong number of values (= {}) on generators (want {})".format(x, len(orders)))
274
+ if isinstance(x, free_module_element.FreeModuleElement):
275
+ x = parent._module(x)
276
+ if any(u * v for u, v in zip(x, orders)):
277
+ raise ValueError("values (= {} modulo {}) must have additive orders dividing {}, respectively"
278
+ .format(x, parent.zeta_order(), orders))
279
+ self.element.set_cache(x)
280
+ else:
281
+ R = parent.base_ring()
282
+ x = tuple(map(R, x))
283
+ if R.is_exact() and any(u**v != 1 for u, v in zip(x, orders)):
284
+ raise ValueError("values (= {}) must have multiplicative orders dividing {}, respectively"
285
+ .format(x, orders))
286
+ self.values_on_gens.set_cache(x)
287
+ else:
288
+ if isinstance(x, free_module_element.FreeModuleElement):
289
+ self.element.set_cache(x)
290
+ else:
291
+ self.values_on_gens.set_cache(x)
292
+
293
+ @cached_method
294
+ def __eval_at_minus_one(self):
295
+ r"""
296
+ Efficiently evaluate the character at -1 using knowledge of its
297
+ order. This is potentially much more efficient than computing the
298
+ value of -1 directly using dlog and a large power of the image root
299
+ of unity.
300
+
301
+ We use the following. Proposition: Suppose eps is a character mod
302
+ `p^n`, where `p` is a prime. Then
303
+ `\varepsilon(-1) = -1` if and only if `p = 2` and
304
+ the factor of eps at 4 is nontrivial or `p > 2` and 2 does
305
+ not divide `\phi(p^n)/\mbox{\rm ord}(\varepsilon)`.
306
+
307
+ EXAMPLES::
308
+
309
+ sage: chi = DirichletGroup(20).0; chi._DirichletCharacter__eval_at_minus_one()
310
+ -1
311
+ """
312
+ D = self.decomposition()
313
+ val = self.base_ring()(1)
314
+ for e in D:
315
+ if e.modulus() % 2 == 0:
316
+ if e.modulus() % 4 == 0:
317
+ val *= e.values_on_gens()[0] # first gen is -1 for 2-power modulus
318
+ elif (euler_phi(e.parent().modulus()) / e.order()) % 2:
319
+ val *= -1
320
+ return val
321
+
322
+ def __call__(self, m):
323
+ """
324
+ Return the value of this character at the integer `m`.
325
+
326
+ .. warning::
327
+
328
+ A table of values of the character is made the first time
329
+ you call this (unless `m` equals -1)
330
+
331
+ EXAMPLES::
332
+
333
+ sage: G = DirichletGroup(60)
334
+ sage: e = prod(G.gens(), G(1))
335
+ sage: e
336
+ Dirichlet character modulo 60 of conductor 60 mapping 31 |--> -1, 41 |--> -1, 37 |--> zeta4
337
+ sage: e(-1)
338
+ -1
339
+ sage: e(2)
340
+ 0
341
+ sage: e(7)
342
+ -zeta4
343
+ sage: Integers(60).unit_gens()
344
+ (31, 41, 37)
345
+ sage: e(31)
346
+ -1
347
+ sage: e(41)
348
+ -1
349
+ sage: e(37)
350
+ zeta4
351
+ sage: e(31*37)
352
+ -zeta4
353
+ sage: parent(e(31*37))
354
+ Cyclotomic Field of order 4 and degree 2
355
+ """
356
+ N = self.modulus()
357
+ m = m % N
358
+ if self.values.is_in_cache() or m != N - 1:
359
+ return self.values()[m]
360
+ else:
361
+ return self.__eval_at_minus_one()
362
+
363
+ def change_ring(self, R):
364
+ """
365
+ Return the base extension of ``self`` to ``R``.
366
+
367
+ INPUT:
368
+
369
+ - ``R`` -- either a ring admitting a conversion map from the
370
+ base ring of ``self``, or a ring homomorphism with the base
371
+ ring of ``self`` as its domain
372
+
373
+ EXAMPLES::
374
+
375
+ sage: e = DirichletGroup(7, QQ).0
376
+ sage: f = e.change_ring(QuadraticField(3, 'a'))
377
+ sage: f.parent()
378
+ Group of Dirichlet characters modulo 7 with values in Number Field in a
379
+ with defining polynomial x^2 - 3 with a = 1.732050807568878?
380
+
381
+ ::
382
+
383
+ sage: e = DirichletGroup(13).0
384
+ sage: e.change_ring(QQ)
385
+ Traceback (most recent call last):
386
+ ...
387
+ TypeError: Unable to coerce zeta12 to a rational
388
+
389
+ We test the case where `R` is a map (:issue:`18072`)::
390
+
391
+ sage: K.<i> = QuadraticField(-1)
392
+ sage: chi = DirichletGroup(5, K)[1]
393
+ sage: chi(2)
394
+ i
395
+ sage: f = K.complex_embeddings()[0]
396
+ sage: psi = chi.change_ring(f)
397
+ sage: psi(2)
398
+ -1.83697019872103e-16 - 1.00000000000000*I
399
+ """
400
+ if self.base_ring() is R:
401
+ return self
402
+ G = self.parent().change_ring(R)
403
+ return G.element_class(G, [R(x) for x in self.values_on_gens()])
404
+
405
+ def _richcmp_(self, other, op) -> bool:
406
+ """
407
+ Compare ``self`` to ``other``.
408
+
409
+ .. NOTE::
410
+
411
+ Since there is no coercion between Dirichlet groups
412
+ of different moduli, characters of different moduli
413
+ compare as unequal, even if they define identical
414
+ functions on ``ZZ``.
415
+
416
+ EXAMPLES::
417
+
418
+ sage: # needs sage.rings.number_field
419
+ sage: e = DirichletGroup(16)([-1, 1])
420
+ sage: f = e.restrict(8)
421
+ sage: e == e
422
+ True
423
+ sage: f == f
424
+ True
425
+ sage: e == f
426
+ False
427
+ sage: k = DirichletGroup(7)([-1])
428
+ sage: k == e
429
+ False
430
+ """
431
+ return richcmp(self.values_on_gens(), other.values_on_gens(), op)
432
+
433
+ def __hash__(self) -> int:
434
+ """
435
+ Return the hash of ``self``.
436
+
437
+ EXAMPLES::
438
+
439
+ sage: # needs sage.rings.number_field
440
+ sage: e = DirichletGroup(16)([-1, 1])
441
+ sage: hash(e) == hash((-1,1))
442
+ True
443
+ """
444
+ return hash(self.values_on_gens())
445
+
446
+ def __invert__(self):
447
+ """
448
+ Return the multiplicative inverse of ``self``.
449
+
450
+ EXAMPLES::
451
+
452
+ sage: e = DirichletGroup(13).0
453
+ sage: f = ~e
454
+ sage: f*e
455
+ Dirichlet character modulo 13 of conductor 1 mapping 2 |--> 1
456
+ """
457
+ G = self.parent()
458
+ if G.zeta.is_in_cache():
459
+ x = -self.element()
460
+ else:
461
+ x = tuple(~z for z in self.values_on_gens())
462
+ return G.element_class(G, x, check=False)
463
+
464
+ def _mul_(self, other):
465
+ """
466
+ Return the product of ``self`` and ``other``.
467
+
468
+ EXAMPLES::
469
+
470
+ sage: G.<a,b> = DirichletGroup(20)
471
+ sage: a
472
+ Dirichlet character modulo 20 of conductor 4 mapping 11 |--> -1, 17 |--> 1
473
+ sage: b
474
+ Dirichlet character modulo 20 of conductor 5 mapping 11 |--> 1, 17 |--> zeta4
475
+ sage: a*b # indirect doctest
476
+ Dirichlet character modulo 20 of conductor 20 mapping 11 |--> -1, 17 |--> zeta4
477
+
478
+ Multiplying elements whose parents have different zeta orders works::
479
+
480
+ sage: a = DirichletGroup(3, QQ, zeta=1, zeta_order=1)(1)
481
+ sage: b = DirichletGroup(3, QQ, zeta=-1, zeta_order=2)([-1])
482
+ sage: a * b # indirect doctest
483
+ Dirichlet character modulo 3 of conductor 3 mapping 2 |--> -1
484
+ """
485
+ G = self.parent()
486
+ if G.zeta.is_in_cache():
487
+ x = self.element() + other.element()
488
+ else:
489
+ x = tuple(y * z for y, z in zip(self.values_on_gens(), other.values_on_gens()))
490
+ return G.element_class(G, x, check=False)
491
+
492
+ def __copy__(self):
493
+ """
494
+ Return a (shallow) copy of this Dirichlet character.
495
+
496
+ EXAMPLES::
497
+
498
+ sage: G.<a> = DirichletGroup(11)
499
+ sage: b = copy(a)
500
+ sage: a is b
501
+ False
502
+ sage: a.element() is b.element()
503
+ False
504
+ sage: a.values_on_gens() is b.values_on_gens()
505
+ True
506
+ """
507
+ # This method exists solely because of a bug in the cPickle module --
508
+ # see modsym/manin_symbols.py.
509
+ G = self.parent()
510
+ return G.element_class(G, self.values_on_gens(), check=False)
511
+
512
+ def __pow__(self, n):
513
+ """
514
+ Return ``self`` raised to the power of ``n``.
515
+
516
+ EXAMPLES::
517
+
518
+ sage: G.<a,b> = DirichletGroup(20)
519
+ sage: a^2
520
+ Dirichlet character modulo 20 of conductor 1 mapping 11 |--> 1, 17 |--> 1
521
+ sage: b^2
522
+ Dirichlet character modulo 20 of conductor 5 mapping 11 |--> 1, 17 |--> -1
523
+ """
524
+ G = self.parent()
525
+ if G.zeta.is_in_cache():
526
+ x = n * self.element()
527
+ else:
528
+ x = tuple(z**n for z in self.values_on_gens())
529
+ return G.element_class(G, x, check=False)
530
+
531
+ def _repr_short_(self) -> str:
532
+ r"""
533
+ A short string representation of ``self``, often used in string representations of modular forms.
534
+
535
+ EXAMPLES::
536
+
537
+ sage: chi = DirichletGroup(24).0
538
+ sage: chi._repr_short_()
539
+ '[-1, 1, 1]'
540
+ """
541
+ return str(list(self.values_on_gens()))
542
+
543
+ def _repr_(self) -> str:
544
+ """
545
+ String representation of ``self``.
546
+
547
+ EXAMPLES::
548
+
549
+ sage: G.<a,b> = DirichletGroup(20)
550
+ sage: repr(a) # indirect doctest
551
+ 'Dirichlet character modulo 20 of conductor 4 mapping 11 |--> -1, 17 |--> 1'
552
+
553
+ TESTS:
554
+
555
+ Dirichlet characters modulo 1 and 2 are printed correctly (see
556
+ :issue:`17338`)::
557
+
558
+ sage: DirichletGroup(1)[0]
559
+ Dirichlet character modulo 1 of conductor 1
560
+ sage: DirichletGroup(2)[0]
561
+ Dirichlet character modulo 2 of conductor 1
562
+ """
563
+ s = 'Dirichlet character modulo %s of conductor %s' % (self.modulus(), self.conductor())
564
+ r = len(self.values_on_gens())
565
+ if r:
566
+ s += ' mapping '
567
+ for i in range(r):
568
+ if i:
569
+ s += ', '
570
+ s += str(self.parent().unit_gens()[i]) + ' |--> ' + str(self.values_on_gens()[i])
571
+ return s
572
+
573
+ def _latex_(self) -> str:
574
+ r"""
575
+ LaTeX representation of ``self``.
576
+
577
+ EXAMPLES::
578
+
579
+ sage: # needs sage.rings.number_field
580
+ sage: G.<a,b> = DirichletGroup(16)
581
+ sage: latex(b) # indirect doctest
582
+ \hbox{Dirichlet character modulo } 16 \hbox{ of conductor } 16 \hbox{ mapping } 15 \mapsto 1,\ 5 \mapsto \zeta_{4}
583
+
584
+ TESTS:
585
+
586
+ Dirichlet characters modulo 1 and 2 are printed correctly (see
587
+ :issue:`17338`)::
588
+
589
+ sage: latex(DirichletGroup(1)[0])
590
+ \hbox{Dirichlet character modulo } 1 \hbox{ of conductor } 1
591
+ sage: latex(DirichletGroup(2)[0])
592
+ \hbox{Dirichlet character modulo } 2 \hbox{ of conductor } 1
593
+ """
594
+ s = r'\hbox{Dirichlet character modulo } %s \hbox{ of conductor } %s' % (self.modulus(), self.conductor())
595
+ r = len(self.values_on_gens())
596
+ if r != 0:
597
+ s += r' \hbox{ mapping } '
598
+ for i in range(r):
599
+ if i != 0:
600
+ s += r',\ '
601
+ s += self.parent().unit_gens()[i]._latex_() + r' \mapsto ' + self.values_on_gens()[i]._latex_()
602
+ return s
603
+
604
+ def base_ring(self):
605
+ """
606
+ Return the base ring of this Dirichlet character.
607
+
608
+ EXAMPLES::
609
+
610
+ sage: G = DirichletGroup(11)
611
+ sage: G.gen(0).base_ring()
612
+ Cyclotomic Field of order 10 and degree 4
613
+ sage: G = DirichletGroup(11, RationalField())
614
+ sage: G.gen(0).base_ring()
615
+ Rational Field
616
+ """
617
+ return self.parent().base_ring()
618
+
619
+ def bar(self):
620
+ """
621
+ Return the complex conjugate of this Dirichlet character.
622
+
623
+ EXAMPLES::
624
+
625
+ sage: e = DirichletGroup(5).0
626
+ sage: e
627
+ Dirichlet character modulo 5 of conductor 5 mapping 2 |--> zeta4
628
+ sage: e.bar()
629
+ Dirichlet character modulo 5 of conductor 5 mapping 2 |--> -zeta4
630
+ """
631
+ return ~self
632
+
633
+ def bernoulli(self, k, algorithm='recurrence', cache=True, **opts):
634
+ r"""
635
+ Return the generalized Bernoulli number `B_{k,eps}`.
636
+
637
+ INPUT:
638
+
639
+ - ``k`` -- nonnegative integer
640
+
641
+ - ``algorithm`` -- either ``'recurrence'`` (default) or
642
+ ``'definition'``
643
+
644
+ - ``cache`` -- if ``True``, cache answers
645
+
646
+ - ``**opts`` -- optional arguments; not used directly, but
647
+ passed to the :func:`bernoulli` function if this is called
648
+
649
+ OUTPUT:
650
+
651
+ Let `\varepsilon` be a (not necessarily primitive) character
652
+ of modulus `N`. This function returns the generalized
653
+ Bernoulli number `B_{k,\varepsilon}`, as defined by the
654
+ following identity of power series (see for example
655
+ [DI1995]_, Section 2.2):
656
+
657
+ .. MATH::
658
+
659
+ \sum_{a=1}^N \frac{\varepsilon(a) t e^{at}}{e^{Nt}-1}
660
+ = \sum_{k=0}^{\infty} \frac{B_{k,\varepsilon}}{k!} t^k.
661
+
662
+ ALGORITHM:
663
+
664
+ The ``'recurrence'`` algorithm computes generalized Bernoulli
665
+ numbers via classical Bernoulli numbers using the formula in
666
+ [Coh2007]_, Proposition 9.4.5; this is usually optimal. The
667
+ ``definition`` algorithm uses the definition directly.
668
+
669
+ .. WARNING::
670
+
671
+ In the case of the trivial Dirichlet character modulo 1,
672
+ this function returns `B_{1,\varepsilon} = 1/2`, in
673
+ accordance with the above definition, but in contrast to
674
+ the value `B_1 = -1/2` for the classical Bernoulli number.
675
+ Some authors use an alternative definition giving
676
+ `B_{1,\varepsilon} = -1/2`; see the discussion in
677
+ [Coh2007]_, Section 9.4.1.
678
+
679
+ EXAMPLES::
680
+
681
+ sage: G = DirichletGroup(13)
682
+ sage: e = G.0
683
+ sage: e.bernoulli(5)
684
+ 7430/13*zeta12^3 - 34750/13*zeta12^2 - 11380/13*zeta12 + 9110/13
685
+ sage: eps = DirichletGroup(9).0
686
+ sage: eps.bernoulli(3)
687
+ 10*zeta6 + 4
688
+ sage: eps.bernoulli(3, algorithm='definition')
689
+ 10*zeta6 + 4
690
+
691
+ TESTS:
692
+
693
+ Check that :issue:`17586` is fixed::
694
+
695
+ sage: DirichletGroup(1)[0].bernoulli(1)
696
+ 1/2
697
+ """
698
+ if cache:
699
+ try:
700
+ self.__bernoulli
701
+ except AttributeError:
702
+ self.__bernoulli = {}
703
+ if k in self.__bernoulli:
704
+ return self.__bernoulli[k]
705
+ N = self.modulus()
706
+ K = self.base_ring()
707
+
708
+ if N == 1:
709
+ # By definition, the first Bernoulli number of the trivial
710
+ # character is 1/2, in contrast to the value B_1 = -1/2.
711
+ ber = K.one() / 2 if k == 1 else K(bernoulli(k))
712
+ elif self(-1) != K((-1)**k):
713
+ ber = K.zero()
714
+ elif algorithm == "recurrence":
715
+ # The following code is pretty fast, at least compared to
716
+ # the other algorithm below. That said, I'm sure it could
717
+ # be sped up by a factor of 10 or more in many cases,
718
+ # especially since we end up computing all the Bernoulli
719
+ # numbers up to k, which should be done with power series
720
+ # instead of calls to the Bernoulli function. Likewise
721
+ # computing all binomial coefficients can be done much
722
+ # more efficiently.
723
+ v = self.values()
724
+
725
+ def S(n):
726
+ return sum(v[r] * r**n for r in range(1, N))
727
+
728
+ ber = sum(ZZ(k).binomial(j) * bernoulli(j, **opts) *
729
+ N**(j - 1) * S(k - j) for j in range(k + 1))
730
+ elif algorithm == "definition":
731
+ # This is better since it computes the same thing, but requires
732
+ # no arith in a poly ring over a number field.
733
+ prec = k + 2
734
+ R = PowerSeriesRing(QQ, 't')
735
+ t = R.gen()
736
+ # g(t) = t/(e^{Nt}-1)
737
+ g = t / ((N * t).exp(prec) - 1)
738
+ # h(n) = g(t)*e^{nt}
739
+ h = [0] + [g * ((n * t).exp(prec)) for n in range(1, N + 1)]
740
+ ber = sum([self(a) * h[a][k] for a in range(1, N + 1)]) * factorial(k)
741
+ else:
742
+ raise ValueError(f"algorithm = '{algorithm}' unknown")
743
+
744
+ if cache:
745
+ self.__bernoulli[k] = ber
746
+ return ber
747
+
748
+ def lfunction(self, prec=53, algorithm='pari'):
749
+ """
750
+ Return the `L`-function of ``self``.
751
+
752
+ The result is a wrapper around a PARI `L`-function or around
753
+ the ``lcalc`` program.
754
+
755
+ INPUT:
756
+
757
+ - ``prec`` -- precision (default: 53)
758
+
759
+ - ``algorithm`` -- 'pari' (default) or 'lcalc'
760
+
761
+ EXAMPLES::
762
+
763
+ sage: G.<a,b> = DirichletGroup(20)
764
+ sage: L = a.lfunction(); L
765
+ PARI L-function associated to Dirichlet character modulo 20
766
+ of conductor 4 mapping 11 |--> -1, 17 |--> 1
767
+ sage: L(4)
768
+ 0.988944551741105
769
+
770
+ With the algorithm "lcalc"::
771
+
772
+ sage: a = a.primitive_character()
773
+ sage: L = a.lfunction(algorithm='lcalc'); L # needs lcalc
774
+ L-function with complex Dirichlet coefficients
775
+ sage: L.value(4) # abs tol 1e-8 # needs lcalc
776
+ 0.988944551741105 + 0.0*I
777
+ """
778
+ if algorithm is None:
779
+ algorithm = 'pari'
780
+
781
+ if algorithm == 'pari':
782
+ from sage.lfunctions.pari import lfun_character, LFunction
783
+ Z = LFunction(lfun_character(self), prec=prec)
784
+ Z.rename('PARI L-function associated to %s' % self)
785
+ return Z
786
+ elif algorithm == 'lcalc':
787
+ from sage.libs.lcalc.lcalc_Lfunction import Lfunction_from_character
788
+ return Lfunction_from_character(self)
789
+
790
+ raise ValueError('algorithm must be "pari" or "lcalc"')
791
+
792
+ @cached_method
793
+ def conductor(self):
794
+ """
795
+ Compute and return the conductor of this character.
796
+
797
+ EXAMPLES::
798
+
799
+ sage: G.<a,b> = DirichletGroup(20)
800
+ sage: a.conductor()
801
+ 4
802
+ sage: b.conductor()
803
+ 5
804
+ sage: (a*b).conductor()
805
+ 20
806
+
807
+ TESTS::
808
+
809
+ sage: G.<a, b> = DirichletGroup(20)
810
+ sage: type(G(1).conductor())
811
+ <class 'sage.rings.integer.Integer'>
812
+ """
813
+ if self.modulus() == 1 or self.is_trivial():
814
+ return Integer(1)
815
+ F = factor(self.modulus())
816
+ if len(F) > 1:
817
+ return prod([d.conductor() for d in self.decomposition()])
818
+ p = F[0][0]
819
+ # When p is odd, and x =/= 1, the conductor is the smallest p**r such that
820
+ # Order(x) divides EulerPhi(p**r) = p**(r-1)*(p-1).
821
+ # For a given r, whether or not the above divisibility holds
822
+ # depends only on the factor of p**(r-1) on the right hand side.
823
+ # Since p-1 is coprime to p, this smallest r such that the
824
+ # divisibility holds equals Valuation(Order(x),p)+1.
825
+ cond = p**(valuation(self.order(), p) + 1)
826
+ if p == 2 and F[0][1] > 2 and self.values_on_gens()[1].multiplicative_order() != 1:
827
+ cond *= 2
828
+ return Integer(cond)
829
+
830
+ @cached_method
831
+ def fixed_field_polynomial(self, algorithm='pari'):
832
+ r"""
833
+ Given a Dirichlet character, this will return a
834
+ polynomial generating the abelian extension fixed by the kernel
835
+ of the corresponding Galois character.
836
+
837
+ ALGORITHM: (Sage)
838
+
839
+ A formula by Gauss for the products of periods;
840
+ see Disquisitiones §343. See the source code for more.
841
+
842
+ OUTPUT: a polynomial with integer coefficients
843
+
844
+ EXAMPLES::
845
+
846
+ sage: G = DirichletGroup(37)
847
+ sage: chi = G.0
848
+ sage: psi = chi^18
849
+ sage: psi.fixed_field_polynomial()
850
+ x^2 + x - 9
851
+
852
+ sage: G = DirichletGroup(7)
853
+ sage: chi = G.0^2
854
+ sage: chi
855
+ Dirichlet character modulo 7 of conductor 7 mapping 3 |--> zeta6 - 1
856
+ sage: chi.fixed_field_polynomial()
857
+ x^3 + x^2 - 2*x - 1
858
+
859
+ sage: G = DirichletGroup(31)
860
+ sage: chi = G.0
861
+ sage: chi^6
862
+ Dirichlet character modulo 31 of conductor 31 mapping 3 |--> zeta30^6
863
+ sage: psi = chi^6
864
+ sage: psi.fixed_field_polynomial()
865
+ x^5 + x^4 - 12*x^3 - 21*x^2 + x + 5
866
+
867
+ sage: G = DirichletGroup(7)
868
+ sage: chi = G.0
869
+ sage: chi.fixed_field_polynomial()
870
+ x^6 + x^5 + x^4 + x^3 + x^2 + x + 1
871
+
872
+ sage: G = DirichletGroup(1001)
873
+ sage: chi = G.0
874
+ sage: psi = chi^3
875
+ sage: psi.order()
876
+ 2
877
+ sage: psi.fixed_field_polynomial(algorithm='pari')
878
+ x^2 + x + 2
879
+
880
+ With the Sage implementation::
881
+
882
+ sage: G = DirichletGroup(37)
883
+ sage: chi = G.0
884
+ sage: psi = chi^18
885
+ sage: psi.fixed_field_polynomial(algorithm='sage')
886
+ x^2 + x - 9
887
+
888
+ sage: G = DirichletGroup(7)
889
+ sage: chi = G.0^2
890
+ sage: chi
891
+ Dirichlet character modulo 7 of conductor 7 mapping 3 |--> zeta6 - 1
892
+ sage: chi.fixed_field_polynomial(algorithm='sage')
893
+ x^3 + x^2 - 2*x - 1
894
+
895
+ sage: G = DirichletGroup(31)
896
+ sage: chi = G.0
897
+ sage: chi^6
898
+ Dirichlet character modulo 31 of conductor 31 mapping 3 |--> zeta30^6
899
+ sage: psi = chi^6
900
+ sage: psi.fixed_field_polynomial(algorithm='sage')
901
+ x^5 + x^4 - 12*x^3 - 21*x^2 + x + 5
902
+
903
+ sage: G = DirichletGroup(7)
904
+ sage: chi = G.0
905
+ sage: chi.fixed_field_polynomial(algorithm='sage')
906
+ x^6 + x^5 + x^4 + x^3 + x^2 + x + 1
907
+
908
+ sage: G = DirichletGroup(1001)
909
+ sage: chi = G.0
910
+ sage: psi = chi^3
911
+ sage: psi.order()
912
+ 2
913
+ sage: psi.fixed_field_polynomial(algorithm='sage')
914
+ x^2 + x + 2
915
+
916
+ The algorithm must be one of `sage` or `pari`::
917
+
918
+ sage: G = DirichletGroup(1001)
919
+ sage: chi = G.0
920
+ sage: psi = chi^3
921
+ sage: psi.order()
922
+ 2
923
+ sage: psi.fixed_field_polynomial(algorithm='banana')
924
+ Traceback (most recent call last):
925
+ ...
926
+ NotImplementedError: algorithm must be one of 'pari' or 'sage'
927
+ """
928
+
929
+ # this algorithm was written by Francis Clarke see issue #9407
930
+
931
+ from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing
932
+ from sage.matrix.constructor import matrix
933
+
934
+ if algorithm == "sage":
935
+ n = ZZ(self.conductor())
936
+ if not n.is_prime():
937
+ raise NotImplementedError('the conductor %s is supposed to be prime' % n)
938
+
939
+ d = self.order()
940
+
941
+ # check that there will be such a field of degree d inside QQ(zeta_n)
942
+ if euler_phi(n) % d != 0:
943
+ raise ValueError('No field exists because %s does not divide %s=phi(%s)' % (d, euler_phi(n), n))
944
+ f = euler_phi(n) // d
945
+
946
+ S = PolynomialRing(ZZ, 'x')
947
+
948
+ if f == 1:
949
+ from sage.misc.functional import cyclotomic_polynomial
950
+ return cyclotomic_polynomial(n, S.gen())
951
+
952
+ if d == 2:
953
+ if n.mod(4) == 1:
954
+ s = -1
955
+ else:
956
+ s = 1
957
+ return S([s * (n + s) / 4, 1, 1])
958
+
959
+ # Using the notation of van der Waerden, where $\zeta$ is a primitive
960
+ # $n$-root of unity,
961
+ # $$
962
+ # \eta_i = \sum_{j=0}^{f-1}\zeta^{g^{i+dj}},
963
+ # $$
964
+ # is represented by eta[i] as the list of exponents.
965
+ #
966
+ # gen_index is a dictionary such that gen_index[r] = i if the exponent r
967
+ # occurs in eta[i]. Thus $\eta^{(r)} = \eta_i$ in van der Waerden's
968
+ # notation.
969
+
970
+ R = IntegerModRing(n)
971
+ g = R.unit_gens()[0]
972
+ gen_index = {}
973
+ eta = []
974
+ for i in range(d):
975
+ eta.append([])
976
+ for j in range(f):
977
+ r = g**(i + d * j)
978
+ eta[i].append(r)
979
+ gen_index[r] = i
980
+
981
+ # Using Gauss's formula
982
+ # $$
983
+ # \eta^{(r)}\eta^{(s)} = \sum_{j=0}^{f-1}\eta^{(r+sg^{dj})}
984
+ # $$
985
+ # (with $r=1$), we construct the matrix representing multiplication by
986
+ # $\eta_0=\eta^{(1)}$ with respect to the basis consisting of the $\eta_i$.
987
+ # Its characteristic polynomial generates the field. The element
988
+ # $\eta^(0)$=f=-f\sum_{i=0}^{d-1}\eta_i$ is represented by eta_zero.
989
+
990
+ V = FreeModule(ZZ, d)
991
+ eta_zero = V([-f] * d)
992
+ m = []
993
+ for j in range(d):
994
+ v = 0
995
+ for e in eta[j]:
996
+ try:
997
+ s = V.gen(gen_index[1 + e])
998
+ except KeyError:
999
+ s = eta_zero
1000
+ v += s
1001
+ m.append(v)
1002
+
1003
+ xx = S.gen()
1004
+ return matrix(m).charpoly(xx)
1005
+
1006
+ elif algorithm == "pari":
1007
+ # Use pari
1008
+ G, chi = self._pari_init_()
1009
+ K = pari.charker(G, chi)
1010
+ H = pari.galoissubcyclo(G, K)
1011
+ P = PolynomialRing(QQ, "x")
1012
+ x = P.gen()
1013
+ return H.sage({"x": x})
1014
+
1015
+ else:
1016
+ raise NotImplementedError("algorithm must be one of 'pari' or 'sage'")
1017
+
1018
+ def fixed_field(self):
1019
+ r"""
1020
+ Given a Dirichlet character, this will return the abelian extension
1021
+ fixed by the kernel of the corresponding Galois character.
1022
+
1023
+ OUTPUT: a number field
1024
+
1025
+ EXAMPLES::
1026
+
1027
+ sage: G = DirichletGroup(37)
1028
+ sage: chi = G.0
1029
+ sage: psi = chi^18
1030
+ sage: psi.fixed_field()
1031
+ Number Field in a with defining polynomial x^2 + x - 9
1032
+
1033
+
1034
+ sage: G = DirichletGroup(7)
1035
+ sage: chi = G.0^2
1036
+ sage: chi
1037
+ Dirichlet character modulo 7 of conductor 7 mapping 3 |--> zeta6 - 1
1038
+ sage: chi.fixed_field()
1039
+ Number Field in a with defining polynomial x^3 + x^2 - 2*x - 1
1040
+
1041
+ sage: G = DirichletGroup(31)
1042
+ sage: chi = G.0
1043
+ sage: chi^6
1044
+ Dirichlet character modulo 31 of conductor 31 mapping 3 |--> zeta30^6
1045
+ sage: psi = chi^6
1046
+ sage: psi.fixed_field()
1047
+ Number Field in a with defining polynomial x^5 + x^4 - 12*x^3 - 21*x^2 + x + 5
1048
+ """
1049
+ return NumberField(self.fixed_field_polynomial(), 'a')
1050
+
1051
+ @cached_method
1052
+ def decomposition(self) -> list:
1053
+ r"""
1054
+ Return the decomposition of ``self`` as a product of Dirichlet
1055
+ characters of prime power modulus, where the prime powers exactly
1056
+ divide the modulus of this character.
1057
+
1058
+ EXAMPLES::
1059
+
1060
+ sage: G.<a,b> = DirichletGroup(20)
1061
+ sage: c = a*b
1062
+ sage: d = c.decomposition(); d
1063
+ [Dirichlet character modulo 4 of conductor 4 mapping 3 |--> -1,
1064
+ Dirichlet character modulo 5 of conductor 5 mapping 2 |--> zeta4]
1065
+ sage: d[0].parent()
1066
+ Group of Dirichlet characters modulo 4 with values
1067
+ in Cyclotomic Field of order 4 and degree 2
1068
+ sage: d[1].parent()
1069
+ Group of Dirichlet characters modulo 5 with values
1070
+ in Cyclotomic Field of order 4 and degree 2
1071
+
1072
+ We cannot multiply directly, since coercion of one element into the
1073
+ other parent fails in both cases::
1074
+
1075
+ sage: d[0]*d[1] == c
1076
+ Traceback (most recent call last):
1077
+ ...
1078
+ TypeError: unsupported operand parent(s) for *: 'Group of Dirichlet
1079
+ characters modulo 4 with values in Cyclotomic Field of order 4 and
1080
+ degree 2' and 'Group of Dirichlet characters modulo 5 with values
1081
+ in Cyclotomic Field of order 4 and degree 2'
1082
+
1083
+ We can multiply if we are explicit about where we want the
1084
+ multiplication to take place.
1085
+
1086
+ ::
1087
+
1088
+ sage: G(d[0])*G(d[1]) == c
1089
+ True
1090
+
1091
+ Conductors that are divisible by various powers of 2 present
1092
+ some problems as the multiplicative group modulo `2^k` is
1093
+ trivial for `k = 1` and non-cyclic for `k \ge 3`::
1094
+
1095
+ sage: (DirichletGroup(18).0).decomposition()
1096
+ [Dirichlet character modulo 2 of conductor 1,
1097
+ Dirichlet character modulo 9 of conductor 9 mapping 2 |--> zeta6]
1098
+ sage: (DirichletGroup(36).0).decomposition()
1099
+ [Dirichlet character modulo 4 of conductor 4 mapping 3 |--> -1,
1100
+ Dirichlet character modulo 9 of conductor 1 mapping 2 |--> 1]
1101
+ sage: (DirichletGroup(72).0).decomposition()
1102
+ [Dirichlet character modulo 8 of conductor 4 mapping 7 |--> -1, 5 |--> 1,
1103
+ Dirichlet character modulo 9 of conductor 1 mapping 2 |--> 1]
1104
+ """
1105
+ D = self.parent().decomposition()
1106
+ vals = [[z] for z in self.values_on_gens()]
1107
+ if self.modulus() % 8 == 0: # 2 factors at 2.
1108
+ vals[0].append(vals[1][0])
1109
+ del vals[1]
1110
+ elif self.modulus() % 4 == 2: # 0 factors at 2.
1111
+ vals = [1] + vals
1112
+ return [D[i](vals[i]) for i in range(len(D))]
1113
+
1114
+ def extend(self, M):
1115
+ """
1116
+ Return the extension of this character to a Dirichlet character
1117
+ modulo the multiple ``M`` of the modulus.
1118
+
1119
+ EXAMPLES::
1120
+
1121
+ sage: G.<a,b> = DirichletGroup(20)
1122
+ sage: H.<c> = DirichletGroup(4)
1123
+ sage: c.extend(20)
1124
+ Dirichlet character modulo 20 of conductor 4 mapping 11 |--> -1, 17 |--> 1
1125
+ sage: a
1126
+ Dirichlet character modulo 20 of conductor 4 mapping 11 |--> -1, 17 |--> 1
1127
+ sage: c.extend(20) == a
1128
+ True
1129
+ """
1130
+ if M % self.modulus():
1131
+ raise ArithmeticError("M(=%s) must be a multiple of the modulus(=%s)" % (M, self.modulus()))
1132
+ H = DirichletGroup(M, self.base_ring())
1133
+ return H(self)
1134
+
1135
+ def _pari_init_(self):
1136
+ r"""
1137
+ Conversion of the character to Pari.
1138
+
1139
+ OUTPUT:
1140
+
1141
+ pair (G, v) where G is `(\ZZ / N \ZZ)^*` where `N` is the modulus
1142
+
1143
+ EXAMPLES::
1144
+
1145
+ sage: # needs sage.rings.number_field
1146
+ sage: chi4 = DirichletGroup(4).gen()
1147
+ sage: pari(chi4)
1148
+ [[[4, [0]], [2, [2], [3]], [[2]~, Vecsmall([2])],
1149
+ [[4], [[1, matrix(0,2)]], Mat(1), [3], [2], [0]], Mat(1)], [1]]
1150
+ sage: pari.charker(*pari(chi4)).sage()
1151
+ [2]
1152
+
1153
+ sage: chi = DirichletGroup(24)([1,-1,-1]); chi
1154
+ Dirichlet character modulo 24 of conductor 24
1155
+ mapping 7 |--> 1, 13 |--> -1, 17 |--> -1
1156
+ sage: pari(chi)
1157
+ [[[24, [0]], [8, [2, 2, 2], [7, 13, 17]],
1158
+ [[2, 2, 3]~, Vecsmall([3, 3, 1])],
1159
+ [[8, 8, 3], [[1, matrix(0,2)], [1, matrix(0,2)], [2, Mat([2, 1])]],
1160
+ [1, 0, 0; 0, 1, 0; 0, 0, 1], [7, 13, 17], [2, 2, 2], [0, 0, 0]],
1161
+ [1, 0, 0; 0, 1, 0; 0, 0, 1]], [0, 1, 1]]
1162
+ sage: pari.charorder(*pari(chi))
1163
+ 2
1164
+ """
1165
+ G = pari.znstar(self.modulus(), 1)
1166
+
1167
+ pari_orders = G[1][1]
1168
+ pari_gens = G[1][2]
1169
+ # one should use the following, but this does not work
1170
+ # pari_orders = G.cyc()
1171
+ # pari_gens = G.gen()
1172
+
1173
+ values_on_gens = (self(x) for x in pari_gens)
1174
+
1175
+ # now compute the input for pari (list of exponents)
1176
+ P = self.parent()
1177
+ if isinstance(P.base_ring(), sage.rings.abc.ComplexField):
1178
+ zeta = P.zeta()
1179
+ zeta_argument = zeta.argument()
1180
+ v = [int(x.argument() / zeta_argument) for x in values_on_gens]
1181
+ else:
1182
+ dlog = P._zeta_dlog
1183
+ v = [dlog[x] for x in values_on_gens]
1184
+
1185
+ m = P.zeta_order()
1186
+ v = [(vi * oi) // m for vi, oi in zip(v, pari_orders)]
1187
+ return (G, v)
1188
+
1189
+ def conrey_number(self):
1190
+ r"""
1191
+ Return the Conrey number for this character.
1192
+
1193
+ This is a positive integer coprime to `q` that identifies a
1194
+ Dirichlet character of modulus `q`.
1195
+
1196
+ See https://www.lmfdb.org/knowledge/show/character.dirichlet.conrey
1197
+
1198
+ EXAMPLES::
1199
+
1200
+ sage: # needs sage.rings.number_field
1201
+ sage: chi4 = DirichletGroup(4).gen()
1202
+ sage: chi4.conrey_number()
1203
+ 3
1204
+ sage: chi = DirichletGroup(24)([1,-1,-1]); chi
1205
+ Dirichlet character modulo 24 of conductor 24
1206
+ mapping 7 |--> 1, 13 |--> -1, 17 |--> -1
1207
+ sage: chi.conrey_number()
1208
+ 5
1209
+
1210
+ sage: chi = DirichletGroup(60)([1,-1,I])
1211
+ sage: chi.conrey_number()
1212
+ 17
1213
+
1214
+ sage: chi = DirichletGroup(420)([1,-1,-I,1])
1215
+ sage: chi.conrey_number()
1216
+ 113
1217
+
1218
+ TESTS::
1219
+
1220
+ sage: eps1 = DirichletGroup(5)([-1])
1221
+ sage: eps2 = DirichletGroup(5,QQ)([-1])
1222
+ sage: eps1.conrey_number() == eps2.conrey_number()
1223
+ True
1224
+ sage: chi = DirichletGroup(1)[0]
1225
+ sage: chi.conrey_number()
1226
+ 1
1227
+ """
1228
+ if self.modulus() == 1:
1229
+ return 1
1230
+ G, v = self._pari_init_()
1231
+ return pari.znconreyexp(G, v).sage()
1232
+
1233
+ def lmfdb_page(self) -> None:
1234
+ r"""
1235
+ Open the LMFDB web page of the character in a browser.
1236
+
1237
+ See https://www.lmfdb.org
1238
+
1239
+ EXAMPLES::
1240
+
1241
+ sage: # needs sage.rings.number_field
1242
+ sage: E = DirichletGroup(4).gen()
1243
+ sage: E.lmfdb_page() # optional -- webbrowser
1244
+ """
1245
+ import webbrowser
1246
+ lmfdb_url = 'https://www.lmfdb.org/Character/Dirichlet/{}/{}'
1247
+ url = lmfdb_url.format(self.modulus(), self.conrey_number())
1248
+ webbrowser.open(url)
1249
+
1250
+ def galois_orbit(self, sort=True) -> list:
1251
+ r"""
1252
+ Return the orbit of this character under the action of the absolute
1253
+ Galois group of the prime subfield of the base ring.
1254
+
1255
+ EXAMPLES::
1256
+
1257
+ sage: G = DirichletGroup(30); e = G.1
1258
+ sage: e.galois_orbit()
1259
+ [Dirichlet character modulo 30 of conductor 5 mapping 11 |--> 1, 7 |--> -zeta4,
1260
+ Dirichlet character modulo 30 of conductor 5 mapping 11 |--> 1, 7 |--> zeta4]
1261
+
1262
+ Another example::
1263
+
1264
+ sage: G = DirichletGroup(13)
1265
+ sage: G.galois_orbits()
1266
+ [[Dirichlet character modulo 13 of conductor 1 mapping 2 |--> 1],
1267
+ ...,
1268
+ [Dirichlet character modulo 13 of conductor 13 mapping 2 |--> -1]]
1269
+ sage: e = G.0
1270
+ sage: e
1271
+ Dirichlet character modulo 13 of conductor 13 mapping 2 |--> zeta12
1272
+ sage: e.galois_orbit()
1273
+ [Dirichlet character modulo 13 of conductor 13 mapping 2 |--> zeta12,
1274
+ Dirichlet character modulo 13 of conductor 13 mapping 2 |--> -zeta12^3 + zeta12,
1275
+ Dirichlet character modulo 13 of conductor 13 mapping 2 |--> zeta12^3 - zeta12,
1276
+ Dirichlet character modulo 13 of conductor 13 mapping 2 |--> -zeta12]
1277
+ sage: e = G.0^2; e
1278
+ Dirichlet character modulo 13 of conductor 13 mapping 2 |--> zeta12^2
1279
+ sage: e.galois_orbit()
1280
+ [Dirichlet character modulo 13 of conductor 13 mapping 2 |--> zeta12^2,
1281
+ Dirichlet character modulo 13 of conductor 13 mapping 2 |--> -zeta12^2 + 1]
1282
+
1283
+ A non-example::
1284
+
1285
+ sage: chi = DirichletGroup(7, Integers(9), zeta = Integers(9)(2)).0
1286
+ sage: chi.galois_orbit()
1287
+ Traceback (most recent call last):
1288
+ ...
1289
+ TypeError: Galois orbits only defined if base ring is an integral domain
1290
+ """
1291
+ if not self.base_ring().is_integral_domain():
1292
+ raise TypeError("Galois orbits only defined if base ring is an integral domain")
1293
+ k = self.order()
1294
+ if k <= 2:
1295
+ return [self]
1296
+ P = self.parent()
1297
+ z = self.element()
1298
+ o = int(z.additive_order())
1299
+ Auts = {m % o for m in P._automorphisms()}
1300
+ v = [P.element_class(P, m * z, check=False) for m in Auts]
1301
+ if sort:
1302
+ v.sort()
1303
+ return v
1304
+
1305
+ def gauss_sum(self, a=1):
1306
+ r"""
1307
+ Return a Gauss sum associated to this Dirichlet character.
1308
+
1309
+ The Gauss sum associated to `\chi` is
1310
+
1311
+ .. MATH::
1312
+
1313
+ g_a(\chi) = \sum_{r \in \ZZ/m\ZZ} \chi(r)\,\zeta^{ar},
1314
+
1315
+ where `m` is the modulus of `\chi` and `\zeta` is a primitive
1316
+ `m`-th root of unity.
1317
+
1318
+ FACTS: If the modulus is a prime `p` and the character is
1319
+ nontrivial, then the Gauss sum has absolute value `\sqrt{p}`.
1320
+
1321
+ CACHING: Computed Gauss sums are *not* cached with this character.
1322
+
1323
+ EXAMPLES::
1324
+
1325
+ sage: G = DirichletGroup(3)
1326
+ sage: e = G([-1])
1327
+ sage: e.gauss_sum(1)
1328
+ 2*zeta6 - 1
1329
+ sage: e.gauss_sum(2)
1330
+ -2*zeta6 + 1
1331
+ sage: norm(e.gauss_sum())
1332
+ 3
1333
+
1334
+ ::
1335
+
1336
+ sage: G = DirichletGroup(13)
1337
+ sage: e = G.0
1338
+ sage: e.gauss_sum()
1339
+ -zeta156^46 + zeta156^45 + zeta156^42 + zeta156^41 + 2*zeta156^40
1340
+ + zeta156^37 - zeta156^36 - zeta156^34 - zeta156^33 - zeta156^31
1341
+ + 2*zeta156^30 + zeta156^28 - zeta156^24 - zeta156^22 + zeta156^21
1342
+ + zeta156^20 - zeta156^19 + zeta156^18 - zeta156^16 - zeta156^15
1343
+ - 2*zeta156^14 - zeta156^10 + zeta156^8 + zeta156^7 + zeta156^6
1344
+ + zeta156^5 - zeta156^4 - zeta156^2 - 1
1345
+ sage: factor(norm(e.gauss_sum()))
1346
+ 13^24
1347
+
1348
+ TESTS:
1349
+
1350
+ The field of algebraic numbers is supported (:issue:`19056`)::
1351
+
1352
+ sage: G = DirichletGroup(7, QQbar)
1353
+ sage: G[1].gauss_sum()
1354
+ -2.440133358345538? + 1.022618791871794?*I
1355
+
1356
+ Check that :issue:`19060` is fixed::
1357
+
1358
+ sage: K.<z> = CyclotomicField(8)
1359
+ sage: G = DirichletGroup(13, K)
1360
+ sage: chi = G([z^2])
1361
+ sage: chi.gauss_sum()
1362
+ zeta52^22 + zeta52^21 + zeta52^19 - zeta52^16 + zeta52^15 + zeta52^14
1363
+ + zeta52^12 - zeta52^11 - zeta52^10 - zeta52^7 - zeta52^5 + zeta52^4
1364
+
1365
+ Check that :issue:`25127` is fixed::
1366
+
1367
+ sage: G = DirichletGroup(1)
1368
+ sage: chi = G.one()
1369
+ sage: chi.gauss_sum()
1370
+ 1
1371
+
1372
+ .. SEEALSO::
1373
+
1374
+ - :func:`sage.arith.misc.gauss_sum` for general finite fields
1375
+ - :func:`sage.rings.padics.misc.gauss_sum` for a `p`-adic version
1376
+ """
1377
+ G = self.parent()
1378
+ K = G.base_ring()
1379
+ chi = self
1380
+ m = G.modulus()
1381
+ if isinstance(K, sage.rings.abc.ComplexField):
1382
+ return self.gauss_sum_numerical(a=a)
1383
+ elif isinstance(K, sage.rings.abc.AlgebraicField):
1384
+ L = K
1385
+ zeta = L.zeta(m)
1386
+ elif isinstance(K, (sage.rings.abc.NumberField_cyclotomic,
1387
+ RationalField)):
1388
+ chi = chi.minimize_base_ring()
1389
+ n = lcm(m, G.zeta_order())
1390
+ L = CyclotomicField(n)
1391
+ zeta = L.gen(0) ** (n // m)
1392
+ else:
1393
+ raise NotImplementedError("Gauss sums only currently implemented when the base ring is a cyclotomic field, QQ, QQbar, or a complex field")
1394
+ zeta = zeta ** a
1395
+ g = L(chi(0))
1396
+ z = L.one()
1397
+ for c in chi.values()[1:]:
1398
+ z *= zeta
1399
+ g += L(c) * z
1400
+ return g
1401
+
1402
+ def gauss_sum_numerical(self, prec=53, a=1):
1403
+ r"""
1404
+ Return a Gauss sum associated to this Dirichlet character as an
1405
+ approximate complex number with ``prec`` bits of precision.
1406
+
1407
+ INPUT:
1408
+
1409
+ - ``prec`` -- integer (default: 53); *bits* of precision
1410
+
1411
+ - ``a`` -- integer; as for :meth:`gauss_sum`
1412
+
1413
+ The Gauss sum associated to `\chi` is
1414
+
1415
+ .. MATH::
1416
+
1417
+ g_a(\chi) = \sum_{r \in \ZZ/m\ZZ} \chi(r)\,\zeta^{ar},
1418
+
1419
+ where `m` is the modulus of `\chi` and `\zeta` is a primitive
1420
+ `m`-th root of unity.
1421
+
1422
+ EXAMPLES::
1423
+
1424
+ sage: G = DirichletGroup(3)
1425
+ sage: e = G.0
1426
+ sage: abs(e.gauss_sum_numerical())
1427
+ 1.7320508075...
1428
+ sage: sqrt(3.0)
1429
+ 1.73205080756888
1430
+ sage: e.gauss_sum_numerical(a=2)
1431
+ -...e-15 - 1.7320508075...*I
1432
+ sage: e.gauss_sum_numerical(a=2, prec=100)
1433
+ 4.7331654313260708324703713917e-30 - 1.7320508075688772935274463415*I
1434
+ sage: G = DirichletGroup(13)
1435
+ sage: H = DirichletGroup(13, CC)
1436
+ sage: e = G.0
1437
+ sage: f = H.0
1438
+ sage: e.gauss_sum_numerical()
1439
+ -3.07497205... + 1.8826966926...*I
1440
+ sage: f.gauss_sum_numerical()
1441
+ -3.07497205... + 1.8826966926...*I
1442
+ sage: abs(e.gauss_sum_numerical())
1443
+ 3.60555127546...
1444
+ sage: abs(f.gauss_sum_numerical())
1445
+ 3.60555127546...
1446
+ sage: sqrt(13.0)
1447
+ 3.60555127546399
1448
+
1449
+ TESTS:
1450
+
1451
+ The field of algebraic numbers is supported (:issue:`19056`)::
1452
+
1453
+ sage: G = DirichletGroup(7, QQbar)
1454
+ sage: G[1].gauss_sum_numerical()
1455
+ -2.44013335834554 + 1.02261879187179*I
1456
+ """
1457
+ G = self.parent()
1458
+ K = G.base_ring()
1459
+ if isinstance(K, sage.rings.abc.ComplexField):
1460
+
1461
+ def phi(t):
1462
+ return t
1463
+ CC = K
1464
+ elif isinstance(K, sage.rings.abc.AlgebraicField):
1465
+ from sage.rings.complex_mpfr import ComplexField
1466
+ CC = ComplexField(prec)
1467
+ phi = CC.coerce_map_from(K)
1468
+ elif isinstance(K, (sage.rings.abc.NumberField_cyclotomic,
1469
+ RationalField)):
1470
+ phi = K.complex_embedding(prec)
1471
+ CC = phi.codomain()
1472
+ else:
1473
+ raise NotImplementedError("Gauss sums only currently implemented when the base ring is a cyclotomic field, QQ, QQbar, or a complex field")
1474
+ zeta = CC.zeta(G.modulus()) ** a
1475
+ g = phi(self(0))
1476
+ z = CC.one()
1477
+ for c in self.values()[1:]:
1478
+ z *= zeta
1479
+ g += phi(c) * z
1480
+ return g
1481
+
1482
+ def jacobi_sum(self, char, check=True):
1483
+ r"""
1484
+ Return the Jacobi sum associated to these Dirichlet characters
1485
+ (i.e., J(self,char)).
1486
+
1487
+ This is defined as
1488
+
1489
+ .. MATH::
1490
+
1491
+ J(\chi, \psi) = \sum_{a \in \ZZ / N\ZZ} \chi(a) \psi(1-a)
1492
+
1493
+ where `\chi` and `\psi` are both characters modulo `N`.
1494
+
1495
+ EXAMPLES::
1496
+
1497
+ sage: D = DirichletGroup(13)
1498
+ sage: e = D.0
1499
+ sage: f = D[-2]
1500
+ sage: e.jacobi_sum(f)
1501
+ 3*zeta12^2 + 2*zeta12 - 3
1502
+ sage: f.jacobi_sum(e)
1503
+ 3*zeta12^2 + 2*zeta12 - 3
1504
+ sage: p = 7
1505
+ sage: DP = DirichletGroup(p)
1506
+ sage: f = DP.0
1507
+ sage: e.jacobi_sum(f)
1508
+ Traceback (most recent call last):
1509
+ ...
1510
+ NotImplementedError: Characters must be from the same Dirichlet Group.
1511
+
1512
+ sage: all_jacobi_sums = [(DP[i].values_on_gens(),
1513
+ ....: DP[j].values_on_gens(),
1514
+ ....: DP[i].jacobi_sum(DP[j]))
1515
+ ....: for i in range(p - 1) for j in range(i, p - 1)]
1516
+ sage: for s in all_jacobi_sums:
1517
+ ....: print(s)
1518
+ ((1,), (1,), 5)
1519
+ ((1,), (zeta6,), -1)
1520
+ ((1,), (zeta6 - 1,), -1)
1521
+ ((1,), (-1,), -1)
1522
+ ((1,), (-zeta6,), -1)
1523
+ ((1,), (-zeta6 + 1,), -1)
1524
+ ((zeta6,), (zeta6,), -zeta6 + 3)
1525
+ ((zeta6,), (zeta6 - 1,), 2*zeta6 + 1)
1526
+ ((zeta6,), (-1,), -2*zeta6 - 1)
1527
+ ((zeta6,), (-zeta6,), zeta6 - 3)
1528
+ ((zeta6,), (-zeta6 + 1,), 1)
1529
+ ((zeta6 - 1,), (zeta6 - 1,), -3*zeta6 + 2)
1530
+ ((zeta6 - 1,), (-1,), 2*zeta6 + 1)
1531
+ ((zeta6 - 1,), (-zeta6,), -1)
1532
+ ((zeta6 - 1,), (-zeta6 + 1,), -zeta6 - 2)
1533
+ ((-1,), (-1,), 1)
1534
+ ((-1,), (-zeta6,), -2*zeta6 + 3)
1535
+ ((-1,), (-zeta6 + 1,), 2*zeta6 - 3)
1536
+ ((-zeta6,), (-zeta6,), 3*zeta6 - 1)
1537
+ ((-zeta6,), (-zeta6 + 1,), -2*zeta6 + 3)
1538
+ ((-zeta6 + 1,), (-zeta6 + 1,), zeta6 + 2)
1539
+
1540
+ Let's check that trivial sums are being calculated correctly::
1541
+
1542
+ sage: N = 13
1543
+ sage: D = DirichletGroup(N)
1544
+ sage: g = D(1)
1545
+ sage: g.jacobi_sum(g)
1546
+ 11
1547
+ sage: sum([g(x)*g(1-x) for x in IntegerModRing(N)])
1548
+ 11
1549
+
1550
+ And sums where exactly one character is nontrivial (see :issue:`6393`)::
1551
+
1552
+ sage: G = DirichletGroup(5); X = G.list(); Y = X[0]; Z = X[1]
1553
+ sage: Y.jacobi_sum(Z)
1554
+ -1
1555
+ sage: Z.jacobi_sum(Y)
1556
+ -1
1557
+
1558
+ Now let's take a look at a non-prime modulus::
1559
+
1560
+ sage: N = 9
1561
+ sage: D = DirichletGroup(N)
1562
+ sage: g = D(1)
1563
+ sage: g.jacobi_sum(g)
1564
+ 3
1565
+
1566
+ We consider a sum with values in a finite field::
1567
+
1568
+ sage: g = DirichletGroup(17, GF(9,'a')).0
1569
+ sage: g.jacobi_sum(g**2)
1570
+ 2*a
1571
+
1572
+ TESTS:
1573
+
1574
+ This shows that :issue:`6393` has been fixed::
1575
+
1576
+ sage: G = DirichletGroup(5); X = G.list(); Y = X[0]; Z = X[1]
1577
+ sage: # Y is trivial and Z is quartic
1578
+ sage: sum([Y(x)*Z(1-x) for x in IntegerModRing(5)])
1579
+ -1
1580
+ sage: # The value -1 above is the correct value of the Jacobi sum J(Y, Z).
1581
+ sage: Y.jacobi_sum(Z); Z.jacobi_sum(Y)
1582
+ -1
1583
+ -1
1584
+ """
1585
+ if check:
1586
+ if self.parent() != char.parent():
1587
+ raise NotImplementedError("Characters must be from the same Dirichlet Group.")
1588
+
1589
+ return sum([self(x) * char(1 - x)
1590
+ for x in IntegerModRing(self.modulus())])
1591
+
1592
+ def kloosterman_sum(self, a=1, b=0):
1593
+ r"""
1594
+ Return the "twisted" Kloosterman sum associated to this Dirichlet character.
1595
+
1596
+ This includes Gauss sums, classical Kloosterman sums, Salié sums, etc.
1597
+
1598
+ The Kloosterman sum associated to `\chi` and the integers a,b is
1599
+
1600
+ .. MATH::
1601
+
1602
+ K(a,b,\chi) = \sum_{r \in (\ZZ/m\ZZ)^\times} \chi(r)\,\zeta^{ar+br^{-1}},
1603
+
1604
+ where `m` is the modulus of `\chi` and `\zeta` is a primitive
1605
+ `m` th root of unity. This reduces to the Gauss sum if `b=0`.
1606
+
1607
+ This method performs an exact calculation and returns an element of a
1608
+ suitable cyclotomic field; see also :meth:`.kloosterman_sum_numerical`,
1609
+ which gives an inexact answer (but is generally much quicker).
1610
+
1611
+ CACHING: Computed Kloosterman sums are *not* cached with this
1612
+ character.
1613
+
1614
+ EXAMPLES::
1615
+
1616
+ sage: G = DirichletGroup(3)
1617
+ sage: e = G([-1])
1618
+ sage: e.kloosterman_sum(3,5)
1619
+ -2*zeta6 + 1
1620
+ sage: G = DirichletGroup(20)
1621
+ sage: e = G([1 for u in G.unit_gens()])
1622
+ sage: e.kloosterman_sum(7,17)
1623
+ -2*zeta20^6 + 2*zeta20^4 + 4
1624
+
1625
+ TESTS::
1626
+
1627
+ sage: # needs sage.libs.gap sage.rings.number_field
1628
+ sage: G = DirichletGroup(20, UniversalCyclotomicField())
1629
+ sage: e = G([1 for u in G.unit_gens()])
1630
+ sage: e.kloosterman_sum(7,17)
1631
+ -2*E(5) - 4*E(5)^2 - 4*E(5)^3 - 2*E(5)^4
1632
+
1633
+ sage: # needs sage.rings.number_field
1634
+ sage: G = DirichletGroup(12, QQbar)
1635
+ sage: e = G.gens()[0]
1636
+ sage: e.kloosterman_sum(5, 4)
1637
+ 0.?e-17 - 4.000000000000000?*I
1638
+ sage: e.kloosterman_sum(5,11)
1639
+ 0
1640
+ """
1641
+ G = self.parent()
1642
+ zo = G.zeta_order()
1643
+ m = G.modulus()
1644
+ g = 0
1645
+ L = CyclotomicField(m.lcm(zo))
1646
+ zeta = L.gen(0)
1647
+ try:
1648
+ self(1) * zeta**(a + b)
1649
+ except TypeError:
1650
+ raise NotImplementedError('Kloosterman sums not implemented '
1651
+ 'over this ring')
1652
+ n = zeta.multiplicative_order()
1653
+ zeta = zeta**(n // m)
1654
+ for c in m.coprime_integers(m):
1655
+ e = Mod(c, m)
1656
+ g += self(c) * zeta**int(a * e + b * e**(-1))
1657
+ return g
1658
+
1659
+ def kloosterman_sum_numerical(self, prec=53, a=1, b=0):
1660
+ r"""
1661
+ Return the Kloosterman sum associated to this Dirichlet character as
1662
+ an approximate complex number with ``prec`` bits of precision.
1663
+
1664
+ See also :meth:`.kloosterman_sum`, which calculates the sum
1665
+ exactly (which is generally slower).
1666
+
1667
+ INPUT:
1668
+
1669
+ - ``prec`` -- integer (default: 53); *bits* of precision
1670
+ - ``a`` -- integer; as for :meth:`.kloosterman_sum`
1671
+ - ``b`` -- integer; as for :meth:`.kloosterman_sum`
1672
+
1673
+ EXAMPLES::
1674
+
1675
+ sage: G = DirichletGroup(3)
1676
+ sage: e = G.0
1677
+
1678
+ The real component of the numerical value of e is near zero::
1679
+
1680
+ sage: v = e.kloosterman_sum_numerical()
1681
+ sage: v.real() < 1.0e15
1682
+ True
1683
+ sage: v.imag()
1684
+ 1.73205080756888
1685
+ sage: G = DirichletGroup(20)
1686
+ sage: e = G.1
1687
+ sage: e.kloosterman_sum_numerical(53,3,11)
1688
+ 3.80422606518061 - 3.80422606518061*I
1689
+ """
1690
+ G = self.parent()
1691
+ K = G.base_ring()
1692
+ if not isinstance(K, (sage.rings.abc.NumberField_cyclotomic,
1693
+ RationalField)):
1694
+ raise NotImplementedError("Kloosterman sums only currently implemented when the base ring is a cyclotomic field or QQ")
1695
+ phi = K.complex_embedding(prec)
1696
+ CC = phi.codomain()
1697
+ g = 0
1698
+ m = G.modulus()
1699
+ zeta = CC.zeta(m)
1700
+ for c in m.coprime_integers(m):
1701
+ e = Mod(c, m)
1702
+ z = zeta ** int(a * e + b * (e**(-1)))
1703
+ g += phi(self(c)) * z
1704
+ return g
1705
+
1706
+ @cached_method
1707
+ def is_even(self) -> bool:
1708
+ r"""
1709
+ Return ``True`` if and only if `\varepsilon(-1) = 1`.
1710
+
1711
+ EXAMPLES::
1712
+
1713
+ sage: G = DirichletGroup(13)
1714
+ sage: e = G.0
1715
+ sage: e.is_even()
1716
+ False
1717
+ sage: e(-1)
1718
+ -1
1719
+ sage: [e.is_even() for e in G]
1720
+ [True, False, True, False, True, False, True, False, True, False, True, False]
1721
+
1722
+ sage: G = DirichletGroup(13, CC)
1723
+ sage: e = G.0
1724
+ sage: e.is_even()
1725
+ False
1726
+ sage: e(-1)
1727
+ -1.000000...
1728
+ sage: [e.is_even() for e in G]
1729
+ [True, False, True, False, True, False, True, False, True, False, True, False]
1730
+
1731
+ sage: G = DirichletGroup(100000, CC)
1732
+ sage: G.1.is_even()
1733
+ True
1734
+
1735
+ Note that ``is_even`` need not be the negation of
1736
+ is_odd, e.g., in characteristic 2::
1737
+
1738
+ sage: G.<e> = DirichletGroup(13, GF(4,'a'))
1739
+ sage: e.is_even()
1740
+ True
1741
+ sage: e.is_odd()
1742
+ True
1743
+ """
1744
+ R = self.base_ring()
1745
+ # self(-1) is either +1 or -1
1746
+ if not R.is_exact():
1747
+ return abs(self(-1) - R.one()) < 0.5
1748
+ return self(-1) == R.one()
1749
+
1750
+ @cached_method
1751
+ def is_odd(self) -> bool:
1752
+ r"""
1753
+ Return ``True`` if and only if `\varepsilon(-1) = -1`.
1754
+
1755
+ EXAMPLES::
1756
+
1757
+ sage: G = DirichletGroup(13)
1758
+ sage: e = G.0
1759
+ sage: e.is_odd()
1760
+ True
1761
+ sage: [e.is_odd() for e in G]
1762
+ [False, True, False, True, False, True, False, True, False, True, False, True]
1763
+
1764
+ sage: G = DirichletGroup(13)
1765
+ sage: e = G.0
1766
+ sage: e.is_odd()
1767
+ True
1768
+ sage: [e.is_odd() for e in G]
1769
+ [False, True, False, True, False, True, False, True, False, True, False, True]
1770
+
1771
+ sage: G = DirichletGroup(100000, CC)
1772
+ sage: G.0.is_odd()
1773
+ True
1774
+
1775
+ Note that ``is_even`` need not be the negation of
1776
+ is_odd, e.g., in characteristic 2::
1777
+
1778
+ sage: G.<e> = DirichletGroup(13, GF(4,'a'))
1779
+ sage: e.is_even()
1780
+ True
1781
+ sage: e.is_odd()
1782
+ True
1783
+ """
1784
+ R = self.base_ring()
1785
+ # self(-1) is either +1 or -1
1786
+ if not R.is_exact():
1787
+ return abs(self(-1) - R(-1)) < 0.5
1788
+ return self(-1) == R(-1)
1789
+
1790
+ @cached_method
1791
+ def is_primitive(self) -> bool:
1792
+ """
1793
+ Return ``True`` if and only if this character is
1794
+ primitive, i.e., its conductor equals its modulus.
1795
+
1796
+ EXAMPLES::
1797
+
1798
+ sage: G.<a,b> = DirichletGroup(20)
1799
+ sage: a.is_primitive()
1800
+ False
1801
+ sage: b.is_primitive()
1802
+ False
1803
+ sage: (a*b).is_primitive()
1804
+ True
1805
+ sage: G.<a,b> = DirichletGroup(20, CC)
1806
+ sage: a.is_primitive()
1807
+ False
1808
+ sage: b.is_primitive()
1809
+ False
1810
+ sage: (a*b).is_primitive()
1811
+ True
1812
+ """
1813
+ return (self.conductor() == self.modulus())
1814
+
1815
+ @cached_method
1816
+ def is_trivial(self) -> bool:
1817
+ r"""
1818
+ Return ``True`` if this is the trivial character,
1819
+ i.e., has order 1.
1820
+
1821
+ EXAMPLES::
1822
+
1823
+ sage: G.<a,b> = DirichletGroup(20)
1824
+ sage: a.is_trivial()
1825
+ False
1826
+ sage: (a^2).is_trivial()
1827
+ True
1828
+ """
1829
+ if self.element.is_in_cache():
1830
+ return not self.element()
1831
+ one = self.base_ring().one()
1832
+ return all(x == one for x in self.values_on_gens())
1833
+
1834
+ def kernel(self) -> list:
1835
+ r"""
1836
+ Return the kernel of this character.
1837
+
1838
+ OUTPUT: currently the kernel is returned as a list; this may
1839
+ change
1840
+
1841
+ EXAMPLES::
1842
+
1843
+ sage: G.<a,b> = DirichletGroup(20)
1844
+ sage: a.kernel()
1845
+ [1, 9, 13, 17]
1846
+ sage: b.kernel()
1847
+ [1, 11]
1848
+ """
1849
+ one = self.base_ring().one()
1850
+ return [x for x in range(self.modulus()) if self(x) == one]
1851
+
1852
+ def maximize_base_ring(self):
1853
+ r"""
1854
+ Let
1855
+
1856
+ .. MATH::
1857
+
1858
+ \varepsilon : (\ZZ/N\ZZ)^* \to \QQ(\zeta_n)
1859
+
1860
+ be a Dirichlet character. This function returns an equal Dirichlet
1861
+ character
1862
+
1863
+ .. MATH::
1864
+
1865
+ \chi : (\ZZ/N\ZZ)^* \to \QQ(\zeta_m)
1866
+
1867
+ where `m` is the least common multiple of `n` and
1868
+ the exponent of `(\ZZ/N\ZZ)^*`.
1869
+
1870
+ EXAMPLES::
1871
+
1872
+ sage: G.<a,b> = DirichletGroup(20,QQ)
1873
+ sage: b.maximize_base_ring()
1874
+ Dirichlet character modulo 20 of conductor 5 mapping 11 |--> 1, 17 |--> -1
1875
+ sage: b.maximize_base_ring().base_ring()
1876
+ Cyclotomic Field of order 4 and degree 2
1877
+ sage: DirichletGroup(20).base_ring()
1878
+ Cyclotomic Field of order 4 and degree 2
1879
+ """
1880
+ g = IntegerModRing(self.modulus()).unit_group_exponent()
1881
+ if g == 1:
1882
+ g = 2
1883
+ z = self.base_ring().zeta()
1884
+ n = z.multiplicative_order()
1885
+ m = lcm(g, n)
1886
+ if n == m:
1887
+ return self
1888
+ K = CyclotomicField(m)
1889
+ return self.change_ring(K)
1890
+
1891
+ def minimize_base_ring(self):
1892
+ r"""
1893
+ Return a Dirichlet character that equals this one, but over as
1894
+ small a subfield (or subring) of the base ring as possible.
1895
+
1896
+ .. NOTE::
1897
+
1898
+ This function is currently only implemented when the base
1899
+ ring is a number field. It is the identity function in
1900
+ characteristic p.
1901
+
1902
+ EXAMPLES::
1903
+
1904
+ sage: G = DirichletGroup(13)
1905
+ sage: e = DirichletGroup(13).0
1906
+ sage: e.base_ring()
1907
+ Cyclotomic Field of order 12 and degree 4
1908
+ sage: e.minimize_base_ring().base_ring()
1909
+ Cyclotomic Field of order 12 and degree 4
1910
+ sage: (e^2).minimize_base_ring().base_ring()
1911
+ Cyclotomic Field of order 6 and degree 2
1912
+ sage: (e^3).minimize_base_ring().base_ring()
1913
+ Cyclotomic Field of order 4 and degree 2
1914
+ sage: (e^12).minimize_base_ring().base_ring()
1915
+ Rational Field
1916
+
1917
+ TESTS:
1918
+
1919
+ Check that :issue:`18479` is fixed::
1920
+
1921
+ sage: f = Newforms(Gamma1(25), names='a')[1]
1922
+ sage: eps = f.character()
1923
+ sage: eps.minimize_base_ring() == eps
1924
+ True
1925
+
1926
+ A related bug (see :issue:`18086`)::
1927
+
1928
+ sage: x = polygen(ZZ, 'x')
1929
+ sage: K.<a,b> = NumberField([x^2 + 1, x^2 - 3])
1930
+ sage: chi = DirichletGroup(7, K).0
1931
+ sage: chi.minimize_base_ring()
1932
+ Dirichlet character modulo 7 of conductor 7 mapping 3 |--> -1/2*b*a + 1/2
1933
+ """
1934
+ R = self.base_ring()
1935
+ if R.is_prime_field():
1936
+ return self
1937
+ p = R.characteristic()
1938
+
1939
+ if p:
1940
+ K = IntegerModRing(p)
1941
+ elif self.order() <= 2:
1942
+ K = QQ
1943
+ elif (isinstance(R, NumberField_generic)
1944
+ and euler_phi(self.order()) < R.absolute_degree()):
1945
+ K = CyclotomicField(self.order())
1946
+ else:
1947
+ return self
1948
+
1949
+ try:
1950
+ return self.change_ring(K)
1951
+ except (TypeError, ValueError, ArithmeticError):
1952
+ return self
1953
+
1954
+ def modulus(self):
1955
+ """
1956
+ Return the modulus of this character.
1957
+
1958
+ EXAMPLES::
1959
+
1960
+ sage: e = DirichletGroup(100, QQ).0
1961
+ sage: e.modulus()
1962
+ 100
1963
+ sage: e.conductor()
1964
+ 4
1965
+ """
1966
+ return self.parent().modulus()
1967
+
1968
+ def level(self):
1969
+ """
1970
+ Synonym for modulus.
1971
+
1972
+ EXAMPLES::
1973
+
1974
+ sage: e = DirichletGroup(100, QQ).0
1975
+ sage: e.level()
1976
+ 100
1977
+ """
1978
+ return self.modulus()
1979
+
1980
+ @cached_method
1981
+ def multiplicative_order(self):
1982
+ """
1983
+ Return the order of this character.
1984
+
1985
+ EXAMPLES::
1986
+
1987
+ sage: e = DirichletGroup(100).1
1988
+ sage: e.order() # same as multiplicative_order, since group is multiplicative
1989
+ 20
1990
+ sage: e.multiplicative_order()
1991
+ 20
1992
+ sage: e = DirichletGroup(100).0
1993
+ sage: e.multiplicative_order()
1994
+ 2
1995
+ """
1996
+ if self.parent().zeta.is_in_cache():
1997
+ return self.element().additive_order()
1998
+ return lcm([z.multiplicative_order() for z in self.values_on_gens()])
1999
+
2000
+ def primitive_character(self):
2001
+ """
2002
+ Return the primitive character associated to ``self``.
2003
+
2004
+ EXAMPLES::
2005
+
2006
+ sage: e = DirichletGroup(100).0; e
2007
+ Dirichlet character modulo 100 of conductor 4 mapping 51 |--> -1, 77 |--> 1
2008
+ sage: e.conductor()
2009
+ 4
2010
+ sage: f = e.primitive_character(); f
2011
+ Dirichlet character modulo 4 of conductor 4 mapping 3 |--> -1
2012
+ sage: f.modulus()
2013
+ 4
2014
+ """
2015
+ return self.restrict(self.conductor())
2016
+
2017
+ def restrict(self, M):
2018
+ """
2019
+ Return the restriction of this character to a Dirichlet character
2020
+ modulo the divisor ``M`` of the modulus, which must also be a multiple
2021
+ of the conductor of this character.
2022
+
2023
+ EXAMPLES::
2024
+
2025
+ sage: e = DirichletGroup(100).0
2026
+ sage: e.modulus()
2027
+ 100
2028
+ sage: e.conductor()
2029
+ 4
2030
+ sage: e.restrict(20)
2031
+ Dirichlet character modulo 20 of conductor 4 mapping 11 |--> -1, 17 |--> 1
2032
+ sage: e.restrict(4)
2033
+ Dirichlet character modulo 4 of conductor 4 mapping 3 |--> -1
2034
+ sage: e.restrict(50)
2035
+ Traceback (most recent call last):
2036
+ ...
2037
+ ValueError: conductor(=4) must divide M(=50)
2038
+ """
2039
+ M = int(M)
2040
+ if self.modulus() % M:
2041
+ raise ValueError("M(=%s) must divide the modulus(=%s)" % (M, self.modulus()))
2042
+ if M % self.conductor():
2043
+ raise ValueError("conductor(=%s) must divide M(=%s)" % (self.conductor(), M))
2044
+ H = DirichletGroup(M, self.base_ring())
2045
+ return H(self)
2046
+
2047
+ @cached_method
2048
+ def values(self) -> list:
2049
+ """
2050
+ Return a list of the values of this character on each integer
2051
+ between 0 and the modulus.
2052
+
2053
+ EXAMPLES::
2054
+
2055
+ sage: e = DirichletGroup(20)(1)
2056
+ sage: e.values()
2057
+ [0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1]
2058
+ sage: e = DirichletGroup(20).gen(0)
2059
+ sage: e.values()
2060
+ [0, 1, 0, -1, 0, 0, 0, -1, 0, 1, 0, -1, 0, 1, 0, 0, 0, 1, 0, -1]
2061
+ sage: e = DirichletGroup(20).gen(1)
2062
+ sage: e.values()
2063
+ [0, 1, 0, -zeta4, 0, 0, 0, zeta4, 0, -1, 0, 1, 0, -zeta4, 0, 0, 0, zeta4, 0, -1]
2064
+ sage: e = DirichletGroup(21).gen(0) ; e.values()
2065
+ [0, 1, -1, 0, 1, -1, 0, 0, -1, 0, 1, -1, 0, 1, 0, 0, 1, -1, 0, 1, -1]
2066
+ sage: e = DirichletGroup(21, base_ring=GF(37)).gen(0) ; e.values()
2067
+ [0, 1, 36, 0, 1, 36, 0, 0, 36, 0, 1, 36, 0, 1, 0, 0, 1, 36, 0, 1, 36]
2068
+ sage: e = DirichletGroup(21, base_ring=GF(3)).gen(0) ; e.values()
2069
+ [0, 1, 2, 0, 1, 2, 0, 0, 2, 0, 1, 2, 0, 1, 0, 0, 1, 2, 0, 1, 2]
2070
+
2071
+ ::
2072
+
2073
+ sage: chi = DirichletGroup(100151, CyclotomicField(10)).0
2074
+ sage: ls = chi.values() ; ls[0:10]
2075
+ [0,
2076
+ 1,
2077
+ -zeta10^3,
2078
+ -zeta10,
2079
+ -zeta10,
2080
+ 1,
2081
+ zeta10^3 - zeta10^2 + zeta10 - 1,
2082
+ zeta10,
2083
+ zeta10^3 - zeta10^2 + zeta10 - 1,
2084
+ zeta10^2]
2085
+
2086
+ TESTS:
2087
+
2088
+ Test that :issue:`11783` and :issue:`14368` are fixed::
2089
+
2090
+ sage: chi = DirichletGroup(1).list()[0]
2091
+ sage: chi.values()
2092
+ [1]
2093
+ sage: chi(1)
2094
+ 1
2095
+ """
2096
+ G = self.parent()
2097
+ R = G.base_ring()
2098
+
2099
+ mod = self.parent().modulus()
2100
+ if mod == 1:
2101
+ return [R.one()]
2102
+ elif mod == 2:
2103
+ return [R.zero(), R.one()]
2104
+
2105
+ result_list = [R.zero()] * mod
2106
+ gens = G.unit_gens()
2107
+ orders = G.integers_mod().unit_group().gens_orders()
2108
+
2109
+ R_values = G._zeta_powers
2110
+ val_on_gen = self.element()
2111
+
2112
+ exponents = [0] * len(orders)
2113
+ n = G.integers_mod().one()
2114
+ value = val_on_gen.base_ring().zero()
2115
+
2116
+ while True:
2117
+ # record character value on n
2118
+ result_list[n] = R_values[value]
2119
+ # iterate:
2120
+ # increase the exponent vector by 1,
2121
+ # increase n accordingly, and increase value
2122
+ i = 0
2123
+ while True:
2124
+ try:
2125
+ exponents[i] += 1
2126
+ except IndexError: # Done!
2127
+ return result_list
2128
+ value += val_on_gen[i]
2129
+ n *= gens[i]
2130
+ if exponents[i] < orders[i]:
2131
+ break
2132
+ exponents[i] = 0
2133
+ i += 1
2134
+
2135
+ @cached_method(do_pickle=True)
2136
+ def values_on_gens(self) -> tuple:
2137
+ r"""
2138
+ Return a tuple of the values of ``self`` on the standard
2139
+ generators of `(\ZZ/N\ZZ)^*`, where `N` is the modulus.
2140
+
2141
+ EXAMPLES::
2142
+
2143
+ sage: # needs sage.rings.number_field
2144
+ sage: e = DirichletGroup(16)([-1, 1])
2145
+ sage: e.values_on_gens ()
2146
+ (-1, 1)
2147
+
2148
+ .. NOTE::
2149
+
2150
+ The constructor of :class:`DirichletCharacter` sets the
2151
+ cache of :meth:`element` or of :meth:`values_on_gens`. The cache of
2152
+ one of these methods needs to be set for the other method to work properly,
2153
+ these caches have to be stored when pickling an instance of
2154
+ :class:`DirichletCharacter`.
2155
+ """
2156
+ pows = self.parent()._zeta_powers
2157
+ return tuple([pows[i] for i in self.element()])
2158
+
2159
+ @cached_method(do_pickle=True)
2160
+ def element(self):
2161
+ r"""
2162
+ Return the underlying `\ZZ/n\ZZ`-module
2163
+ vector of exponents.
2164
+
2165
+ EXAMPLES::
2166
+
2167
+ sage: G.<a,b> = DirichletGroup(20)
2168
+ sage: a.element()
2169
+ (2, 0)
2170
+ sage: b.element()
2171
+ (0, 1)
2172
+
2173
+ .. NOTE::
2174
+
2175
+ The constructor of :class:`DirichletCharacter` sets the
2176
+ cache of :meth:`element` or of :meth:`values_on_gens`. The cache of
2177
+ one of these methods needs to be set for the other method to work properly,
2178
+ these caches have to be stored when pickling an instance of
2179
+ :class:`DirichletCharacter`.
2180
+ """
2181
+ P = self.parent()
2182
+ M = P._module
2183
+ if isinstance(P.base_ring(), sage.rings.abc.ComplexField):
2184
+ zeta = P.zeta()
2185
+ zeta_argument = zeta.argument()
2186
+ v = M([int(round(x.argument() / zeta_argument))
2187
+ for x in self.values_on_gens()])
2188
+ else:
2189
+ dlog = P._zeta_dlog
2190
+ v = M([dlog[x] for x in self.values_on_gens()])
2191
+ v.set_immutable()
2192
+ return v
2193
+
2194
+ def __setstate__(self, state):
2195
+ r"""
2196
+ Restore a pickled element from ``state``.
2197
+
2198
+ TESTS::
2199
+
2200
+ sage: # needs sage.rings.number_field
2201
+ sage: e = DirichletGroup(16)([-1, 1])
2202
+ sage: loads(dumps(e)) == e
2203
+ True
2204
+ """
2205
+ # values_on_gens() used an explicit cache __values_on_gens in the past
2206
+ # we need to set the cache of values_on_gens() from that if we encounter it in a pickle
2207
+ values_on_gens_key = '_DirichletCharacter__values_on_gens'
2208
+ values_on_gens = None
2209
+ state_dict = state[1]
2210
+ if values_on_gens_key in state_dict:
2211
+ values_on_gens = state_dict[values_on_gens_key]
2212
+ del state_dict[values_on_gens_key]
2213
+
2214
+ # element() used an explicit cache __element in the past
2215
+ # we need to set the cache of element() from that if we encounter it in a pickle
2216
+ element_key = '_DirichletCharacter__element'
2217
+ element = None
2218
+ if element_key in state_dict:
2219
+ element = state_dict[element_key]
2220
+ del state_dict[element_key]
2221
+
2222
+ super().__setstate__(state)
2223
+
2224
+ if values_on_gens is not None:
2225
+ self.values_on_gens.set_cache(values_on_gens)
2226
+ if element is not None:
2227
+ self.element.set_cache(element)
2228
+
2229
+
2230
+ class DirichletGroupFactory(UniqueFactory):
2231
+ r"""
2232
+ Construct a group of Dirichlet characters modulo `N`.
2233
+
2234
+ INPUT:
2235
+
2236
+ - ``N`` -- positive integer
2237
+
2238
+ - ``base_ring`` -- commutative ring; the value ring for the
2239
+ characters in this group (default: the cyclotomic field
2240
+ `\QQ(\zeta_n)`, where `n` is the exponent of `(\ZZ/N\ZZ)^*`)
2241
+
2242
+ - ``zeta`` -- (optional) root of unity in ``base_ring``
2243
+
2244
+ - ``zeta_order`` -- (optional) positive integer; this must be the
2245
+ order of ``zeta`` if both are specified
2246
+
2247
+ - ``names`` -- ignored (needed so ``G.<...> = DirichletGroup(...)``
2248
+ notation works)
2249
+
2250
+ - ``integral`` -- boolean (default: ``False``); whether to replace
2251
+ the default cyclotomic field by its rings of integers as the
2252
+ base ring. This is ignored if ``base_ring`` is not ``None``.
2253
+
2254
+ OUTPUT:
2255
+
2256
+ The group of Dirichlet characters modulo `N` with values in a
2257
+ subgroup `V` of the multiplicative group `R^*` of ``base_ring``.
2258
+ This is the group of homomorphisms `(\ZZ/N\ZZ)^* \to V` with
2259
+ pointwise multiplication. The group `V` is determined as follows:
2260
+
2261
+ - If both ``zeta`` and ``zeta_order`` are omitted, then `V` is
2262
+ taken to be `R^*`, or equivalently its `n`-torsion subgroup,
2263
+ where `n` is the exponent of `(\ZZ/N\ZZ)^*`. Many operations,
2264
+ such as finding a set of generators for the group, are only
2265
+ implemented if `V` is cyclic and a generator for `V` can be
2266
+ found.
2267
+
2268
+ - If ``zeta`` is specified, then `V` is taken to be the cyclic
2269
+ subgroup of `R^*` generated by ``zeta``. If ``zeta_order`` is
2270
+ also given, it must be the multiplicative order of ``zeta``;
2271
+ this is useful if the base ring is not exact or if the order of
2272
+ ``zeta`` is very large.
2273
+
2274
+ - If ``zeta`` is not specified but ``zeta_order`` is, then `V` is
2275
+ taken to be the group of roots of unity of order dividing
2276
+ ``zeta_order`` in `R`. In this case, `R` must be a domain (so
2277
+ `V` is cyclic), and `V` must have order ``zeta_order``.
2278
+ Furthermore, a generator ``zeta`` of `V` is computed, and an
2279
+ error is raised if such ``zeta`` cannot be found.
2280
+
2281
+ EXAMPLES:
2282
+
2283
+ The default base ring is a cyclotomic field of order the exponent
2284
+ of `(\ZZ/N\ZZ)^*`::
2285
+
2286
+ sage: DirichletGroup(20)
2287
+ Group of Dirichlet characters modulo 20 with values
2288
+ in Cyclotomic Field of order 4 and degree 2
2289
+
2290
+ We create the group of Dirichlet character mod 20 with values in
2291
+ the rational numbers::
2292
+
2293
+ sage: G = DirichletGroup(20, QQ); G
2294
+ Group of Dirichlet characters modulo 20 with values in Rational Field
2295
+ sage: G.order()
2296
+ 4
2297
+ sage: G.base_ring()
2298
+ Rational Field
2299
+
2300
+ The elements of G print as lists giving the values of the character
2301
+ on the generators of `(Z/NZ)^*`::
2302
+
2303
+ sage: list(G)
2304
+ [Dirichlet character modulo 20 of conductor 1 mapping 11 |--> 1, 17 |--> 1,
2305
+ Dirichlet character modulo 20 of conductor 4 mapping 11 |--> -1, 17 |--> 1,
2306
+ Dirichlet character modulo 20 of conductor 5 mapping 11 |--> 1, 17 |--> -1,
2307
+ Dirichlet character modulo 20 of conductor 20 mapping 11 |--> -1, 17 |--> -1]
2308
+
2309
+ Next we construct the group of Dirichlet character mod 20, but with
2310
+ values in `\QQ(\zeta_n)`::
2311
+
2312
+ sage: G = DirichletGroup(20)
2313
+ sage: G.1
2314
+ Dirichlet character modulo 20 of conductor 5 mapping 11 |--> 1, 17 |--> zeta4
2315
+
2316
+ We next compute several invariants of ``G``::
2317
+
2318
+ sage: G.gens()
2319
+ (Dirichlet character modulo 20 of conductor 4 mapping 11 |--> -1, 17 |--> 1,
2320
+ Dirichlet character modulo 20 of conductor 5 mapping 11 |--> 1, 17 |--> zeta4)
2321
+ sage: G.unit_gens()
2322
+ (11, 17)
2323
+ sage: G.zeta()
2324
+ zeta4
2325
+ sage: G.zeta_order()
2326
+ 4
2327
+
2328
+ In this example we create a Dirichlet group with values in a
2329
+ number field::
2330
+
2331
+ sage: R.<x> = PolynomialRing(QQ)
2332
+ sage: K.<a> = NumberField(x^4 + 1)
2333
+ sage: DirichletGroup(5, K)
2334
+ Group of Dirichlet characters modulo 5 with values
2335
+ in Number Field in a with defining polynomial x^4 + 1
2336
+
2337
+ An example where we give ``zeta``, but not its order::
2338
+
2339
+ sage: G = DirichletGroup(5, K, a); G
2340
+ Group of Dirichlet characters modulo 5 with values in the group of order 8
2341
+ generated by a in Number Field in a with defining polynomial x^4 + 1
2342
+ sage: G.list()
2343
+ [Dirichlet character modulo 5 of conductor 1 mapping 2 |--> 1,
2344
+ Dirichlet character modulo 5 of conductor 5 mapping 2 |--> a^2,
2345
+ Dirichlet character modulo 5 of conductor 5 mapping 2 |--> -1,
2346
+ Dirichlet character modulo 5 of conductor 5 mapping 2 |--> -a^2]
2347
+
2348
+ We can also restrict the order of the characters, either with or
2349
+ without specifying a root of unity::
2350
+
2351
+ sage: DirichletGroup(5, K, zeta=-1, zeta_order=2)
2352
+ Group of Dirichlet characters modulo 5 with values in the group of order 2
2353
+ generated by -1 in Number Field in a with defining polynomial x^4 + 1
2354
+ sage: DirichletGroup(5, K, zeta_order=2)
2355
+ Group of Dirichlet characters modulo 5 with values in the group of order 2
2356
+ generated by -1 in Number Field in a with defining polynomial x^4 + 1
2357
+
2358
+ ::
2359
+
2360
+ sage: G.<e> = DirichletGroup(13)
2361
+ sage: loads(G.dumps()) == G
2362
+ True
2363
+
2364
+ ::
2365
+
2366
+ sage: G = DirichletGroup(19, GF(5))
2367
+ sage: loads(G.dumps()) == G
2368
+ True
2369
+
2370
+ We compute a Dirichlet group over a large prime field::
2371
+
2372
+ sage: p = next_prime(10^40)
2373
+ sage: g = DirichletGroup(19, GF(p)); g
2374
+ Group of Dirichlet characters modulo 19 with values
2375
+ in Finite Field of size 10000000000000000000000000000000000000121
2376
+
2377
+ Note that the root of unity has small order, i.e., it is not the
2378
+ largest order root of unity in the field::
2379
+
2380
+ sage: g.zeta_order()
2381
+ 2
2382
+
2383
+ ::
2384
+
2385
+ sage: K = CyclotomicField(4)
2386
+ sage: r4 = K.ring_of_integers()
2387
+ sage: G = DirichletGroup(60, r4)
2388
+ sage: G.gens()
2389
+ (Dirichlet character modulo 60 of conductor 4
2390
+ mapping 31 |--> -1, 41 |--> 1, 37 |--> 1,
2391
+ Dirichlet character modulo 60 of conductor 3
2392
+ mapping 31 |--> 1, 41 |--> -1, 37 |--> 1,
2393
+ Dirichlet character modulo 60 of conductor 5
2394
+ mapping 31 |--> 1, 41 |--> 1, 37 |--> zeta4)
2395
+ sage: val = G.gens()[2].values_on_gens()[2] ; val
2396
+ zeta4
2397
+ sage: parent(val)
2398
+ Gaussian Integers generated by zeta4 in Cyclotomic Field of order 4 and degree 2
2399
+ sage: r4_29_0 = r4.residue_field(K(29).factor()[0][0]); r4_29_0(val)
2400
+ 12
2401
+ sage: r4_29_0(val) * GF(29)(3)
2402
+ 7
2403
+ sage: r4_29_0(G.gens()[2].values_on_gens()[2]) * 3
2404
+ 7
2405
+ sage: parent(r4_29_0(G.gens()[2].values_on_gens()[2]) * 3)
2406
+ Residue field of Fractional ideal (-2*zeta4 - 5)
2407
+
2408
+ ::
2409
+
2410
+ sage: DirichletGroup(60, integral=True)
2411
+ Group of Dirichlet characters modulo 60 with values in
2412
+ Gaussian Integers generated by zeta4 in Cyclotomic Field of order 4 and degree 2
2413
+ sage: parent(DirichletGroup(60, integral=True).gens()[2].values_on_gens()[2])
2414
+ Gaussian Integers generated by zeta4 in Cyclotomic Field of order 4 and degree 2
2415
+
2416
+ If the order of ``zeta`` cannot be determined automatically, we
2417
+ can specify it using ``zeta_order``::
2418
+
2419
+ sage: DirichletGroup(7, CC, zeta=exp(2*pi*I/6)) # needs sage.symbolic
2420
+ Traceback (most recent call last):
2421
+ ...
2422
+ NotImplementedError: order of element not known
2423
+
2424
+ sage: DirichletGroup(7, CC, zeta=exp(2*pi*I/6), zeta_order=6) # needs sage.symbolic
2425
+ Group of Dirichlet characters modulo 7 with values in the group of order 6
2426
+ generated by 0.500000000000000 + 0.866025403784439*I
2427
+ in Complex Field with 53 bits of precision
2428
+
2429
+ If the base ring is not a domain (in which case the group of roots
2430
+ of unity is not necessarily cyclic), some operations still work,
2431
+ such as creation of elements::
2432
+
2433
+ sage: G = DirichletGroup(5, Zmod(15)); G
2434
+ Group of Dirichlet characters modulo 5 with values in Ring of integers modulo 15
2435
+ sage: chi = G([13]); chi
2436
+ Dirichlet character modulo 5 of conductor 5 mapping 2 |--> 13
2437
+ sage: chi^2
2438
+ Dirichlet character modulo 5 of conductor 5 mapping 2 |--> 4
2439
+ sage: chi.multiplicative_order()
2440
+ 4
2441
+
2442
+ Other operations only work if ``zeta`` is specified::
2443
+
2444
+ sage: G.gens()
2445
+ Traceback (most recent call last):
2446
+ ...
2447
+ NotImplementedError: factorization of polynomials over rings
2448
+ with composite characteristic is not implemented
2449
+ sage: G = DirichletGroup(5, Zmod(15), zeta=2); G
2450
+ Group of Dirichlet characters modulo 5 with values in the group of order 4
2451
+ generated by 2 in Ring of integers modulo 15
2452
+ sage: G.gens()
2453
+ (Dirichlet character modulo 5 of conductor 5 mapping 2 |--> 2,)
2454
+
2455
+ TESTS:
2456
+
2457
+ Dirichlet groups are cached, creating two groups with the same parameters
2458
+ yields the same object::
2459
+
2460
+ sage: DirichletGroup(60) is DirichletGroup(60)
2461
+ True
2462
+
2463
+ Test for pickling::
2464
+
2465
+ sage: G = DirichletGroup(9)
2466
+ sage: loads(dumps(G)) is G
2467
+ True
2468
+ """
2469
+ def create_key(self, N, base_ring=None, zeta=None, zeta_order=None,
2470
+ names=None, integral=False):
2471
+ """
2472
+ Create a key that uniquely determines a Dirichlet group.
2473
+
2474
+ TESTS::
2475
+
2476
+ sage: DirichletGroup.create_key(60)
2477
+ (Cyclotomic Field of order 4 and degree 2, 60, None, None)
2478
+
2479
+ An example to illustrate that ``base_ring`` is a part of the key::
2480
+
2481
+ sage: k = DirichletGroup.create_key(2, base_ring=QQ); k
2482
+ (Rational Field, 2, None, None)
2483
+ sage: l = DirichletGroup.create_key(2, base_ring=CC); l
2484
+ (Complex Field with 53 bits of precision, 2, None, None)
2485
+ sage: k == l
2486
+ False
2487
+ sage: G = DirichletGroup.create_object(None, k); G
2488
+ Group of Dirichlet characters modulo 2 with values in Rational Field
2489
+ sage: H = DirichletGroup.create_object(None, l); H
2490
+ Group of Dirichlet characters modulo 2 with values in Complex Field with 53 bits of precision
2491
+ sage: G == H
2492
+ False
2493
+
2494
+ If ``base_ring`` was not be a part of the key, the keys would compare
2495
+ equal and the caching would be broken::
2496
+
2497
+ sage: k = k[1:]; k
2498
+ (2, None, None)
2499
+ sage: l = l[1:]; l
2500
+ (2, None, None)
2501
+ sage: k == l
2502
+ True
2503
+ sage: DirichletGroup(2, base_ring=QQ) is DirichletGroup(2, base_ring=CC)
2504
+ False
2505
+
2506
+ If the base ring is not an integral domain, an error will be
2507
+ raised if only ``zeta_order`` is specified::
2508
+
2509
+ sage: DirichletGroup(17, Integers(15))
2510
+ Group of Dirichlet characters modulo 17 with values in Ring of integers modulo 15
2511
+ sage: DirichletGroup(17, Integers(15), zeta_order=4)
2512
+ Traceback (most recent call last):
2513
+ ...
2514
+ ValueError: base ring (= Ring of integers modulo 15) must be an integral domain if only zeta_order is specified
2515
+ sage: G = DirichletGroup(17, Integers(15), zeta=7); G
2516
+ Group of Dirichlet characters modulo 17 with values in the group of order 4 generated by 7 in Ring of integers modulo 15
2517
+ sage: G.order()
2518
+ 4
2519
+
2520
+ sage: DirichletGroup(-33)
2521
+ Traceback (most recent call last):
2522
+ ...
2523
+ ValueError: modulus should be positive
2524
+ """
2525
+ modulus = Integer(N)
2526
+ if modulus <= 0:
2527
+ raise ValueError('modulus should be positive')
2528
+
2529
+ if base_ring is None:
2530
+ if not (zeta is None and zeta_order is None):
2531
+ raise ValueError("zeta and zeta_order must be None if base_ring not specified")
2532
+ e = IntegerModRing(modulus).unit_group_exponent()
2533
+ base_ring = CyclotomicField(e)
2534
+ if integral:
2535
+ base_ring = base_ring.ring_of_integers()
2536
+
2537
+ if base_ring not in Rings():
2538
+ raise TypeError("base_ring (= %s) must be a ring" % base_ring)
2539
+
2540
+ # If either zeta or zeta_order is given, compute the other.
2541
+ if zeta is not None:
2542
+ zeta = base_ring(zeta)
2543
+ if zeta_order is None:
2544
+ zeta_order = zeta.multiplicative_order()
2545
+ elif zeta_order is not None:
2546
+ if not base_ring.is_integral_domain():
2547
+ raise ValueError("base ring (= %s) must be an integral domain if only zeta_order is specified"
2548
+ % base_ring)
2549
+ zeta_order = Integer(zeta_order)
2550
+ zeta = base_ring.zeta(zeta_order)
2551
+
2552
+ return (base_ring, modulus, zeta, zeta_order)
2553
+
2554
+ def create_object(self, version, key, **extra_args):
2555
+ """
2556
+ Create the object from the key (extra arguments are ignored).
2557
+
2558
+ This is only called if the object was not found in the cache.
2559
+
2560
+ TESTS::
2561
+
2562
+ sage: # needs sage.rings.number_field
2563
+ sage: K = CyclotomicField(4)
2564
+ sage: DirichletGroup.create_object(None, (K, 60, K.gen(), 4))
2565
+ Group of Dirichlet characters modulo 60 with values in the group of order 4
2566
+ generated by zeta4 in Cyclotomic Field of order 4 and degree 2
2567
+ """
2568
+ base_ring, modulus, zeta, zeta_order = key
2569
+ return DirichletGroup_class(base_ring, modulus, zeta, zeta_order)
2570
+
2571
+
2572
+ DirichletGroup = DirichletGroupFactory("DirichletGroup")
2573
+
2574
+
2575
+ def is_DirichletGroup(x) -> bool:
2576
+ """
2577
+ Return ``True`` if ``x`` is a Dirichlet group.
2578
+
2579
+ EXAMPLES::
2580
+
2581
+ sage: from sage.modular.dirichlet import is_DirichletGroup
2582
+ sage: is_DirichletGroup(DirichletGroup(11))
2583
+ doctest:warning...
2584
+ DeprecationWarning: The function is_DirichletGroup is deprecated; use 'isinstance(..., DirichletGroup_class)' instead.
2585
+ See https://github.com/sagemath/sage/issues/38035 for details.
2586
+ True
2587
+ sage: is_DirichletGroup(11)
2588
+ False
2589
+ sage: is_DirichletGroup(DirichletGroup(11).0)
2590
+ False
2591
+ """
2592
+ from sage.misc.superseded import deprecation
2593
+ deprecation(38035, "The function is_DirichletGroup is deprecated; use 'isinstance(..., DirichletGroup_class)' instead.")
2594
+ return isinstance(x, DirichletGroup_class)
2595
+
2596
+
2597
+ class DirichletGroup_class(WithEqualityById, Parent):
2598
+ """
2599
+ Group of Dirichlet characters modulo `N` with values in a ring `R`.
2600
+ """
2601
+
2602
+ Element = DirichletCharacter
2603
+
2604
+ def __init__(self, base_ring, modulus, zeta, zeta_order) -> None:
2605
+ """
2606
+ Create a Dirichlet group.
2607
+
2608
+ Not to be called directly (use the factory function ``DirichletGroup``).
2609
+
2610
+ The ``DirichletGroup`` factory ensures that either both
2611
+ ``zeta`` and ``zeta_order`` are specified, or that both are
2612
+ ``None``. In the former case, it also ensures that ``zeta``
2613
+ is an element of ``base_ring`` and that ``zeta_order`` is an
2614
+ element of ``ZZ``.
2615
+
2616
+ TESTS::
2617
+
2618
+ sage: G = DirichletGroup(7, base_ring=Integers(9), zeta=2) # indirect doctest
2619
+ sage: TestSuite(G).run()
2620
+ sage: G.base() # check that Parent.__init__ has been called
2621
+ Ring of integers modulo 9
2622
+
2623
+ sage: DirichletGroup(13) == DirichletGroup(13)
2624
+ True
2625
+ sage: DirichletGroup(13) == DirichletGroup(13, QQ)
2626
+ False
2627
+ """
2628
+ from sage.categories.groups import Groups
2629
+ category = Groups().Commutative()
2630
+ if base_ring.is_integral_domain() or base_ring.is_finite():
2631
+ # The group of n-th roots of unity in the base ring is
2632
+ # finite, and hence this Dirichlet group is finite too.
2633
+ # In particular, it is finitely generated; the added
2634
+ # FinitelyGenerated() here means that the group has a
2635
+ # distinguished set of generators.
2636
+ category = category.Finite().FinitelyGenerated()
2637
+ Parent.__init__(self, base_ring, category=category)
2638
+ self._zeta = zeta
2639
+ self._zeta_order = zeta_order
2640
+ self._modulus = modulus
2641
+ self._integers = IntegerModRing(modulus)
2642
+
2643
+ @property
2644
+ def _module(self):
2645
+ """
2646
+ Return the free module used to represent Dirichlet characters.
2647
+
2648
+ TESTS::
2649
+
2650
+ sage: DirichletGroup(12)._module
2651
+ Vector space of dimension 2 over Ring of integers modulo 2
2652
+ """
2653
+ return FreeModule(IntegerModRing(self.zeta_order()),
2654
+ len(self.unit_gens()))
2655
+
2656
+ @property
2657
+ def _zeta_powers(self):
2658
+ """
2659
+ Return a list of powers of the distinguished root of unity.
2660
+
2661
+ TESTS::
2662
+
2663
+ sage: DirichletGroup(5)._zeta_powers
2664
+ [1, zeta4, -1, -zeta4]
2665
+ """
2666
+ R = self.base_ring()
2667
+ a = R.one()
2668
+ w = [a]
2669
+ zeta = self.zeta()
2670
+ zeta_order = self.zeta_order()
2671
+ if isinstance(R, sage.rings.abc.ComplexField):
2672
+ for i in range(1, zeta_order):
2673
+ a = a * zeta
2674
+ a._set_multiplicative_order(zeta_order / gcd(zeta_order, i))
2675
+ w.append(a)
2676
+ else:
2677
+ for i in range(1, zeta_order):
2678
+ a = a * zeta
2679
+ w.append(a)
2680
+ return w
2681
+
2682
+ @property
2683
+ def _zeta_dlog(self) -> dict:
2684
+ """
2685
+ Return a dictionary that can be used to compute discrete
2686
+ logarithms in the value group of this Dirichlet group.
2687
+
2688
+ TESTS::
2689
+
2690
+ sage: DirichletGroup(5)._zeta_dlog
2691
+ {-1: 2, -zeta4: 3, zeta4: 1, 1: 0}
2692
+ """
2693
+ return {z: i for i, z in enumerate(self._zeta_powers)}
2694
+
2695
+ def change_ring(self, R, zeta=None, zeta_order=None):
2696
+ """
2697
+ Return the base extension of ``self`` to ``R``.
2698
+
2699
+ INPUT:
2700
+
2701
+ - ``R`` -- either a ring admitting a conversion map from the
2702
+ base ring of ``self``, or a ring homomorphism with the base
2703
+ ring of ``self`` as its domain
2704
+
2705
+ - ``zeta`` -- (optional) root of unity in ``R``
2706
+
2707
+ - ``zeta_order`` -- (optional) order of ``zeta``
2708
+
2709
+ EXAMPLES::
2710
+
2711
+ sage: G = DirichletGroup(7,QQ); G
2712
+ Group of Dirichlet characters modulo 7 with values in Rational Field
2713
+ sage: G.change_ring(CyclotomicField(6)) # needs sage.rings.number_field
2714
+ Group of Dirichlet characters modulo 7 with values in
2715
+ Cyclotomic Field of order 6 and degree 2
2716
+
2717
+ TESTS:
2718
+
2719
+ We test the case where `R` is a map (:issue:`18072`)::
2720
+
2721
+ sage: # needs sage.rings.number_field
2722
+ sage: K.<i> = QuadraticField(-1)
2723
+ sage: f = K.complex_embeddings()[0]
2724
+ sage: D = DirichletGroup(5, K)
2725
+ sage: D.change_ring(f)
2726
+ Group of Dirichlet characters modulo 5 with values in
2727
+ Complex Field with 53 bits of precision
2728
+ """
2729
+ if zeta is None and self._zeta is not None:
2730
+ # A root of unity was explicitly given; we use it over the
2731
+ # new base ring as well.
2732
+ zeta = self._zeta
2733
+ if zeta_order is None:
2734
+ # We reuse _zeta_order if we know that it stays the
2735
+ # same; otherwise it will be recomputed as the order
2736
+ # of R(zeta) by the DirichletGroup factory.
2737
+ p = R.characteristic()
2738
+ if p == 0 or p.gcd(self._zeta_order) == 1:
2739
+ zeta_order = self._zeta_order
2740
+ else:
2741
+ # No root of unity specified; use the same zeta_order
2742
+ # (which may still be None).
2743
+ zeta_order = self._zeta_order
2744
+ # Map zeta to the new parent
2745
+ if zeta is not None:
2746
+ zeta = R(zeta)
2747
+ if isinstance(R, Map):
2748
+ R = R.codomain()
2749
+ return DirichletGroup(self.modulus(), R,
2750
+ zeta=zeta,
2751
+ zeta_order=zeta_order)
2752
+
2753
+ def base_extend(self, R):
2754
+ """
2755
+ Return the base extension of ``self`` to ``R``.
2756
+
2757
+ INPUT:
2758
+
2759
+ - ``R`` -- either a ring admitting a *coercion* map from the
2760
+ base ring of ``self``, or a ring homomorphism with the base
2761
+ ring of ``self`` as its domain
2762
+
2763
+ EXAMPLES::
2764
+
2765
+ sage: G = DirichletGroup(7,QQ); G
2766
+ Group of Dirichlet characters modulo 7 with values in Rational Field
2767
+ sage: H = G.base_extend(CyclotomicField(6)); H
2768
+ Group of Dirichlet characters modulo 7 with values in Cyclotomic Field of order 6 and degree 2
2769
+
2770
+ Note that the root of unity can change::
2771
+
2772
+ sage: H.zeta()
2773
+ zeta6
2774
+
2775
+ This method (in contrast to :meth:`change_ring`) requires a
2776
+ coercion map to exist::
2777
+
2778
+ sage: G.base_extend(ZZ)
2779
+ Traceback (most recent call last):
2780
+ ...
2781
+ TypeError: no coercion map from Rational Field to Integer Ring is defined
2782
+
2783
+ Base-extended Dirichlet groups do not silently get roots of
2784
+ unity with smaller order than expected (:issue:`6018`)::
2785
+
2786
+ sage: G = DirichletGroup(10, QQ).base_extend(CyclotomicField(4))
2787
+ sage: H = DirichletGroup(10, CyclotomicField(4))
2788
+ sage: G is H
2789
+ True
2790
+
2791
+ sage: G3 = DirichletGroup(31, CyclotomicField(3))
2792
+ sage: G5 = DirichletGroup(31, CyclotomicField(5))
2793
+ sage: K30 = CyclotomicField(30)
2794
+ sage: G3.gen(0).base_extend(K30) * G5.gen(0).base_extend(K30)
2795
+ Dirichlet character modulo 31 of conductor 31 mapping 3 |--> -zeta30^7 + zeta30^5 + zeta30^4 + zeta30^3 - zeta30 - 1
2796
+
2797
+ When a root of unity is specified, base extension still works
2798
+ if the new base ring is not an integral domain::
2799
+
2800
+ sage: f = DirichletGroup(17, ZZ, zeta=-1).0
2801
+ sage: g = f.base_extend(Integers(15))
2802
+ sage: g(3)
2803
+ 14
2804
+ sage: g.parent().zeta()
2805
+ 14
2806
+ """
2807
+ if not (isinstance(R, Map) or
2808
+ R.has_coerce_map_from(self.base_ring())):
2809
+ raise TypeError("no coercion map from %s to %s is defined"
2810
+ % (self.base_ring(), R))
2811
+ return self.change_ring(R)
2812
+
2813
+ def _element_constructor_(self, x):
2814
+ """
2815
+ Construct a Dirichlet character from `x`.
2816
+
2817
+ EXAMPLES::
2818
+
2819
+ sage: G = DirichletGroup(13)
2820
+ sage: K = G.base_ring()
2821
+ sage: G(1)
2822
+ Dirichlet character modulo 13 of conductor 1 mapping 2 |--> 1
2823
+ sage: G([-1])
2824
+ Dirichlet character modulo 13 of conductor 13 mapping 2 |--> -1
2825
+ sage: G([K.0])
2826
+ Dirichlet character modulo 13 of conductor 13 mapping 2 |--> zeta12
2827
+ sage: G(0)
2828
+ Traceback (most recent call last):
2829
+ ...
2830
+ TypeError: cannot convert 0 to an element of Group of Dirichlet characters modulo 13 with values in Cyclotomic Field of order 12 and degree 4
2831
+
2832
+ sage: G = DirichletGroup(6)
2833
+ sage: G(DirichletGroup(3).0)
2834
+ Dirichlet character modulo 6 of conductor 3 mapping 5 |--> -1
2835
+ sage: G(DirichletGroup(15).0)
2836
+ Dirichlet character modulo 6 of conductor 3 mapping 5 |--> -1
2837
+ sage: G(DirichletGroup(15).1)
2838
+ Traceback (most recent call last):
2839
+ ...
2840
+ TypeError: conductor must divide modulus
2841
+ sage: H = DirichletGroup(16, QQ); H(DirichletGroup(16).1)
2842
+ Traceback (most recent call last):
2843
+ ...
2844
+ TypeError: Unable to coerce zeta4 to a rational
2845
+ """
2846
+ R = self.base_ring()
2847
+ try:
2848
+ if x == R.one():
2849
+ x = [R.one()] * len(self.unit_gens())
2850
+ except (TypeError, ValueError, ArithmeticError):
2851
+ pass
2852
+ if isinstance(x, list): # list of values on each unit generator
2853
+ return self.element_class(self, x)
2854
+ elif not isinstance(x, DirichletCharacter):
2855
+ raise TypeError("cannot convert %s to an element of %s" % (x, self))
2856
+ elif not x.conductor().divides(self.modulus()):
2857
+ raise TypeError("conductor must divide modulus")
2858
+ a = []
2859
+ for u in self.unit_gens():
2860
+ v = u.lift()
2861
+ # have to do this, since e.g., unit gens mod 11 are not units mod 22.
2862
+ while x.modulus().gcd(v) != 1:
2863
+ v += self.modulus()
2864
+ a.append(R(x(v)))
2865
+ return self.element_class(self, a)
2866
+
2867
+ def _coerce_map_from_(self, X) -> bool:
2868
+ """
2869
+ Decide whether there is a coercion map from `X`.
2870
+
2871
+ There is conversion between Dirichlet groups of different
2872
+ moduli, but no coercion. This implies that Dirichlet
2873
+ characters of different moduli do not compare as equal.
2874
+
2875
+ TESTS::
2876
+
2877
+ sage: trivial_character(6) == trivial_character(3) # indirect doctest
2878
+ False
2879
+ sage: trivial_character(3) == trivial_character(9)
2880
+ False
2881
+ sage: trivial_character(3) == DirichletGroup(3, QQ).0^2
2882
+ True
2883
+ """
2884
+ return (isinstance(X, DirichletGroup_class) and
2885
+ self.modulus() == X.modulus() and
2886
+ self.base_ring().has_coerce_map_from(X.base_ring()) and
2887
+ (self._zeta is None or
2888
+ (X._zeta is not None and
2889
+ self.base_ring()(X._zeta) in self._zeta_powers)))
2890
+
2891
+ def __len__(self):
2892
+ """
2893
+ Return the number of elements of this Dirichlet group.
2894
+
2895
+ This is the same as self.order().
2896
+
2897
+ EXAMPLES::
2898
+
2899
+ sage: len(DirichletGroup(20))
2900
+ 8
2901
+ sage: len(DirichletGroup(20, QQ))
2902
+ 4
2903
+ sage: len(DirichletGroup(20, GF(5)))
2904
+ 8
2905
+ sage: len(DirichletGroup(20, GF(2)))
2906
+ 1
2907
+ sage: len(DirichletGroup(20, GF(3)))
2908
+ 4
2909
+ """
2910
+ return self.order()
2911
+
2912
+ def _repr_(self) -> str:
2913
+ """
2914
+ Return a print representation of this group, which can be renamed.
2915
+
2916
+ EXAMPLES::
2917
+
2918
+ sage: G = DirichletGroup(11)
2919
+ sage: repr(G) # indirect doctest
2920
+ 'Group of Dirichlet characters modulo 11 with values in Cyclotomic Field of order 10 and degree 4'
2921
+ sage: G.rename('Dir(11)')
2922
+ sage: G
2923
+ Dir(11)
2924
+ """
2925
+ s = "Group of Dirichlet characters modulo %s with values in " % self.modulus()
2926
+ if self._zeta is not None:
2927
+ s += "the group of order %s generated by %s in " % (self._zeta_order, self._zeta)
2928
+ s += str(self.base_ring())
2929
+ return s
2930
+
2931
+ @cached_method
2932
+ def decomposition(self) -> list:
2933
+ r"""
2934
+ Return the Dirichlet groups of prime power modulus corresponding
2935
+ to primes dividing modulus.
2936
+
2937
+ (Note that if the modulus is 2 mod 4, there will be a "factor" of
2938
+ `(\ZZ/2\ZZ)^*`, which is the trivial group.)
2939
+
2940
+ EXAMPLES::
2941
+
2942
+ sage: DirichletGroup(20).decomposition()
2943
+ [Group of Dirichlet characters modulo 4 with values in Cyclotomic Field of order 4 and degree 2,
2944
+ Group of Dirichlet characters modulo 5 with values in Cyclotomic Field of order 4 and degree 2]
2945
+ sage: DirichletGroup(20,GF(5)).decomposition()
2946
+ [Group of Dirichlet characters modulo 4 with values in Finite Field of size 5,
2947
+ Group of Dirichlet characters modulo 5 with values in Finite Field of size 5]
2948
+ """
2949
+ R = self.base_ring()
2950
+ return Sequence([DirichletGroup(p**r, R)
2951
+ for p, r in factor(self.modulus())],
2952
+ cr=True,
2953
+ universe=Objects())
2954
+
2955
+ def exponent(self):
2956
+ """
2957
+ Return the exponent of this group.
2958
+
2959
+ EXAMPLES::
2960
+
2961
+ sage: DirichletGroup(20).exponent()
2962
+ 4
2963
+ sage: DirichletGroup(20,GF(3)).exponent()
2964
+ 2
2965
+ sage: DirichletGroup(20,GF(2)).exponent()
2966
+ 1
2967
+ sage: DirichletGroup(37).exponent()
2968
+ 36
2969
+ """
2970
+ return self.zeta_order()
2971
+
2972
+ @cached_method
2973
+ def _automorphisms(self):
2974
+ """
2975
+ Compute the automorphisms of ``self``. These are always given by raising to
2976
+ a power, so the return value is a list of integers.
2977
+
2978
+ At present this is only implemented if the base ring has characteristic 0 or a prime.
2979
+
2980
+ EXAMPLES::
2981
+
2982
+ sage: DirichletGroup(17)._automorphisms()
2983
+ [1, 3, 5, 7, 9, 11, 13, 15]
2984
+ sage: DirichletGroup(17, GF(11^4, 'a'))._automorphisms()
2985
+ [1, 11, 121, 1331]
2986
+ sage: DirichletGroup(17, Integers(6), zeta=Integers(6)(5))._automorphisms()
2987
+ Traceback (most recent call last):
2988
+ ...
2989
+ NotImplementedError: Automorphisms for finite non-field base rings not implemented
2990
+ sage: DirichletGroup(17, Integers(9), zeta=Integers(9)(2))._automorphisms()
2991
+ Traceback (most recent call last):
2992
+ ...
2993
+ NotImplementedError: Automorphisms for finite non-field base rings not implemented
2994
+ """
2995
+ n = self.zeta_order()
2996
+ R = self.base_ring()
2997
+ p = R.characteristic()
2998
+ if p == 0:
2999
+ Auts = [e for e in range(1, n) if gcd(e, n) == 1]
3000
+ else:
3001
+ if not Integer(p).is_prime():
3002
+ raise NotImplementedError("Automorphisms for finite non-field base rings not implemented")
3003
+ # The automorphisms in characteristic p are
3004
+ # k-th powering for
3005
+ # k = 1, p, p^2, ..., p^(r-1),
3006
+ # where p^r = 1 (mod n), so r is the mult order of p modulo n.
3007
+ r = IntegerModRing(n)(p).multiplicative_order()
3008
+ Auts = [p**m for m in range(r)]
3009
+ return Auts
3010
+
3011
+ def galois_orbits(self, v=None, reps_only=False, sort=True, check=True):
3012
+ """
3013
+ Return a list of the Galois orbits of Dirichlet characters in ``self``,
3014
+ or in ``v`` if ``v`` is not ``None``.
3015
+
3016
+ INPUT:
3017
+
3018
+ - ``v`` -- (optional) list of elements of ``self``
3019
+
3020
+ - ``reps_only`` -- (optional: default ``False``) if ``True``
3021
+ only returns representatives for the orbits
3022
+
3023
+ - ``sort`` -- (optional: default ``True``) whether to sort
3024
+ the list of orbits and the orbits themselves (slightly faster if
3025
+ ``False``).
3026
+
3027
+ - ``check`` -- boolean (default: ``True``); whether or not
3028
+ to explicitly coerce each element of ``v`` into ``self``
3029
+
3030
+ The Galois group is the absolute Galois group of the prime subfield
3031
+ of Frac(R). If R is not a domain, an error will be raised.
3032
+
3033
+ EXAMPLES::
3034
+
3035
+ sage: DirichletGroup(20).galois_orbits()
3036
+ [[Dirichlet character modulo 20 of conductor 20 mapping ...]]
3037
+ sage: DirichletGroup(17, Integers(6), zeta=Integers(6)(5)).galois_orbits()
3038
+ Traceback (most recent call last):
3039
+ ...
3040
+ TypeError: Galois orbits only defined if base ring is an integral domain
3041
+ sage: DirichletGroup(17, Integers(9), zeta=Integers(9)(2)).galois_orbits()
3042
+ Traceback (most recent call last):
3043
+ ...
3044
+ TypeError: Galois orbits only defined if base ring is an integral domain
3045
+ """
3046
+ if v is None:
3047
+ v = self.list()
3048
+ else:
3049
+ if check:
3050
+ v = [self(x) for x in v]
3051
+
3052
+ G = []
3053
+ seen_so_far = set()
3054
+ for x in v:
3055
+ z = x.element()
3056
+ e = tuple(z) # change when there are immutable vectors (and below)
3057
+ if e in seen_so_far:
3058
+ continue
3059
+ orbit = x.galois_orbit(sort=sort)
3060
+ if reps_only:
3061
+ G.append(x)
3062
+ else:
3063
+ G.append(orbit)
3064
+ for z in orbit:
3065
+ seen_so_far.add(tuple(z.element()))
3066
+ G = Sequence(G, cr=True)
3067
+ if sort:
3068
+ G.sort()
3069
+ return G
3070
+
3071
+ def gen(self, n=0):
3072
+ """
3073
+ Return the `n`-th generator of ``self``.
3074
+
3075
+ EXAMPLES::
3076
+
3077
+ sage: G = DirichletGroup(20)
3078
+ sage: G.gen(0)
3079
+ Dirichlet character modulo 20 of conductor 4 mapping 11 |--> -1, 17 |--> 1
3080
+ sage: G.gen(1)
3081
+ Dirichlet character modulo 20 of conductor 5 mapping 11 |--> 1, 17 |--> zeta4
3082
+ sage: G.gen(2)
3083
+ Traceback (most recent call last):
3084
+ ...
3085
+ IndexError: n(=2) must be between 0 and 1
3086
+
3087
+ ::
3088
+
3089
+ sage: G.gen(-1)
3090
+ Traceback (most recent call last):
3091
+ ...
3092
+ IndexError: n(=-1) must be between 0 and 1
3093
+ """
3094
+ n = int(n)
3095
+ g = self.gens()
3096
+ if n < 0 or n >= len(g):
3097
+ raise IndexError("n(=%s) must be between 0 and %s" % (n, len(g) - 1))
3098
+ return g[n]
3099
+
3100
+ @cached_method
3101
+ def gens(self) -> tuple:
3102
+ """
3103
+ Return generators of ``self``.
3104
+
3105
+ EXAMPLES::
3106
+
3107
+ sage: G = DirichletGroup(20)
3108
+ sage: G.gens()
3109
+ (Dirichlet character modulo 20 of conductor 4 mapping 11 |--> -1, 17 |--> 1, Dirichlet character modulo 20 of conductor 5 mapping 11 |--> 1, 17 |--> zeta4)
3110
+ """
3111
+ g = []
3112
+ ord = self.zeta_order()
3113
+ M = self._module
3114
+ zero = M.zero()
3115
+ orders = self.integers_mod().unit_group().gens_orders()
3116
+ for i in range(len(self.unit_gens())):
3117
+ z = zero.__copy__()
3118
+ z[i] = ord // gcd(ord, orders[i])
3119
+ g.append(self.element_class(self, z, check=False))
3120
+ return tuple(g)
3121
+
3122
+ def integers_mod(self):
3123
+ r"""
3124
+ Return the group of integers `\ZZ/N\ZZ`
3125
+ where `N` is the modulus of ``self``.
3126
+
3127
+ EXAMPLES::
3128
+
3129
+ sage: G = DirichletGroup(20)
3130
+ sage: G.integers_mod()
3131
+ Ring of integers modulo 20
3132
+ """
3133
+ return self._integers
3134
+
3135
+ __iter__ = multiplicative_iterator
3136
+
3137
+ def list(self) -> list:
3138
+ """
3139
+ Return a list of the Dirichlet characters in this group.
3140
+
3141
+ EXAMPLES::
3142
+
3143
+ sage: DirichletGroup(5).list()
3144
+ [Dirichlet character modulo 5 of conductor 1 mapping 2 |--> 1,
3145
+ Dirichlet character modulo 5 of conductor 5 mapping 2 |--> zeta4,
3146
+ Dirichlet character modulo 5 of conductor 5 mapping 2 |--> -1,
3147
+ Dirichlet character modulo 5 of conductor 5 mapping 2 |--> -zeta4]
3148
+ """
3149
+ return self._list_from_iterator()
3150
+
3151
+ def modulus(self):
3152
+ """
3153
+ Return the modulus of ``self``.
3154
+
3155
+ EXAMPLES::
3156
+
3157
+ sage: G = DirichletGroup(20)
3158
+ sage: G.modulus()
3159
+ 20
3160
+ """
3161
+ return self._modulus
3162
+
3163
+ def ngens(self) -> int:
3164
+ """
3165
+ Return the number of generators of ``self``.
3166
+
3167
+ EXAMPLES::
3168
+
3169
+ sage: G = DirichletGroup(20)
3170
+ sage: G.ngens()
3171
+ 2
3172
+ """
3173
+ return len(self.gens())
3174
+
3175
+ @cached_method
3176
+ def order(self):
3177
+ """
3178
+ Return the number of elements of ``self``.
3179
+
3180
+ This is the same as len(self).
3181
+
3182
+ EXAMPLES::
3183
+
3184
+ sage: DirichletGroup(20).order()
3185
+ 8
3186
+ sage: DirichletGroup(37).order()
3187
+ 36
3188
+ """
3189
+ ord = Integer(1)
3190
+ for g in self.gens():
3191
+ ord *= int(g.order())
3192
+ return ord
3193
+
3194
+ def random_element(self):
3195
+ """
3196
+ Return a random element of ``self``.
3197
+
3198
+ The element is computed by multiplying a random power of each
3199
+ generator together, where the power is between 0 and the order of
3200
+ the generator minus 1, inclusive.
3201
+
3202
+ EXAMPLES::
3203
+
3204
+ sage: D = DirichletGroup(37)
3205
+ sage: g = D.random_element()
3206
+ sage: g.parent() is D
3207
+ True
3208
+ sage: g**36
3209
+ Dirichlet character modulo 37 of conductor 1 mapping 2 |--> 1
3210
+ sage: S = set(D.random_element().conductor() for _ in range(100))
3211
+ sage: while S != {1, 37}:
3212
+ ....: S.add(D.random_element().conductor())
3213
+
3214
+ sage: D = DirichletGroup(20)
3215
+ sage: g = D.random_element()
3216
+ sage: g.parent() is D
3217
+ True
3218
+ sage: g**4
3219
+ Dirichlet character modulo 20 of conductor 1 mapping 11 |--> 1, 17 |--> 1
3220
+ sage: S = set(D.random_element().conductor() for _ in range(100))
3221
+ sage: while S != {1, 4, 5, 20}:
3222
+ ....: S.add(D.random_element().conductor())
3223
+
3224
+ sage: D = DirichletGroup(60)
3225
+ sage: g = D.random_element()
3226
+ sage: g.parent() is D
3227
+ True
3228
+ sage: g**4
3229
+ Dirichlet character modulo 60 of conductor 1 mapping 31 |--> 1, 41 |--> 1, 37 |--> 1
3230
+ sage: S = set(D.random_element().conductor() for _ in range(100))
3231
+ sage: while S != {1, 3, 4, 5, 12, 15, 20, 60}:
3232
+ ....: S.add(D.random_element().conductor())
3233
+ """
3234
+ e = self(1)
3235
+ for i in range(self.ngens()):
3236
+ g = self.gen(i)
3237
+ n = random.randrange(g.order())
3238
+ e *= g**n
3239
+ return e
3240
+
3241
+ def unit_gens(self) -> tuple:
3242
+ r"""
3243
+ Return the minimal generators for the units of
3244
+ `(\ZZ/N\ZZ)^*`, where `N` is the
3245
+ modulus of ``self``.
3246
+
3247
+ EXAMPLES::
3248
+
3249
+ sage: DirichletGroup(37).unit_gens()
3250
+ (2,)
3251
+ sage: DirichletGroup(20).unit_gens()
3252
+ (11, 17)
3253
+ sage: DirichletGroup(60).unit_gens()
3254
+ (31, 41, 37)
3255
+ sage: DirichletGroup(20,QQ).unit_gens()
3256
+ (11, 17)
3257
+ """
3258
+ return self._integers.unit_gens()
3259
+
3260
+ @cached_method
3261
+ def zeta(self):
3262
+ """
3263
+ Return the chosen root of unity in the base ring.
3264
+
3265
+ EXAMPLES::
3266
+
3267
+ sage: DirichletGroup(37).zeta()
3268
+ zeta36
3269
+ sage: DirichletGroup(20).zeta()
3270
+ zeta4
3271
+ sage: DirichletGroup(60).zeta()
3272
+ zeta4
3273
+ sage: DirichletGroup(60,QQ).zeta()
3274
+ -1
3275
+ sage: DirichletGroup(60, GF(25,'a')).zeta()
3276
+ 2
3277
+ """
3278
+ zeta = self._zeta
3279
+ if zeta is None:
3280
+ R = self.base_ring()
3281
+ e = self._integers.unit_group_exponent()
3282
+ for d in reversed(e.divisors()):
3283
+ try:
3284
+ zeta = R.zeta(d)
3285
+ break
3286
+ except ValueError:
3287
+ pass
3288
+ self.zeta_order.set_cache(d)
3289
+ return zeta
3290
+
3291
+ @cached_method
3292
+ def zeta_order(self):
3293
+ """
3294
+ Return the order of the chosen root of unity in the base ring.
3295
+
3296
+ EXAMPLES::
3297
+
3298
+ sage: DirichletGroup(20).zeta_order()
3299
+ 4
3300
+ sage: DirichletGroup(60).zeta_order()
3301
+ 4
3302
+ sage: DirichletGroup(60, GF(25,'a')).zeta_order()
3303
+ 4
3304
+ sage: DirichletGroup(19).zeta_order()
3305
+ 18
3306
+ """
3307
+ order = self._zeta_order
3308
+ if order is None:
3309
+ order = self.zeta().multiplicative_order()
3310
+ return order