passagemath-schemes 10.6.40__cp314-cp314-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.

Potentially problematic release.


This version of passagemath-schemes might be problematic. Click here for more details.

Files changed (314) hide show
  1. passagemath_schemes/.dylibs/libflint.22.0.dylib +0 -0
  2. passagemath_schemes/.dylibs/libgmp.10.dylib +0 -0
  3. passagemath_schemes/.dylibs/libgmpxx.4.dylib +0 -0
  4. passagemath_schemes/.dylibs/libmpfr.6.dylib +0 -0
  5. passagemath_schemes/__init__.py +3 -0
  6. passagemath_schemes-10.6.40.dist-info/METADATA +204 -0
  7. passagemath_schemes-10.6.40.dist-info/METADATA.bak +205 -0
  8. passagemath_schemes-10.6.40.dist-info/RECORD +314 -0
  9. passagemath_schemes-10.6.40.dist-info/WHEEL +6 -0
  10. passagemath_schemes-10.6.40.dist-info/top_level.txt +3 -0
  11. sage/all__sagemath_schemes.py +23 -0
  12. sage/databases/all__sagemath_schemes.py +7 -0
  13. sage/databases/cremona.py +1723 -0
  14. sage/dynamics/all__sagemath_schemes.py +2 -0
  15. sage/dynamics/arithmetic_dynamics/affine_ds.py +1083 -0
  16. sage/dynamics/arithmetic_dynamics/all.py +14 -0
  17. sage/dynamics/arithmetic_dynamics/berkovich_ds.py +1101 -0
  18. sage/dynamics/arithmetic_dynamics/dynamical_semigroup.py +1543 -0
  19. sage/dynamics/arithmetic_dynamics/endPN_automorphism_group.py +2426 -0
  20. sage/dynamics/arithmetic_dynamics/endPN_minimal_model.py +1169 -0
  21. sage/dynamics/arithmetic_dynamics/generic_ds.py +663 -0
  22. sage/dynamics/arithmetic_dynamics/product_projective_ds.py +339 -0
  23. sage/dynamics/arithmetic_dynamics/projective_ds.py +9558 -0
  24. sage/dynamics/arithmetic_dynamics/projective_ds_helper.cpython-314-darwin.so +0 -0
  25. sage/dynamics/arithmetic_dynamics/projective_ds_helper.pyx +301 -0
  26. sage/dynamics/arithmetic_dynamics/wehlerK3.py +2576 -0
  27. sage/lfunctions/all.py +18 -0
  28. sage/lfunctions/dokchitser.py +745 -0
  29. sage/lfunctions/pari.py +818 -0
  30. sage/lfunctions/zero_sums.cpython-314-darwin.so +0 -0
  31. sage/lfunctions/zero_sums.pyx +1847 -0
  32. sage/modular/abvar/abvar.py +5135 -0
  33. sage/modular/abvar/abvar_ambient_jacobian.py +413 -0
  34. sage/modular/abvar/abvar_newform.py +244 -0
  35. sage/modular/abvar/all.py +8 -0
  36. sage/modular/abvar/constructor.py +186 -0
  37. sage/modular/abvar/cuspidal_subgroup.py +371 -0
  38. sage/modular/abvar/finite_subgroup.py +896 -0
  39. sage/modular/abvar/homology.py +720 -0
  40. sage/modular/abvar/homspace.py +998 -0
  41. sage/modular/abvar/lseries.py +415 -0
  42. sage/modular/abvar/morphism.py +935 -0
  43. sage/modular/abvar/torsion_point.py +274 -0
  44. sage/modular/abvar/torsion_subgroup.py +740 -0
  45. sage/modular/all.py +43 -0
  46. sage/modular/arithgroup/all.py +20 -0
  47. sage/modular/arithgroup/arithgroup_element.cpython-314-darwin.so +0 -0
  48. sage/modular/arithgroup/arithgroup_element.pyx +474 -0
  49. sage/modular/arithgroup/arithgroup_generic.py +1402 -0
  50. sage/modular/arithgroup/arithgroup_perm.py +2692 -0
  51. sage/modular/arithgroup/congroup.cpython-314-darwin.so +0 -0
  52. sage/modular/arithgroup/congroup.pyx +334 -0
  53. sage/modular/arithgroup/congroup_gamma.py +363 -0
  54. sage/modular/arithgroup/congroup_gamma0.py +692 -0
  55. sage/modular/arithgroup/congroup_gamma1.py +653 -0
  56. sage/modular/arithgroup/congroup_gammaH.py +1469 -0
  57. sage/modular/arithgroup/congroup_generic.py +628 -0
  58. sage/modular/arithgroup/congroup_sl2z.py +267 -0
  59. sage/modular/arithgroup/farey_symbol.cpython-314-darwin.so +0 -0
  60. sage/modular/arithgroup/farey_symbol.pyx +1066 -0
  61. sage/modular/arithgroup/tests.py +418 -0
  62. sage/modular/btquotients/all.py +4 -0
  63. sage/modular/btquotients/btquotient.py +3753 -0
  64. sage/modular/btquotients/pautomorphicform.py +2570 -0
  65. sage/modular/buzzard.py +100 -0
  66. sage/modular/congroup.py +29 -0
  67. sage/modular/congroup_element.py +13 -0
  68. sage/modular/cusps.py +1109 -0
  69. sage/modular/cusps_nf.py +1270 -0
  70. sage/modular/dims.py +569 -0
  71. sage/modular/dirichlet.py +3310 -0
  72. sage/modular/drinfeld_modform/all.py +2 -0
  73. sage/modular/drinfeld_modform/element.py +446 -0
  74. sage/modular/drinfeld_modform/ring.py +773 -0
  75. sage/modular/drinfeld_modform/tutorial.py +236 -0
  76. sage/modular/etaproducts.py +1065 -0
  77. sage/modular/hecke/algebra.py +746 -0
  78. sage/modular/hecke/all.py +20 -0
  79. sage/modular/hecke/ambient_module.py +1019 -0
  80. sage/modular/hecke/degenmap.py +119 -0
  81. sage/modular/hecke/element.py +325 -0
  82. sage/modular/hecke/hecke_operator.py +780 -0
  83. sage/modular/hecke/homspace.py +206 -0
  84. sage/modular/hecke/module.py +1767 -0
  85. sage/modular/hecke/morphism.py +174 -0
  86. sage/modular/hecke/submodule.py +989 -0
  87. sage/modular/hypergeometric_misc.cpython-314-darwin.so +0 -0
  88. sage/modular/hypergeometric_misc.pxd +4 -0
  89. sage/modular/hypergeometric_misc.pyx +166 -0
  90. sage/modular/hypergeometric_motive.py +2017 -0
  91. sage/modular/local_comp/all.py +2 -0
  92. sage/modular/local_comp/liftings.py +292 -0
  93. sage/modular/local_comp/local_comp.py +1071 -0
  94. sage/modular/local_comp/smoothchar.py +1825 -0
  95. sage/modular/local_comp/type_space.py +748 -0
  96. sage/modular/modform/all.py +30 -0
  97. sage/modular/modform/ambient.py +815 -0
  98. sage/modular/modform/ambient_R.py +177 -0
  99. sage/modular/modform/ambient_eps.py +306 -0
  100. sage/modular/modform/ambient_g0.py +124 -0
  101. sage/modular/modform/ambient_g1.py +204 -0
  102. sage/modular/modform/constructor.py +545 -0
  103. sage/modular/modform/cuspidal_submodule.py +708 -0
  104. sage/modular/modform/defaults.py +14 -0
  105. sage/modular/modform/eis_series.py +505 -0
  106. sage/modular/modform/eisenstein_submodule.py +663 -0
  107. sage/modular/modform/element.py +4131 -0
  108. sage/modular/modform/find_generators.py +59 -0
  109. sage/modular/modform/half_integral.py +154 -0
  110. sage/modular/modform/hecke_operator_on_qexp.py +247 -0
  111. sage/modular/modform/j_invariant.py +47 -0
  112. sage/modular/modform/l_series_gross_zagier.py +133 -0
  113. sage/modular/modform/l_series_gross_zagier_coeffs.cpython-314-darwin.so +0 -0
  114. sage/modular/modform/l_series_gross_zagier_coeffs.pyx +177 -0
  115. sage/modular/modform/notes.py +45 -0
  116. sage/modular/modform/numerical.py +514 -0
  117. sage/modular/modform/periods.py +14 -0
  118. sage/modular/modform/ring.py +1257 -0
  119. sage/modular/modform/space.py +1860 -0
  120. sage/modular/modform/submodule.py +118 -0
  121. sage/modular/modform/tests.py +64 -0
  122. sage/modular/modform/theta.py +110 -0
  123. sage/modular/modform/vm_basis.py +381 -0
  124. sage/modular/modform/weight1.py +220 -0
  125. sage/modular/modform_hecketriangle/abstract_ring.py +1932 -0
  126. sage/modular/modform_hecketriangle/abstract_space.py +2528 -0
  127. sage/modular/modform_hecketriangle/all.py +30 -0
  128. sage/modular/modform_hecketriangle/analytic_type.py +590 -0
  129. sage/modular/modform_hecketriangle/constructor.py +416 -0
  130. sage/modular/modform_hecketriangle/element.py +351 -0
  131. sage/modular/modform_hecketriangle/functors.py +752 -0
  132. sage/modular/modform_hecketriangle/graded_ring.py +541 -0
  133. sage/modular/modform_hecketriangle/graded_ring_element.py +2225 -0
  134. sage/modular/modform_hecketriangle/hecke_triangle_group_element.py +3352 -0
  135. sage/modular/modform_hecketriangle/hecke_triangle_groups.py +1432 -0
  136. sage/modular/modform_hecketriangle/readme.py +1214 -0
  137. sage/modular/modform_hecketriangle/series_constructor.py +580 -0
  138. sage/modular/modform_hecketriangle/space.py +1037 -0
  139. sage/modular/modform_hecketriangle/subspace.py +423 -0
  140. sage/modular/modsym/all.py +17 -0
  141. sage/modular/modsym/ambient.py +3846 -0
  142. sage/modular/modsym/boundary.py +1420 -0
  143. sage/modular/modsym/element.py +336 -0
  144. sage/modular/modsym/g1list.py +178 -0
  145. sage/modular/modsym/ghlist.py +182 -0
  146. sage/modular/modsym/hecke_operator.py +73 -0
  147. sage/modular/modsym/manin_symbol.cpython-314-darwin.so +0 -0
  148. sage/modular/modsym/manin_symbol.pxd +5 -0
  149. sage/modular/modsym/manin_symbol.pyx +497 -0
  150. sage/modular/modsym/manin_symbol_list.py +1295 -0
  151. sage/modular/modsym/modsym.py +400 -0
  152. sage/modular/modsym/modular_symbols.py +384 -0
  153. sage/modular/modsym/p1list.cpython-314-darwin.so +0 -0
  154. sage/modular/modsym/p1list.pxd +29 -0
  155. sage/modular/modsym/p1list.pyx +1372 -0
  156. sage/modular/modsym/p1list_nf.py +1241 -0
  157. sage/modular/modsym/relation_matrix.py +591 -0
  158. sage/modular/modsym/relation_matrix_pyx.cpython-314-darwin.so +0 -0
  159. sage/modular/modsym/relation_matrix_pyx.pyx +108 -0
  160. sage/modular/modsym/space.py +2468 -0
  161. sage/modular/modsym/subspace.py +455 -0
  162. sage/modular/modsym/tests.py +375 -0
  163. sage/modular/multiple_zeta.py +2632 -0
  164. sage/modular/multiple_zeta_F_algebra.py +786 -0
  165. sage/modular/overconvergent/all.py +6 -0
  166. sage/modular/overconvergent/genus0.py +1878 -0
  167. sage/modular/overconvergent/hecke_series.py +1187 -0
  168. sage/modular/overconvergent/weightspace.py +778 -0
  169. sage/modular/pollack_stevens/all.py +4 -0
  170. sage/modular/pollack_stevens/distributions.py +874 -0
  171. sage/modular/pollack_stevens/fund_domain.py +1572 -0
  172. sage/modular/pollack_stevens/manin_map.py +859 -0
  173. sage/modular/pollack_stevens/modsym.py +1593 -0
  174. sage/modular/pollack_stevens/padic_lseries.py +417 -0
  175. sage/modular/pollack_stevens/sigma0.py +534 -0
  176. sage/modular/pollack_stevens/space.py +1076 -0
  177. sage/modular/quasimodform/all.py +3 -0
  178. sage/modular/quasimodform/element.py +845 -0
  179. sage/modular/quasimodform/ring.py +828 -0
  180. sage/modular/quatalg/all.py +3 -0
  181. sage/modular/quatalg/brandt.py +1642 -0
  182. sage/modular/ssmod/all.py +8 -0
  183. sage/modular/ssmod/ssmod.py +827 -0
  184. sage/rings/all__sagemath_schemes.py +1 -0
  185. sage/rings/polynomial/all__sagemath_schemes.py +1 -0
  186. sage/rings/polynomial/binary_form_reduce.py +585 -0
  187. sage/schemes/all.py +41 -0
  188. sage/schemes/berkovich/all.py +6 -0
  189. sage/schemes/berkovich/berkovich_cp_element.py +2582 -0
  190. sage/schemes/berkovich/berkovich_space.py +748 -0
  191. sage/schemes/curves/affine_curve.py +2928 -0
  192. sage/schemes/curves/all.py +33 -0
  193. sage/schemes/curves/closed_point.py +434 -0
  194. sage/schemes/curves/constructor.py +381 -0
  195. sage/schemes/curves/curve.py +542 -0
  196. sage/schemes/curves/plane_curve_arrangement.py +1283 -0
  197. sage/schemes/curves/point.py +463 -0
  198. sage/schemes/curves/projective_curve.py +3026 -0
  199. sage/schemes/curves/zariski_vankampen.py +1932 -0
  200. sage/schemes/cyclic_covers/all.py +2 -0
  201. sage/schemes/cyclic_covers/charpoly_frobenius.py +320 -0
  202. sage/schemes/cyclic_covers/constructor.py +137 -0
  203. sage/schemes/cyclic_covers/cycliccover_finite_field.py +1309 -0
  204. sage/schemes/cyclic_covers/cycliccover_generic.py +310 -0
  205. sage/schemes/elliptic_curves/BSD.py +1036 -0
  206. sage/schemes/elliptic_curves/Qcurves.py +592 -0
  207. sage/schemes/elliptic_curves/addition_formulas_ring.py +94 -0
  208. sage/schemes/elliptic_curves/all.py +49 -0
  209. sage/schemes/elliptic_curves/cardinality.py +609 -0
  210. sage/schemes/elliptic_curves/cm.py +1102 -0
  211. sage/schemes/elliptic_curves/constructor.py +1552 -0
  212. sage/schemes/elliptic_curves/ec_database.py +175 -0
  213. sage/schemes/elliptic_curves/ell_curve_isogeny.py +3972 -0
  214. sage/schemes/elliptic_curves/ell_egros.py +459 -0
  215. sage/schemes/elliptic_curves/ell_field.py +2836 -0
  216. sage/schemes/elliptic_curves/ell_finite_field.py +3359 -0
  217. sage/schemes/elliptic_curves/ell_generic.py +3760 -0
  218. sage/schemes/elliptic_curves/ell_local_data.py +1207 -0
  219. sage/schemes/elliptic_curves/ell_modular_symbols.py +775 -0
  220. sage/schemes/elliptic_curves/ell_number_field.py +4220 -0
  221. sage/schemes/elliptic_curves/ell_padic_field.py +107 -0
  222. sage/schemes/elliptic_curves/ell_point.py +4787 -0
  223. sage/schemes/elliptic_curves/ell_rational_field.py +7368 -0
  224. sage/schemes/elliptic_curves/ell_tate_curve.py +671 -0
  225. sage/schemes/elliptic_curves/ell_torsion.py +436 -0
  226. sage/schemes/elliptic_curves/ell_wp.py +352 -0
  227. sage/schemes/elliptic_curves/formal_group.py +760 -0
  228. sage/schemes/elliptic_curves/gal_reps.py +1459 -0
  229. sage/schemes/elliptic_curves/gal_reps_number_field.py +1669 -0
  230. sage/schemes/elliptic_curves/gp_simon.py +152 -0
  231. sage/schemes/elliptic_curves/heegner.py +7335 -0
  232. sage/schemes/elliptic_curves/height.py +2109 -0
  233. sage/schemes/elliptic_curves/hom.py +1406 -0
  234. sage/schemes/elliptic_curves/hom_composite.py +934 -0
  235. sage/schemes/elliptic_curves/hom_frobenius.py +522 -0
  236. sage/schemes/elliptic_curves/hom_scalar.py +531 -0
  237. sage/schemes/elliptic_curves/hom_sum.py +682 -0
  238. sage/schemes/elliptic_curves/hom_velusqrt.py +1290 -0
  239. sage/schemes/elliptic_curves/homset.py +271 -0
  240. sage/schemes/elliptic_curves/isogeny_class.py +1521 -0
  241. sage/schemes/elliptic_curves/isogeny_small_degree.py +2797 -0
  242. sage/schemes/elliptic_curves/jacobian.py +237 -0
  243. sage/schemes/elliptic_curves/kodaira_symbol.py +344 -0
  244. sage/schemes/elliptic_curves/kraus.py +1014 -0
  245. sage/schemes/elliptic_curves/lseries_ell.py +943 -0
  246. sage/schemes/elliptic_curves/mod5family.py +105 -0
  247. sage/schemes/elliptic_curves/mod_poly.py +197 -0
  248. sage/schemes/elliptic_curves/mod_sym_num.cpython-314-darwin.so +0 -0
  249. sage/schemes/elliptic_curves/mod_sym_num.pyx +3796 -0
  250. sage/schemes/elliptic_curves/modular_parametrization.py +305 -0
  251. sage/schemes/elliptic_curves/padic_lseries.py +1793 -0
  252. sage/schemes/elliptic_curves/padics.py +1816 -0
  253. sage/schemes/elliptic_curves/period_lattice.py +2234 -0
  254. sage/schemes/elliptic_curves/period_lattice_region.cpython-314-darwin.so +0 -0
  255. sage/schemes/elliptic_curves/period_lattice_region.pyx +722 -0
  256. sage/schemes/elliptic_curves/saturation.py +715 -0
  257. sage/schemes/elliptic_curves/sha_tate.py +1158 -0
  258. sage/schemes/elliptic_curves/weierstrass_morphism.py +1117 -0
  259. sage/schemes/elliptic_curves/weierstrass_transform.py +200 -0
  260. sage/schemes/hyperelliptic_curves/all.py +6 -0
  261. sage/schemes/hyperelliptic_curves/constructor.py +291 -0
  262. sage/schemes/hyperelliptic_curves/hyperelliptic_finite_field.py +1914 -0
  263. sage/schemes/hyperelliptic_curves/hyperelliptic_g2.py +192 -0
  264. sage/schemes/hyperelliptic_curves/hyperelliptic_generic.py +954 -0
  265. sage/schemes/hyperelliptic_curves/hyperelliptic_padic_field.py +1332 -0
  266. sage/schemes/hyperelliptic_curves/hyperelliptic_rational_field.py +84 -0
  267. sage/schemes/hyperelliptic_curves/invariants.py +410 -0
  268. sage/schemes/hyperelliptic_curves/jacobian_endomorphism_utils.py +315 -0
  269. sage/schemes/hyperelliptic_curves/jacobian_g2.py +32 -0
  270. sage/schemes/hyperelliptic_curves/jacobian_generic.py +419 -0
  271. sage/schemes/hyperelliptic_curves/jacobian_homset.py +186 -0
  272. sage/schemes/hyperelliptic_curves/jacobian_morphism.py +875 -0
  273. sage/schemes/hyperelliptic_curves/kummer_surface.py +99 -0
  274. sage/schemes/hyperelliptic_curves/mestre.py +302 -0
  275. sage/schemes/hyperelliptic_curves/monsky_washnitzer.py +3871 -0
  276. sage/schemes/jacobians/abstract_jacobian.py +277 -0
  277. sage/schemes/jacobians/all.py +2 -0
  278. sage/schemes/overview.py +161 -0
  279. sage/schemes/plane_conics/all.py +22 -0
  280. sage/schemes/plane_conics/con_field.py +1296 -0
  281. sage/schemes/plane_conics/con_finite_field.py +158 -0
  282. sage/schemes/plane_conics/con_number_field.py +456 -0
  283. sage/schemes/plane_conics/con_rational_field.py +406 -0
  284. sage/schemes/plane_conics/con_rational_function_field.py +580 -0
  285. sage/schemes/plane_conics/constructor.py +249 -0
  286. sage/schemes/plane_quartics/all.py +2 -0
  287. sage/schemes/plane_quartics/quartic_constructor.py +71 -0
  288. sage/schemes/plane_quartics/quartic_generic.py +73 -0
  289. sage/schemes/riemann_surfaces/all.py +1 -0
  290. sage/schemes/riemann_surfaces/riemann_surface.py +4117 -0
  291. sage_wheels/share/cremona/cremona_mini.db +0 -0
  292. sage_wheels/share/ellcurves/rank0 +30427 -0
  293. sage_wheels/share/ellcurves/rank1 +31871 -0
  294. sage_wheels/share/ellcurves/rank10 +6 -0
  295. sage_wheels/share/ellcurves/rank11 +6 -0
  296. sage_wheels/share/ellcurves/rank12 +1 -0
  297. sage_wheels/share/ellcurves/rank14 +1 -0
  298. sage_wheels/share/ellcurves/rank15 +1 -0
  299. sage_wheels/share/ellcurves/rank17 +1 -0
  300. sage_wheels/share/ellcurves/rank19 +1 -0
  301. sage_wheels/share/ellcurves/rank2 +2388 -0
  302. sage_wheels/share/ellcurves/rank20 +1 -0
  303. sage_wheels/share/ellcurves/rank21 +1 -0
  304. sage_wheels/share/ellcurves/rank22 +1 -0
  305. sage_wheels/share/ellcurves/rank23 +1 -0
  306. sage_wheels/share/ellcurves/rank24 +1 -0
  307. sage_wheels/share/ellcurves/rank28 +1 -0
  308. sage_wheels/share/ellcurves/rank3 +836 -0
  309. sage_wheels/share/ellcurves/rank4 +10 -0
  310. sage_wheels/share/ellcurves/rank5 +5 -0
  311. sage_wheels/share/ellcurves/rank6 +5 -0
  312. sage_wheels/share/ellcurves/rank7 +5 -0
  313. sage_wheels/share/ellcurves/rank8 +6 -0
  314. sage_wheels/share/ellcurves/rank9 +7 -0
@@ -0,0 +1,1825 @@
1
+ # sage_setup: distribution = sagemath-schemes
2
+ # sage.doctest: needs sage.libs.pari sage.rings.number_field
3
+ r"""
4
+ Smooth characters of `p`-adic fields
5
+
6
+ Let `F` be a finite extension of `\QQ_p`. Then we may consider the group of
7
+ smooth (i.e. locally constant) group homomorphisms `F^\times \to L^\times`, for
8
+ `L` any field. Such characters are important since they can be used to
9
+ parametrise smooth representations of `\mathrm{GL}_2(\QQ_p)`, which arise as
10
+ the local components of modular forms.
11
+
12
+ This module contains classes to represent such characters when `F` is `\QQ_p`
13
+ or a quadratic extension. In the latter case, we choose a quadratic extension
14
+ `K` of `\QQ` whose completion at `p` is `F`, and use Sage's wrappers of the
15
+ Pari :pari:`idealstar` and :pari:`ideallog` methods to work in the finite group
16
+ `\mathcal{O}_K / p^c` for `c \ge 0`.
17
+
18
+ An example with characters of `\QQ_7`::
19
+
20
+ sage: from sage.modular.local_comp.smoothchar import SmoothCharacterGroupQp
21
+ sage: K.<z> = CyclotomicField(42)
22
+ sage: G = SmoothCharacterGroupQp(7, K)
23
+ sage: G.unit_gens(2), G.exponents(2)
24
+ ([3, 7], [42, 0])
25
+
26
+ The output of the last line means that the group `\QQ_7^\times / (1 + 7^2
27
+ \ZZ_7)` is isomorphic to `C_{42} \times \ZZ`, with the two factors being
28
+ generated by `3` and `7` respectively. We create a character by specifying the
29
+ images of these generators::
30
+
31
+ sage: chi = G.character(2, [z^5, 11 + z]); chi
32
+ Character of Q_7*, of level 2, mapping 3 |--> z^5, 7 |--> z + 11
33
+ sage: chi(4)
34
+ z^8
35
+ sage: chi(42)
36
+ z^10 + 11*z^9
37
+
38
+ Characters are themselves group elements, and basic arithmetic on them works::
39
+
40
+ sage: chi**3
41
+ Character of Q_7*, of level 2, mapping 3 |--> z^8 - z, 7 |--> z^3 + 33*z^2 + 363*z + 1331
42
+ sage: chi.multiplicative_order()
43
+ +Infinity
44
+ """
45
+
46
+ import operator
47
+
48
+ from sage.arith.functions import lcm
49
+ from sage.arith.misc import crt
50
+ from sage.categories.groups import Groups
51
+ from sage.categories.rings import Rings
52
+ from sage.misc.abstract_method import abstract_method
53
+ from sage.misc.cachefunc import cached_method
54
+ from sage.misc.lazy_import import lazy_import
55
+ from sage.misc.misc_c import prod
56
+ from sage.misc.mrange import xmrange
57
+ from sage.misc.verbose import verbose
58
+ from sage.modular.dirichlet import DirichletGroup
59
+ from sage.rings.finite_rings.integer_mod_ring import Zmod
60
+ from sage.rings.infinity import Infinity
61
+ from sage.rings.integer_ring import ZZ
62
+ from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing
63
+ from sage.rings.rational_field import QQ
64
+ from sage.structure.element import MultiplicativeGroupElement, parent
65
+ from sage.structure.parent import Parent
66
+ from sage.structure.richcmp import richcmp_not_equal, richcmp
67
+ from sage.structure.sequence import Sequence
68
+
69
+ lazy_import('sage.rings.finite_rings.conway_polynomials', 'conway_polynomial')
70
+ lazy_import('sage.rings.number_field.number_field', 'NumberField')
71
+
72
+
73
+ class SmoothCharacterGeneric(MultiplicativeGroupElement):
74
+ r"""
75
+ A smooth (i.e. locally constant) character of `F^\times`, for `F` some
76
+ finite extension of `\QQ_p`.
77
+ """
78
+ def __init__(self, parent, c, values_on_gens):
79
+ r"""
80
+ Standard init function.
81
+
82
+ EXAMPLES::
83
+
84
+ sage: from sage.modular.local_comp.smoothchar import SmoothCharacterGroupUnramifiedQuadratic
85
+ sage: G = SmoothCharacterGroupUnramifiedQuadratic(2, QQ)
86
+ sage: G.character(0, [17]) # indirect doctest
87
+ Character of unramified extension Q_2(s)* (s^2 + s + 1 = 0), of level 0, mapping 2 |--> 17
88
+ sage: G.character(1, [1, 17]) # indirect doctest
89
+ Character of unramified extension Q_2(s)* (s^2 + s + 1 = 0), of level 0, mapping 2 |--> 17
90
+ sage: G.character(2, [1, -1, 1, 17]) # indirect doctest
91
+ Character of unramified extension Q_2(s)* (s^2 + s + 1 = 0), of level 2, mapping s |--> 1, 2*s + 1 |--> -1, -1 |--> 1, 2 |--> 17
92
+ sage: G.character(2, [1, 1, 1, 17]) # indirect doctest
93
+ Character of unramified extension Q_2(s)* (s^2 + s + 1 = 0), of level 0, mapping 2 |--> 17
94
+ """
95
+ MultiplicativeGroupElement.__init__(self, parent)
96
+ self._c = c
97
+ self._values_on_gens = Sequence(values_on_gens, universe=self.base_ring(), immutable=True)
98
+ self._check_level()
99
+
100
+ def _check_level(self):
101
+ r"""
102
+ Check that this character has the level it claims to have, and if not,
103
+ decrement the level appropriately. This is called by :meth:`__init__`.
104
+
105
+ EXAMPLES::
106
+
107
+ sage: from sage.modular.local_comp.smoothchar import SmoothCharacterGroupQp
108
+ sage: SmoothCharacterGroupQp(5, QQ).character(5, [-1, 7]) # indirect doctest
109
+ Character of Q_5*, of level 1, mapping 2 |--> -1, 5 |--> 7
110
+ """
111
+ if self.level() == 0:
112
+ return
113
+ v = self.parent().subgroup_gens(self.level())
114
+ if all(self(x) == 1 for x in v):
115
+ new_gens = self.parent().unit_gens(self.level() - 1)
116
+ new_values = [self(x) for x in new_gens]
117
+ self._values_on_gens = Sequence(new_values, universe=self.base_ring(), immutable=True)
118
+ self._c = self._c - 1
119
+ self._check_level()
120
+
121
+ def __hash__(self):
122
+ r"""
123
+ EXAMPLES::
124
+
125
+ sage: from sage.modular.local_comp.smoothchar import SmoothCharacterGroupQp
126
+ sage: chi = SmoothCharacterGroupQp(5, QQ).character(5, [-1, 7])
127
+ sage: D = {chi: 7}; D[chi] # indirect doctest
128
+ 7
129
+ """
130
+ return hash( (self._c, self._values_on_gens) )
131
+
132
+ def _richcmp_(self, other, op):
133
+ r"""
134
+ Compare ``self`` and ``other``.
135
+
136
+ Note that this only gets called when the
137
+ parents of ``self`` and ``other`` are identical.
138
+
139
+ INPUT:
140
+
141
+ - ``other`` -- another smooth character
142
+
143
+ - ``op`` -- a comparison operator (see :mod:`sage.structure.richcmp`)
144
+
145
+ EXAMPLES::
146
+
147
+ sage: from sage.modular.local_comp.smoothchar import SmoothCharacterGroupQp, SmoothCharacterGroupUnramifiedQuadratic
148
+ sage: SmoothCharacterGroupQp(7, Zmod(3)).character(1, [2, 1]) == SmoothCharacterGroupQp(7, ZZ).character(1, [-1, 1])
149
+ True
150
+ sage: chi1 = SmoothCharacterGroupUnramifiedQuadratic(7, QQ).character(0, [1])
151
+ sage: chi2 = SmoothCharacterGroupQp(7, QQ).character(0, [1])
152
+ sage: chi1 == chi2
153
+ False
154
+ sage: chi2.parent()(chi1) == chi2
155
+ True
156
+ sage: chi1 == loads(dumps(chi1))
157
+ True
158
+ """
159
+ lx = self.level()
160
+ rx = other.level()
161
+ if lx != rx:
162
+ return richcmp_not_equal(lx, rx, op)
163
+
164
+ return richcmp(self._values_on_gens, other._values_on_gens, op)
165
+
166
+ def multiplicative_order(self):
167
+ r"""
168
+ Return the order of this character as an element of the character group.
169
+
170
+ EXAMPLES::
171
+
172
+ sage: from sage.modular.local_comp.smoothchar import SmoothCharacterGroupQp
173
+ sage: K.<z> = CyclotomicField(42)
174
+ sage: G = SmoothCharacterGroupQp(7, K)
175
+ sage: G.character(3, [z^10 - z^3, 11]).multiplicative_order()
176
+ +Infinity
177
+ sage: G.character(3, [z^10 - z^3, 1]).multiplicative_order()
178
+ 42
179
+ sage: G.character(1, [z^7, z^14]).multiplicative_order()
180
+ 6
181
+ sage: G.character(0, [1]).multiplicative_order()
182
+ 1
183
+ """
184
+ if self._values_on_gens[-1].multiplicative_order() == Infinity:
185
+ return Infinity
186
+ else:
187
+ return lcm([x.multiplicative_order() for x in self._values_on_gens])
188
+
189
+ def level(self):
190
+ r"""
191
+ Return the level of this character, i.e. the smallest integer `c \ge 0`
192
+ such that it is trivial on `1 + \mathfrak{p}^c`.
193
+
194
+ EXAMPLES::
195
+
196
+ sage: from sage.modular.local_comp.smoothchar import SmoothCharacterGroupQp
197
+ sage: SmoothCharacterGroupQp(7, QQ).character(2, [-1, 1]).level()
198
+ 1
199
+ """
200
+ return self._c
201
+
202
+ def __call__(self, x):
203
+ r"""
204
+ Evaluate the character at ``x``, which should be a nonzero element of
205
+ the number field of the parent group.
206
+
207
+ EXAMPLES::
208
+
209
+ sage: from sage.modular.local_comp.smoothchar import SmoothCharacterGroupQp
210
+ sage: K.<z> = CyclotomicField(42)
211
+ sage: chi = SmoothCharacterGroupQp(7, K).character(3, [z^10 - z^3, 11])
212
+ sage: [chi(x) for x in [1, 2, 3, 9, 21, 1/12345678]]
213
+ [1, -z, z^10 - z^3, -z^11 - z^10 + z^8 + z^7 - z^6 - z^5 + z^3 + z^2 - 1, 11*z^10 - 11*z^3, z^7 - 1]
214
+
215
+ Non-examples::
216
+
217
+ sage: chi(QuadraticField(-1,'i').gen())
218
+ Traceback (most recent call last):
219
+ ...
220
+ TypeError: no canonical coercion from Number Field in i with defining polynomial x^2 + 1 with i = 1*I to Rational Field
221
+ sage: chi(0)
222
+ Traceback (most recent call last):
223
+ ...
224
+ ValueError: cannot evaluate at zero
225
+ sage: chi(Mod(1, 12))
226
+ Traceback (most recent call last):
227
+ ...
228
+ TypeError: no canonical coercion from Ring of integers modulo 12 to Rational Field
229
+
230
+ Some examples with an unramified quadratic extension, where the choice
231
+ of generators is arbitrary (but deterministic)::
232
+
233
+ sage: from sage.modular.local_comp.smoothchar import SmoothCharacterGroupUnramifiedQuadratic
234
+ sage: K.<z> = CyclotomicField(30)
235
+ sage: G = SmoothCharacterGroupUnramifiedQuadratic(5, K)
236
+ sage: chi = G.character(2, [z**5, z**(-6), z**6, 3]); chi
237
+ Character of unramified extension Q_5(s)* (s^2 + 4*s + 2 = 0), of level 2, mapping 11*s - 10 |--> z^5, 6 |--> -z^7 - z^6 + z^3 + z^2 - 1, 5*s + 1 |--> z^6, 5 |--> 3
238
+ sage: chi(G.unit_gens(2)[0]**7 / G.unit_gens(2)[1]/5)
239
+ 1/3*z^6 - 1/3*z
240
+ sage: chi(2)
241
+ -z^3
242
+ """
243
+ v = self.parent().discrete_log(self.level(), x)
244
+ return prod([self._values_on_gens[i] ** v[i] for i in range(len(v))])
245
+
246
+ def _repr_(self):
247
+ r"""
248
+ String representation of this character.
249
+
250
+ EXAMPLES::
251
+
252
+ sage: from sage.modular.local_comp.smoothchar import SmoothCharacterGroupQp
253
+ sage: K.<z> = CyclotomicField(20)
254
+ sage: SmoothCharacterGroupQp(5, K).character(2, [z, z+1])._repr_()
255
+ 'Character of Q_5*, of level 2, mapping 2 |--> z, 5 |--> z + 1'
256
+
257
+ Examples over field extensions::
258
+
259
+ sage: from sage.modular.local_comp.smoothchar import SmoothCharacterGroupUnramifiedQuadratic
260
+ sage: K.<z> = CyclotomicField(15)
261
+ sage: SmoothCharacterGroupUnramifiedQuadratic(5, K).character(2, [z**5, z**3, 1, z+1])._repr_()
262
+ 'Character of unramified extension Q_5(s)* (s^2 + 4*s + 2 = 0), of level 2, mapping 11*s - 10 |--> z^5, 6 |--> z^3, 5*s + 1 |--> 1, 5 |--> z + 1'
263
+ """
264
+ gens = self.parent().unit_gens(self.level())
265
+ mapst = ", ".join( str(gens[i]) + ' |--> ' + str(self._values_on_gens[i]) for i in range(len(gens)) )
266
+ return "Character of %s, of level %s, mapping %s" % (self.parent()._field_name(), self.level(), mapst)
267
+
268
+ def _mul_(self, other):
269
+ r"""
270
+ Product of ``self`` and ``other``.
271
+
272
+ EXAMPLES::
273
+
274
+ sage: from sage.modular.local_comp.smoothchar import SmoothCharacterGroupQp
275
+ sage: K.<z> = CyclotomicField(20)
276
+ sage: chi1 = SmoothCharacterGroupQp(5, K).character(2, [z, z+1])
277
+ sage: chi2 = SmoothCharacterGroupQp(5, K).character(2, [z^4, 3])
278
+ sage: chi1 * chi2 # indirect doctest
279
+ Character of Q_5*, of level 1, mapping 2 |--> z^5, 5 |--> 3*z + 3
280
+ sage: chi2 * chi1 # indirect doctest
281
+ Character of Q_5*, of level 1, mapping 2 |--> z^5, 5 |--> 3*z + 3
282
+ sage: chi1 * SmoothCharacterGroupQp(5, QQ).character(2, [-1, 7]) # indirect doctest
283
+ Character of Q_5*, of level 2, mapping 2 |--> -z, 5 |--> 7*z + 7
284
+ """
285
+ if other.level() > self.level():
286
+ return other * self
287
+ return self.parent().character(self.level(), [self(x) * other(x) for x in self.parent().unit_gens(self.level())])
288
+
289
+ def __invert__(self):
290
+ r"""
291
+ Multiplicative inverse of ``self``.
292
+
293
+ EXAMPLES::
294
+
295
+ sage: from sage.modular.local_comp.smoothchar import SmoothCharacterGroupUnramifiedQuadratic
296
+ sage: K.<z> = CyclotomicField(12)
297
+ sage: chi = SmoothCharacterGroupUnramifiedQuadratic(2, K).character(4, [z**4, z**3, z**9, -1, 7]); chi
298
+ Character of unramified extension Q_2(s)* (s^2 + s + 1 = 0), of level 4, mapping s |--> z^2 - 1, 2*s + 1 |--> z^3, 4*s + 1 |--> -z^3, -1 |--> -1, 2 |--> 7
299
+ sage: chi**(-1) # indirect doctest
300
+ Character of unramified extension Q_2(s)* (s^2 + s + 1 = 0), of level 4, mapping s |--> -z^2, 2*s + 1 |--> -z^3, 4*s + 1 |--> z^3, -1 |--> -1, 2 |--> 1/7
301
+ sage: SmoothCharacterGroupUnramifiedQuadratic(2, QQ).character(0, [7]) / chi # indirect doctest
302
+ Character of unramified extension Q_2(s)* (s^2 + s + 1 = 0), of level 4, mapping s |--> -z^2, 2*s + 1 |--> -z^3, 4*s + 1 |--> z^3, -1 |--> -1, 2 |--> 1
303
+ """
304
+ return self.parent().character(self.level(), [~self(x) for x in self.parent().unit_gens(self.level())])
305
+
306
+ def restrict_to_Qp(self):
307
+ r"""
308
+ Return the restriction of this character to `\QQ_p^\times`, embedded as
309
+ a subfield of `F^\times`.
310
+
311
+ EXAMPLES::
312
+
313
+ sage: from sage.modular.local_comp.smoothchar import SmoothCharacterGroupRamifiedQuadratic
314
+ sage: SmoothCharacterGroupRamifiedQuadratic(3, 0, QQ).character(0, [2]).restrict_to_Qp()
315
+ Character of Q_3*, of level 0, mapping 3 |--> 4
316
+ """
317
+ G = SmoothCharacterGroupQp(self.parent().prime(), self.base_ring())
318
+ ugs = G.unit_gens(self.level())
319
+ return G.character(self.level(), [self(x) for x in ugs])
320
+
321
+ def galois_conjugate(self):
322
+ r"""
323
+ Return the composite of this character with the order `2` automorphism of
324
+ `K / \QQ_p` (assuming `K` is quadratic).
325
+
326
+ Note that this is the Galois operation on the *domain*, not on the
327
+ *codomain*.
328
+
329
+ EXAMPLES::
330
+
331
+ sage: from sage.modular.local_comp.smoothchar import SmoothCharacterGroupUnramifiedQuadratic
332
+ sage: K.<w> = CyclotomicField(3)
333
+ sage: G = SmoothCharacterGroupUnramifiedQuadratic(2, K)
334
+ sage: chi = G.character(2, [w, -1,-1, 3*w])
335
+ sage: chi2 = chi.galois_conjugate(); chi2
336
+ Character of unramified extension Q_2(s)* (s^2 + s + 1 = 0), of level 2, mapping s |--> -w - 1, 2*s + 1 |--> 1, -1 |--> -1, 2 |--> 3*w
337
+
338
+ sage: chi.restrict_to_Qp() == chi2.restrict_to_Qp()
339
+ True
340
+ sage: chi * chi2 == chi.parent().compose_with_norm(chi.restrict_to_Qp())
341
+ True
342
+ """
343
+ K, s = self.parent().number_field().objgen()
344
+ if K.absolute_degree() != 2:
345
+ raise ValueError("Character must be defined on a quadratic extension")
346
+ sigs = K.embeddings(K)
347
+ sig = [x for x in sigs if x(s) != s][0]
348
+ return self.parent().character(self.level(), [self(sig(x)) for x in self.parent().unit_gens(self.level())])
349
+
350
+
351
+ class SmoothCharacterGroupGeneric(Parent):
352
+ r"""
353
+ The group of smooth (i.e. locally constant) characters of a `p`-adic field,
354
+ with values in some ring `R`. This is an abstract base class and should not
355
+ be instantiated directly.
356
+ """
357
+
358
+ Element = SmoothCharacterGeneric
359
+
360
+ def __init__(self, p, base_ring):
361
+ r"""
362
+ TESTS::
363
+
364
+ sage: from sage.modular.local_comp.smoothchar import SmoothCharacterGroupGeneric
365
+ sage: G = SmoothCharacterGroupGeneric(3, QQ)
366
+ sage: SmoothCharacterGroupGeneric(3, "hello")
367
+ Traceback (most recent call last):
368
+ ...
369
+ TypeError: base ring (=hello) must be a ring
370
+ """
371
+ if base_ring not in Rings():
372
+ raise TypeError("base ring (=%s) must be a ring" % base_ring)
373
+ Parent.__init__(self, base=base_ring,
374
+ category=Groups().Commutative())
375
+ if not (p in ZZ and ZZ(p).is_prime()):
376
+ raise ValueError("p (=%s) must be a prime integer" % p)
377
+ self._p = ZZ.coerce(p)
378
+
379
+ def _element_constructor_(self, x):
380
+ r"""
381
+ Construct an element of this group from ``x`` (possibly noncanonically).
382
+ This only works if ``x`` is a character of a field containing the field of
383
+ ``self``, whose values lie in a field that can be converted into ``self``.
384
+
385
+ EXAMPLES::
386
+
387
+ sage: from sage.modular.local_comp.smoothchar import SmoothCharacterGroupQp
388
+ sage: K.<i> = QuadraticField(-1)
389
+ sage: G = SmoothCharacterGroupQp(3, QQ)
390
+ sage: GK = SmoothCharacterGroupQp(3, K)
391
+ sage: chi = GK(G.character(0, [4])); chi # indirect doctest
392
+ Character of Q_3*, of level 0, mapping 3 |--> 4
393
+ sage: chi.parent() is GK
394
+ True
395
+ sage: G(GK.character(0, [7])) # indirect doctest
396
+ Character of Q_3*, of level 0, mapping 3 |--> 7
397
+ sage: G(GK.character(0, [i])) # indirect doctest
398
+ Traceback (most recent call last):
399
+ ...
400
+ TypeError: unable to convert i to an element of Rational Field
401
+ """
402
+ if x == 1:
403
+ return self.character(0, [1])
404
+ P = parent(x)
405
+ if (isinstance(P, SmoothCharacterGroupGeneric)
406
+ and P.number_field().has_coerce_map_from(self.number_field())):
407
+ return self.character(x.level(), [x(v) for v in self.unit_gens(x.level())])
408
+ else:
409
+ raise TypeError
410
+
411
+ def __eq__(self, other):
412
+ r"""
413
+ TESTS::
414
+
415
+ sage: from sage.modular.local_comp.smoothchar import SmoothCharacterGroupQp
416
+ sage: G = SmoothCharacterGroupQp(3, QQ)
417
+ sage: G == SmoothCharacterGroupQp(3, QQ[I])
418
+ False
419
+ sage: G == 7
420
+ False
421
+ sage: G == SmoothCharacterGroupQp(7, QQ)
422
+ False
423
+ sage: G == SmoothCharacterGroupQp(3, QQ)
424
+ True
425
+ """
426
+ if not isinstance(other, SmoothCharacterGroupGeneric):
427
+ return False
428
+
429
+ return (self.prime() == other.prime() and
430
+ self.number_field() == other.number_field() and
431
+ self.base_ring() == other.base_ring())
432
+
433
+ def __ne__(self, other):
434
+ """
435
+ Check whether ``self`` is not equal to ``other``.
436
+
437
+ EXAMPLES::
438
+
439
+ sage: from sage.modular.local_comp.smoothchar import SmoothCharacterGroupQp
440
+ sage: G = SmoothCharacterGroupQp(3, QQ)
441
+ sage: G != SmoothCharacterGroupQp(3, QQ[I])
442
+ True
443
+ sage: G != 7
444
+ True
445
+ sage: G != SmoothCharacterGroupQp(7, QQ)
446
+ True
447
+ sage: G != SmoothCharacterGroupQp(3, QQ)
448
+ False
449
+ """
450
+ return not (self == other)
451
+
452
+ def __hash__(self):
453
+ """
454
+ Return the hash of ``self``.
455
+
456
+ TESTS::
457
+
458
+ sage: from sage.modular.local_comp.smoothchar import SmoothCharacterGroupQp
459
+ sage: G = SmoothCharacterGroupQp(3, QQ)
460
+ sage: hash(G) == hash(SmoothCharacterGroupQp(3, QQ[I]))
461
+ False
462
+ sage: hash(G) == hash(SmoothCharacterGroupQp(7, QQ))
463
+ False
464
+ sage: hash(G) == hash(SmoothCharacterGroupQp(3, QQ))
465
+ True
466
+ """
467
+ return hash((self.prime(), self.number_field(), self.base_ring()))
468
+
469
+ def _coerce_map_from_(self, other):
470
+ r"""
471
+ Return ``True`` if ``self`` has a canonical coerce map from ``other``.
472
+
473
+ EXAMPLES::
474
+
475
+ sage: from sage.modular.local_comp.smoothchar import SmoothCharacterGroupQp
476
+ sage: K.<i> = QuadraticField(-1)
477
+ sage: G = SmoothCharacterGroupQp(3, QQ)
478
+ sage: GK = SmoothCharacterGroupQp(3, K)
479
+ sage: G.has_coerce_map_from(GK)
480
+ False
481
+ sage: GK.has_coerce_map_from(G)
482
+ True
483
+ sage: GK.coerce(G.character(0, [4]))
484
+ Character of Q_3*, of level 0, mapping 3 |--> 4
485
+ sage: G.coerce(GK.character(0, [4]))
486
+ Traceback (most recent call last):
487
+ ...
488
+ TypeError: no canonical coercion from Group of smooth characters of Q_3* with values in Number Field in i with defining polynomial x^2 + 1 with i = 1*I to Group of smooth characters of Q_3* with values in Rational Field
489
+ sage: G.character(0, [4]) in GK # indirect doctest
490
+ True
491
+
492
+ The coercion framework handles base extension, so we test that too::
493
+
494
+ sage: K.<i> = QuadraticField(-1)
495
+ sage: from sage.modular.local_comp.smoothchar import SmoothCharacterGroupUnramifiedQuadratic
496
+ sage: G = SmoothCharacterGroupUnramifiedQuadratic(3, QQ)
497
+ sage: G.character(0, [1]).base_extend(K)
498
+ Character of unramified extension Q_3(s)* (s^2 + 2*s + 2 = 0), of level 0, mapping 3 |--> 1
499
+ """
500
+ return (isinstance(other, SmoothCharacterGroupGeneric)
501
+ and other.number_field() == self.number_field()
502
+ and self.base_ring().has_coerce_map_from(other.base_ring()))
503
+
504
+ def prime(self):
505
+ r"""
506
+ The residue characteristic of the underlying field.
507
+
508
+ EXAMPLES::
509
+
510
+ sage: from sage.modular.local_comp.smoothchar import SmoothCharacterGroupGeneric
511
+ sage: SmoothCharacterGroupGeneric(3, QQ).prime()
512
+ 3
513
+ """
514
+ return self._p
515
+
516
+ @abstract_method
517
+ def change_ring(self, ring):
518
+ r"""
519
+ Return the character group of the same field, but with values in a
520
+ different coefficient ring. To be implemented by all derived classes
521
+ (since the generic base class can't know the parameters).
522
+
523
+ EXAMPLES::
524
+
525
+ sage: from sage.modular.local_comp.smoothchar import SmoothCharacterGroupGeneric
526
+ sage: SmoothCharacterGroupGeneric(3, QQ).change_ring(ZZ)
527
+ Traceback (most recent call last):
528
+ ...
529
+ NotImplementedError: <abstract method change_ring at ...>
530
+ """
531
+ pass
532
+
533
+ def base_extend(self, ring):
534
+ r"""
535
+ Return the character group of the same field, but with values in a new
536
+ coefficient ring into which the old coefficient ring coerces. An error
537
+ will be raised if there is no coercion map from the old coefficient
538
+ ring to the new one.
539
+
540
+ EXAMPLES::
541
+
542
+ sage: from sage.modular.local_comp.smoothchar import SmoothCharacterGroupQp
543
+ sage: G = SmoothCharacterGroupQp(3, QQ)
544
+ sage: G.base_extend(QQbar)
545
+ Group of smooth characters of Q_3* with values in Algebraic Field
546
+ sage: G.base_extend(Zmod(3))
547
+ Traceback (most recent call last):
548
+ ...
549
+ TypeError: no canonical coercion from Rational Field to Ring of integers modulo 3
550
+ """
551
+ if not ring.has_coerce_map_from(self.base_ring()):
552
+ ring.coerce(self.base_ring().an_element())
553
+ # this is here to flush out errors
554
+
555
+ return self.change_ring(ring)
556
+
557
+ @abstract_method
558
+ def _field_name(self):
559
+ r"""
560
+ A string representing the name of the `p`-adic field of which this is the
561
+ character group. To be overridden by derived subclasses.
562
+
563
+ EXAMPLES::
564
+
565
+ sage: from sage.modular.local_comp.smoothchar import SmoothCharacterGroupGeneric
566
+ sage: SmoothCharacterGroupGeneric(3, QQ)._field_name()
567
+ Traceback (most recent call last):
568
+ ...
569
+ NotImplementedError: <abstract method _field_name at ...>
570
+ """
571
+ pass
572
+
573
+ def _repr_(self):
574
+ r"""
575
+ String representation of ``self``.
576
+
577
+ EXAMPLES::
578
+
579
+ sage: from sage.modular.local_comp.smoothchar import SmoothCharacterGroupQp
580
+ sage: SmoothCharacterGroupQp(7, QQ)._repr_()
581
+ 'Group of smooth characters of Q_7* with values in Rational Field'
582
+ """
583
+ return "Group of smooth characters of %s with values in %s" % (self._field_name(), self.base_ring())
584
+
585
+ @abstract_method
586
+ def ideal(self, level):
587
+ r"""
588
+ Return the ``level``-th power of the maximal ideal of the ring of
589
+ integers of the `p`-adic field. Since we approximate by using number
590
+ field arithmetic, what is actually returned is an ideal in a number
591
+ field.
592
+
593
+ EXAMPLES::
594
+
595
+ sage: from sage.modular.local_comp.smoothchar import SmoothCharacterGroupGeneric
596
+ sage: SmoothCharacterGroupGeneric(3, QQ).ideal(3)
597
+ Traceback (most recent call last):
598
+ ...
599
+ NotImplementedError: <abstract method ideal at ...>
600
+ """
601
+ pass
602
+
603
+ @abstract_method
604
+ def unit_gens(self, level):
605
+ r"""
606
+ A list of generators `x_1, \dots, x_d` of the abelian group `F^\times /
607
+ (1 + \mathfrak{p}^c)^\times`, where `c` is the given level, satisfying
608
+ no relations other than `x_i^{n_i} = 1` for each `i` (where the
609
+ integers `n_i` are returned by :meth:`exponents`). We adopt the
610
+ convention that the final generator `x_d` is a uniformiser (and `n_d =
611
+ 0`).
612
+
613
+ EXAMPLES::
614
+
615
+ sage: from sage.modular.local_comp.smoothchar import SmoothCharacterGroupGeneric
616
+ sage: SmoothCharacterGroupGeneric(3, QQ).unit_gens(3)
617
+ Traceback (most recent call last):
618
+ ...
619
+ NotImplementedError: <abstract method unit_gens at ...>
620
+ """
621
+ pass
622
+
623
+ @abstract_method
624
+ def exponents(self, level):
625
+ r"""
626
+ The orders `n_1, \dots, n_d` of the generators `x_i` of `F^\times / (1
627
+ + \mathfrak{p}^c)^\times` returned by :meth:`unit_gens`.
628
+
629
+ EXAMPLES::
630
+
631
+ sage: from sage.modular.local_comp.smoothchar import SmoothCharacterGroupGeneric
632
+ sage: SmoothCharacterGroupGeneric(3, QQ).exponents(3)
633
+ Traceback (most recent call last):
634
+ ...
635
+ NotImplementedError: <abstract method exponents at ...>
636
+ """
637
+ pass
638
+
639
+ @abstract_method
640
+ def subgroup_gens(self, level):
641
+ r"""
642
+ A set of elements of `(\mathcal{O}_F / \mathfrak{p}^c)^\times`
643
+ generating the kernel of the reduction map to `(\mathcal{O}_F /
644
+ \mathfrak{p}^{c-1})^\times`.
645
+
646
+ EXAMPLES::
647
+
648
+ sage: from sage.modular.local_comp.smoothchar import SmoothCharacterGroupGeneric
649
+ sage: SmoothCharacterGroupGeneric(3, QQ).subgroup_gens(3)
650
+ Traceback (most recent call last):
651
+ ...
652
+ NotImplementedError: <abstract method subgroup_gens at ...>
653
+ """
654
+ pass
655
+
656
+ @abstract_method
657
+ def discrete_log(self, level):
658
+ r"""
659
+ Given an element `x \in F^\times` (lying in the number field `K` of
660
+ which `F` is a completion, see module docstring), express the class of
661
+ `x` in terms of the generators of `F^\times / (1 +
662
+ \mathfrak{p}^c)^\times` returned by :meth:`unit_gens`.
663
+
664
+ This should be overridden by all derived classes. The method should
665
+ first attempt to canonically coerce `x` into ``self.number_field()``,
666
+ and check that the result is not zero.
667
+
668
+ EXAMPLES::
669
+
670
+ sage: from sage.modular.local_comp.smoothchar import SmoothCharacterGroupGeneric
671
+ sage: SmoothCharacterGroupGeneric(3, QQ).discrete_log(3)
672
+ Traceback (most recent call last):
673
+ ...
674
+ NotImplementedError: <abstract method discrete_log at ...>
675
+ """
676
+ pass
677
+
678
+ def character(self, level, values_on_gens):
679
+ r"""
680
+ Return the unique character of the given level whose values on the
681
+ generators returned by ``self.unit_gens(level)`` are
682
+ ``values_on_gens``.
683
+
684
+ INPUT:
685
+
686
+ - ``level`` -- integer an integer `\ge 0`
687
+ - ``values_on_gens`` -- sequence a sequence of elements of length equal
688
+ to the length of ``self.unit_gens(level)``. The values should be
689
+ convertible (that is, possibly noncanonically) into the base ring of self; they
690
+ should all be units, and all but the last must be roots of unity (of
691
+ the orders given by ``self.exponents(level)``.
692
+
693
+ .. NOTE::
694
+
695
+ The character returned may have level less than ``level`` in general.
696
+
697
+ EXAMPLES::
698
+
699
+ sage: from sage.modular.local_comp.smoothchar import SmoothCharacterGroupQp
700
+ sage: K.<z> = CyclotomicField(42)
701
+ sage: G = SmoothCharacterGroupQp(7, K)
702
+ sage: G.character(2, [z^6, 8])
703
+ Character of Q_7*, of level 2, mapping 3 |--> z^6, 7 |--> 8
704
+ sage: G.character(2, [z^7, 8])
705
+ Character of Q_7*, of level 1, mapping 3 |--> z^7, 7 |--> 8
706
+
707
+ Non-examples::
708
+
709
+ sage: G.character(1, [z, 1])
710
+ Traceback (most recent call last):
711
+ ...
712
+ ValueError: value on generator 3 (=z) should be a root of unity of order 6
713
+ sage: G.character(1, [1, 0])
714
+ Traceback (most recent call last):
715
+ ...
716
+ ValueError: value on uniformiser 7 (=0) should be a unit
717
+
718
+ An example with a funky coefficient ring::
719
+
720
+ sage: G = SmoothCharacterGroupQp(7, Zmod(9))
721
+ sage: G.character(1, [2, 2])
722
+ Character of Q_7*, of level 1, mapping 3 |--> 2, 7 |--> 2
723
+ sage: G.character(1, [2, 3])
724
+ Traceback (most recent call last):
725
+ ...
726
+ ValueError: value on uniformiser 7 (=3) should be a unit
727
+
728
+ TESTS::
729
+
730
+ sage: G.character(1, [2])
731
+ Traceback (most recent call last):
732
+ ...
733
+ AssertionError: 2 images must be given
734
+ """
735
+ S = Sequence(values_on_gens, universe=self.base_ring(), immutable=True)
736
+ assert len(S) == len(self.unit_gens(level)), "{0} images must be given".format(len(self.unit_gens(level)))
737
+ n = self.exponents(level)
738
+ for i in range(len(S)):
739
+ if n[i] != 0 and not S[i]**n[i] == 1:
740
+ raise ValueError( "value on generator %s (=%s) should be a root of unity of order %s" % (self.unit_gens(level)[i], S[i], n[i]) )
741
+ elif n[i] == 0 and not S[i].is_unit():
742
+ raise ValueError( "value on uniformiser %s (=%s) should be a unit" % (self.unit_gens(level)[i], S[i]) )
743
+ return self.element_class(self, level, S)
744
+
745
+ def norm_character(self):
746
+ r"""
747
+ Return the normalised absolute value character in this group (mapping a
748
+ uniformiser to `1/q` where `q` is the order of the residue field).
749
+
750
+ EXAMPLES::
751
+
752
+ sage: from sage.modular.local_comp.smoothchar import SmoothCharacterGroupQp, SmoothCharacterGroupUnramifiedQuadratic
753
+ sage: SmoothCharacterGroupQp(5, QQ).norm_character()
754
+ Character of Q_5*, of level 0, mapping 5 |--> 1/5
755
+ sage: SmoothCharacterGroupUnramifiedQuadratic(2, QQ).norm_character()
756
+ Character of unramified extension Q_2(s)* (s^2 + s + 1 = 0), of level 0, mapping 2 |--> 1/4
757
+ """
758
+ return self.character(0, [1/self.ideal(1).residue_field().cardinality()])
759
+
760
+ def _an_element_(self):
761
+ r"""
762
+ Return an element of this group. Required by the coercion machinery.
763
+
764
+ EXAMPLES::
765
+
766
+ sage: from sage.modular.local_comp.smoothchar import SmoothCharacterGroupQp
767
+ sage: K.<z> = CyclotomicField(42)
768
+ sage: G = SmoothCharacterGroupQp(7, K)
769
+ sage: G.an_element() # indirect doctest
770
+ Character of Q_7*, of level 0, mapping 7 |--> z
771
+ """
772
+ return self.character(0, [self.base_ring().an_element()])
773
+
774
+ def _test_unitgens(self, **options):
775
+ r"""
776
+ Test that the generators returned by ``unit_gens`` are consistent with
777
+ the exponents returned by ``exponents``.
778
+
779
+ EXAMPLES::
780
+
781
+ sage: from sage.modular.local_comp.smoothchar import SmoothCharacterGroupUnramifiedQuadratic
782
+ sage: SmoothCharacterGroupUnramifiedQuadratic(2, Zmod(8))._test_unitgens()
783
+ """
784
+ T = self._tester(**options)
785
+ for c in range(6):
786
+ gens = self.unit_gens(c)
787
+ exps = self.exponents(c)
788
+ T.assertEqual(exps[-1], 0)
789
+ T.assertTrue(all(u != 0 for u in exps[:-1]))
790
+ T.assertTrue(all(u.parent() is self.number_field() for u in gens))
791
+
792
+ I = self.ideal(c)
793
+ for i in range(len(exps[:-1])):
794
+ g = gens[i]
795
+ for m in range(1, exps[i]):
796
+ if (g - 1 in I):
797
+ T.fail("For generator g=%s, g^%s = %s = 1 mod I, but order should be %s" % (gens[i], m, g, exps[i]))
798
+ g = g * gens[i]
799
+ # reduce g mod I
800
+ if hasattr(I, "small_residue"):
801
+ g = I.small_residue(g)
802
+ else: # I is an ideal of ZZ
803
+ g = g % (I.gen())
804
+ if g - 1 not in I:
805
+ T.fail("For generator g=%s, g^%s = %s, which is not 1 mod I" % (gens[i], exps[i], g))
806
+ I = self.prime() if self.number_field() == QQ else self.ideal(1)
807
+ T.assertEqual(gens[-1].valuation(I), 1)
808
+
809
+ # This implicitly tests that the gens really are gens!
810
+ self.discrete_log(c, -1)
811
+
812
+ def _test_subgroupgens(self, **options):
813
+ r"""
814
+ Test that the values returned by :meth:`~subgroup_gens` are valid.
815
+
816
+ EXAMPLES::
817
+
818
+ sage: from sage.modular.local_comp.smoothchar import SmoothCharacterGroupQp
819
+ sage: SmoothCharacterGroupQp(2, CC)._test_subgroupgens()
820
+ """
821
+ T = self._tester(**options)
822
+ for c in range(1, 6):
823
+ sgs = self.subgroup_gens(c)
824
+ I2 = self.ideal(c - 1)
825
+ T.assertTrue(all(x - 1 in I2 for x in sgs), "Kernel gens at level %s not in kernel!" % c)
826
+
827
+ # now find the exponent of the kernel
828
+
829
+ n1 = prod(self.exponents(c)[:-1])
830
+ n2 = prod(self.exponents(c - 1)[:-1])
831
+ n = n1 // n2
832
+ # if c > 1, n will be a prime here, so that logs below gets calculated correctly
833
+
834
+ logs = []
835
+ for idx in xmrange(len(sgs)*[n]):
836
+ y = prod( map(operator.pow, sgs, idx) )
837
+ L = tuple(self.discrete_log(c, y))
838
+ if L not in logs:
839
+ logs.append(L)
840
+ T.assertEqual(n2 * len(logs), n1, "Kernel gens at level %s don't generate everything!" % c)
841
+
842
+ def compose_with_norm(self, chi):
843
+ r"""
844
+ Calculate the character of `K^\times` given by `\chi \circ \mathrm{Norm}_{K/\QQ_p}`.
845
+ Here `K` should be a quadratic extension and `\chi` a character of `\QQ_p^\times`.
846
+
847
+ EXAMPLES:
848
+
849
+ When `K` is the unramified quadratic extension, the level of the new character is the same as the old::
850
+
851
+ sage: from sage.modular.local_comp.smoothchar import SmoothCharacterGroupQp, SmoothCharacterGroupRamifiedQuadratic, SmoothCharacterGroupUnramifiedQuadratic
852
+ sage: K.<w> = CyclotomicField(6)
853
+ sage: G = SmoothCharacterGroupQp(3, K)
854
+ sage: chi = G.character(2, [w, 5])
855
+ sage: H = SmoothCharacterGroupUnramifiedQuadratic(3, K)
856
+ sage: H.compose_with_norm(chi)
857
+ Character of unramified extension Q_3(s)* (s^2 + 2*s + 2 = 0), of level 2, mapping -2*s |--> -1, 4 |--> -w, 3*s + 1 |--> w - 1, 3 |--> 25
858
+
859
+ In ramified cases, the level of the new character may be larger:
860
+
861
+ .. link
862
+
863
+ ::
864
+
865
+ sage: H = SmoothCharacterGroupRamifiedQuadratic(3, 0, K)
866
+ sage: H.compose_with_norm(chi)
867
+ Character of ramified extension Q_3(s)* (s^2 - 3 = 0), of level 3, mapping 2 |--> w - 1, s + 1 |--> -w, s |--> -5
868
+
869
+ On the other hand, since norm is not surjective, the result can even be trivial:
870
+
871
+ .. link
872
+
873
+ ::
874
+
875
+ sage: chi = G.character(1, [-1, -1]); chi
876
+ Character of Q_3*, of level 1, mapping 2 |--> -1, 3 |--> -1
877
+ sage: H.compose_with_norm(chi)
878
+ Character of ramified extension Q_3(s)* (s^2 - 3 = 0), of level 0, mapping s |--> 1
879
+ """
880
+ if chi.parent().number_field() != QQ:
881
+ raise ValueError
882
+ if self.number_field().absolute_degree() != 2:
883
+ raise ValueError
884
+ n = chi.level()
885
+ P = chi.parent().prime() ** n
886
+ m = self.number_field()(P).valuation(self.ideal(1))
887
+ return self.character(m, [chi(x.norm(QQ)) for x in self.unit_gens(m)])
888
+
889
+
890
+ class SmoothCharacterGroupQp(SmoothCharacterGroupGeneric):
891
+ r"""
892
+ The group of smooth characters of `\QQ_p^\times`, with values in some fixed
893
+ base ring.
894
+
895
+ EXAMPLES::
896
+
897
+ sage: from sage.modular.local_comp.smoothchar import SmoothCharacterGroupQp
898
+ sage: G = SmoothCharacterGroupQp(7, QQ); G
899
+ Group of smooth characters of Q_7* with values in Rational Field
900
+ sage: TestSuite(G).run()
901
+ sage: G == loads(dumps(G))
902
+ True
903
+ """
904
+ def unit_gens(self, level):
905
+ r"""
906
+ Return a set of generators `x_1, \dots, x_d` for `\QQ_p^\times / (1 +
907
+ p^c \ZZ_p)^\times`. These must be independent in the sense that there
908
+ are no relations between them other than relations of the form
909
+ `x_i^{n_i} = 1`. They need not, however, be in Smith normal form.
910
+
911
+ EXAMPLES::
912
+
913
+ sage: from sage.modular.local_comp.smoothchar import SmoothCharacterGroupQp
914
+ sage: SmoothCharacterGroupQp(7, QQ).unit_gens(3)
915
+ [3, 7]
916
+ sage: SmoothCharacterGroupQp(2, QQ).unit_gens(4)
917
+ [15, 5, 2]
918
+ """
919
+ if level == 0:
920
+ return [QQ(self.prime())]
921
+ else:
922
+ return [QQ(x) for x in Zmod(self.prime()**level).unit_gens()] + [QQ(self.prime())]
923
+
924
+ def exponents(self, level):
925
+ r"""
926
+ Return the exponents of the generators returned by :meth:`unit_gens`.
927
+
928
+ EXAMPLES::
929
+
930
+ sage: from sage.modular.local_comp.smoothchar import SmoothCharacterGroupQp
931
+ sage: SmoothCharacterGroupQp(7, QQ).exponents(3)
932
+ [294, 0]
933
+ sage: SmoothCharacterGroupQp(2, QQ).exponents(4)
934
+ [2, 4, 0]
935
+ """
936
+ if level == 0:
937
+ return [0]
938
+ return [x.multiplicative_order() for x in Zmod(self.prime()**level).unit_gens()] + [0]
939
+
940
+ def change_ring(self, ring):
941
+ r"""
942
+ Return the group of characters of the same field but with values in a
943
+ different ring. This need not have anything to do with the original
944
+ base ring, and in particular there won't generally be a coercion map
945
+ from ``self`` to the new group -- use
946
+ :meth:`~SmoothCharacterGroupGeneric.base_extend` if you want this.
947
+
948
+ EXAMPLES::
949
+
950
+ sage: from sage.modular.local_comp.smoothchar import SmoothCharacterGroupQp
951
+ sage: SmoothCharacterGroupQp(7, Zmod(3)).change_ring(CC)
952
+ Group of smooth characters of Q_7* with values in Complex Field with 53 bits of precision
953
+ """
954
+ return SmoothCharacterGroupQp(self.prime(), ring)
955
+
956
+ def number_field(self):
957
+ r"""
958
+ Return the number field used for calculations (a dense subfield of the
959
+ local field of which this is the character group). In this case, this
960
+ is always the rational field.
961
+
962
+ EXAMPLES::
963
+
964
+ sage: from sage.modular.local_comp.smoothchar import SmoothCharacterGroupQp
965
+ sage: SmoothCharacterGroupQp(7, Zmod(3)).number_field()
966
+ Rational Field
967
+ """
968
+ return QQ
969
+
970
+ def ideal(self, level):
971
+ r"""
972
+ Return the ``level``-th power of the maximal ideal. Since we
973
+ approximate by using rational arithmetic, what is actually returned is
974
+ an ideal of `\ZZ`.
975
+
976
+ EXAMPLES::
977
+
978
+ sage: from sage.modular.local_comp.smoothchar import SmoothCharacterGroupQp
979
+ sage: SmoothCharacterGroupQp(7, Zmod(3)).ideal(2)
980
+ Principal ideal (49) of Integer Ring
981
+ """
982
+ return ZZ.ideal(self.prime() ** level)
983
+
984
+ def _field_name(self):
985
+ r"""
986
+ Return a string representation of the field unit group of which this is
987
+ the character group.
988
+
989
+ EXAMPLES::
990
+
991
+ sage: from sage.modular.local_comp.smoothchar import SmoothCharacterGroupQp
992
+ sage: SmoothCharacterGroupQp(7, Zmod(3))._field_name()
993
+ 'Q_7*'
994
+ """
995
+ return "Q_%s*" % self.prime()
996
+
997
+ def discrete_log(self, level, x):
998
+ r"""
999
+ Express the class of `x` in `\QQ_p^\times / (1 + p^c)^\times` in terms
1000
+ of the generators returned by :meth:`unit_gens`.
1001
+
1002
+ EXAMPLES::
1003
+
1004
+ sage: from sage.modular.local_comp.smoothchar import SmoothCharacterGroupQp
1005
+ sage: G = SmoothCharacterGroupQp(7, QQ)
1006
+ sage: G.discrete_log(0, 14)
1007
+ [1]
1008
+ sage: G.discrete_log(1, 14)
1009
+ [2, 1]
1010
+ sage: G.discrete_log(5, 14)
1011
+ [9308, 1]
1012
+ """
1013
+ x = self.number_field().coerce(x)
1014
+ if x == 0:
1015
+ raise ValueError( "cannot evaluate at zero" )
1016
+ s = x.valuation(self.prime())
1017
+ return Zmod(self.prime()**level)(x / self.prime()**s).generalised_log() + [s]
1018
+
1019
+ def subgroup_gens(self, level):
1020
+ r"""
1021
+ Return a list of generators for the kernel of the map `(\ZZ_p / p^c)^\times
1022
+ \to (\ZZ_p / p^{c-1})^\times`.
1023
+
1024
+ INPUT:
1025
+
1026
+ - ``c`` -- integer `\ge 1`
1027
+
1028
+ EXAMPLES::
1029
+
1030
+ sage: from sage.modular.local_comp.smoothchar import SmoothCharacterGroupQp
1031
+ sage: G = SmoothCharacterGroupQp(7, QQ)
1032
+ sage: G.subgroup_gens(1)
1033
+ [3]
1034
+ sage: G.subgroup_gens(2)
1035
+ [8]
1036
+
1037
+ sage: G = SmoothCharacterGroupQp(2, QQ)
1038
+ sage: G.subgroup_gens(1)
1039
+ []
1040
+ sage: G.subgroup_gens(2)
1041
+ [3]
1042
+ sage: G.subgroup_gens(3)
1043
+ [5]
1044
+ """
1045
+ if level == 0:
1046
+ raise ValueError
1047
+ elif level == 1:
1048
+ return self.unit_gens(level)[:-1]
1049
+ else:
1050
+ return [1 + self.prime()**(level - 1)]
1051
+
1052
+ def from_dirichlet(self, chi):
1053
+ r"""
1054
+ Given a Dirichlet character `\chi`, return the factor at p of the
1055
+ adelic character `\phi` which satisfies `\phi(\varpi_\ell) =
1056
+ \chi(\ell)` for almost all `\ell`, where `\varpi_\ell` is a uniformizer
1057
+ at `\ell`.
1058
+
1059
+ More concretely, if we write `\chi = \chi_p \chi_M` as a product of
1060
+ characters of p-power, resp prime-to-p, conductor, then this function
1061
+ returns the character of `\QQ_p^\times` sending `p` to `\chi_M(p)` and
1062
+ agreeing with `\chi_p^{-1}` on integers that are 1 modulo M and coprime
1063
+ to `p`.
1064
+
1065
+ EXAMPLES::
1066
+
1067
+ sage: from sage.modular.local_comp.smoothchar import SmoothCharacterGroupQp
1068
+ sage: G = SmoothCharacterGroupQp(3, CyclotomicField(6))
1069
+ sage: G.from_dirichlet(DirichletGroup(9).0)
1070
+ Character of Q_3*, of level 2, mapping 2 |--> -zeta6 + 1, 3 |--> 1
1071
+ """
1072
+ p = self.prime()
1073
+ chi = chi.primitive_character()
1074
+ c = chi.level().valuation(p)
1075
+ M = chi.level().prime_to_m_part(p)
1076
+ return self.character(chi.conductor().valuation(p), [~chi(crt(1, x, M, p**c)) for x in self.unit_gens(c)[:-1]] + [chi(crt(p, 1, M, p**c))])
1077
+
1078
+ def quadratic_chars(self):
1079
+ r"""
1080
+ Return a list of the (non-trivial) quadratic characters in this group.
1081
+ This will be a list of 3 characters, unless `p = 2` when there are 7.
1082
+
1083
+ EXAMPLES::
1084
+
1085
+ sage: from sage.modular.local_comp.smoothchar import SmoothCharacterGroupQp
1086
+ sage: SmoothCharacterGroupQp(7, QQ).quadratic_chars()
1087
+ [Character of Q_7*, of level 0, mapping 7 |--> -1,
1088
+ Character of Q_7*, of level 1, mapping 3 |--> -1, 7 |--> -1,
1089
+ Character of Q_7*, of level 1, mapping 3 |--> -1, 7 |--> 1]
1090
+ sage: SmoothCharacterGroupQp(2, QQ).quadratic_chars()
1091
+ [Character of Q_2*, of level 0, mapping 2 |--> -1,
1092
+ Character of Q_2*, of level 2, mapping 3 |--> -1, 2 |--> -1,
1093
+ Character of Q_2*, of level 2, mapping 3 |--> -1, 2 |--> 1,
1094
+ Character of Q_2*, of level 3, mapping 7 |--> -1, 5 |--> -1, 2 |--> -1,
1095
+ Character of Q_2*, of level 3, mapping 7 |--> -1, 5 |--> -1, 2 |--> 1,
1096
+ Character of Q_2*, of level 3, mapping 7 |--> 1, 5 |--> -1, 2 |--> -1,
1097
+ Character of Q_2*, of level 3, mapping 7 |--> 1, 5 |--> -1, 2 |--> 1]
1098
+ """
1099
+ if self.prime() == 2:
1100
+ q = 3
1101
+ else:
1102
+ q = 1
1103
+ ram = [self.from_dirichlet(chi) for chi in DirichletGroup(self.prime() ** q, QQ) if not chi.is_trivial()]
1104
+ nr = self.character(0, [-1])
1105
+ return sorted([nr] + list(ram) + [f*nr for f in ram])
1106
+
1107
+
1108
+ class SmoothCharacterGroupQuadratic(SmoothCharacterGroupGeneric):
1109
+ r"""
1110
+ The group of smooth characters of `E^\times`, where `E` is a quadratic extension of `\QQ_p`.
1111
+ """
1112
+
1113
+ def discrete_log(self, level, x, gens=None):
1114
+ r"""
1115
+ Express the class of `x` in `F^\times / (1 + \mathfrak{p}^c)^\times` in
1116
+ terms of the generators returned by ``self.unit_gens(level)``, or a
1117
+ custom set of generators if given.
1118
+
1119
+ EXAMPLES::
1120
+
1121
+ sage: from sage.modular.local_comp.smoothchar import SmoothCharacterGroupUnramifiedQuadratic
1122
+ sage: G = SmoothCharacterGroupUnramifiedQuadratic(2, QQ)
1123
+ sage: G.discrete_log(0, 12)
1124
+ [2]
1125
+ sage: G.discrete_log(1, 12)
1126
+ [0, 2]
1127
+ sage: v = G.discrete_log(5, 12); v
1128
+ [0, 2, 0, 1, 2]
1129
+ sage: g = G.unit_gens(5); prod([g[i]**v[i] for i in [0..4]])/12 - 1 in G.ideal(5)
1130
+ True
1131
+ sage: G.discrete_log(3,G.number_field()([1,1]))
1132
+ [2, 0, 0, 1, 0]
1133
+ sage: H = SmoothCharacterGroupUnramifiedQuadratic(5, QQ)
1134
+ sage: x = H.number_field()([1,1]); x
1135
+ s + 1
1136
+ sage: v = H.discrete_log(5, x); v
1137
+ [22, 263, 379, 0]
1138
+ sage: h = H.unit_gens(5); prod([h[i]**v[i] for i in [0..3]])/x - 1 in H.ideal(5)
1139
+ True
1140
+
1141
+ sage: from sage.modular.local_comp.smoothchar import SmoothCharacterGroupRamifiedQuadratic
1142
+ sage: G = SmoothCharacterGroupRamifiedQuadratic(3, 1, QQ)
1143
+ sage: s = G.number_field().gen()
1144
+ sage: dl = G.discrete_log(4, 3 + 2*s)
1145
+ sage: gs = G.unit_gens(4); gs[0]^dl[0] * gs[1]^dl[1] * gs[2]^dl[2] * gs[3]^dl[3] - (3 + 2*s) in G.ideal(4)
1146
+ True
1147
+
1148
+ An example with a custom generating set::
1149
+
1150
+ sage: G.discrete_log(2, s+3, gens=[s, s+1, 2])
1151
+ [1, 2, 0]
1152
+ """
1153
+ x = self.number_field().coerce(x)
1154
+ if x == 0:
1155
+ raise ValueError( "cannot evaluate at zero" )
1156
+ if gens is None:
1157
+ n1 = x.valuation(self.ideal(1))
1158
+ x1 = x / self.unit_gens(0)[-1] ** n1
1159
+ if level == 0:
1160
+ return [n1]
1161
+ else:
1162
+ return self.ideal(level).ideallog(x1, self.unit_gens(level)[:-1]) + [n1]
1163
+ else:
1164
+ P = self.ideal(1)
1165
+ I = self.ideal(level)
1166
+ gens = [self.number_field().coerce(g) for g in gens]
1167
+ i = min(i for i in range(len(gens)) if gens[i].valuation(P) == 1) # lazy!
1168
+ pi = gens[i]
1169
+ genvals = []
1170
+ genunits = []
1171
+ for g in gens:
1172
+ genvals.append(g.valuation(P))
1173
+ gu = g / pi**genvals[-1]
1174
+ gu *= gu.denominator_ideal().element_1_mod(I)
1175
+ genunits.append(I.reduce(gu))
1176
+ xunit = x / pi**x.valuation(P)
1177
+ xunit = I.reduce(xunit * xunit.denominator_ideal().element_1_mod(I))
1178
+ verbose("computing log of %s in basis %s" % (xunit, genunits), level=1)
1179
+ dl = I.ideallog(xunit, genunits)
1180
+ pi_term = x.valuation(P) - sum(dl[j] * genvals[j] for j in range(len(gens)))
1181
+ dl[i] += pi_term
1182
+ X = prod(gens[j] ** dl[j] for j in range(len(gens)))
1183
+ assert (X/x - 1).valuation(P) >= level
1184
+ return dl
1185
+
1186
+ @cached_method
1187
+ def quotient_gens(self, n):
1188
+ r"""
1189
+ Return a list of elements of `E` which are a generating set for the
1190
+ quotient `E^\times / \QQ_p^\times`, consisting of elements which are
1191
+ "minimal" in the sense of [LW12].
1192
+
1193
+ In the examples we implement here, this quotient is almost always
1194
+ cyclic: the exceptions are the unramified quadratic extension of
1195
+ `\QQ_2` for `n \ge 3`, and the extension `\QQ_3(\sqrt{-3})` for `n \ge
1196
+ 4`.
1197
+
1198
+ EXAMPLES::
1199
+
1200
+ sage: from sage.modular.local_comp.smoothchar import SmoothCharacterGroupUnramifiedQuadratic
1201
+ sage: G = SmoothCharacterGroupUnramifiedQuadratic(7,QQ)
1202
+ sage: G.quotient_gens(1)
1203
+ [2*s - 2]
1204
+ sage: G.quotient_gens(2)
1205
+ [15*s + 21]
1206
+ sage: G.quotient_gens(3)
1207
+ [-75*s + 33]
1208
+
1209
+ A ramified case::
1210
+
1211
+ sage: from sage.modular.local_comp.smoothchar import SmoothCharacterGroupRamifiedQuadratic
1212
+ sage: G = SmoothCharacterGroupRamifiedQuadratic(7, 0, QQ)
1213
+ sage: G.quotient_gens(3)
1214
+ [22*s + 21]
1215
+
1216
+ An example where the quotient group is not cyclic::
1217
+
1218
+ sage: G = SmoothCharacterGroupUnramifiedQuadratic(2,QQ)
1219
+ sage: G.quotient_gens(1)
1220
+ [s + 1]
1221
+ sage: G.quotient_gens(2)
1222
+ [-s + 2]
1223
+ sage: G.quotient_gens(3)
1224
+ [-17*s - 14, 3*s - 2]
1225
+ """
1226
+
1227
+ # silly special case
1228
+ if n == 0:
1229
+ if self.ideal(1).norm().is_prime():
1230
+ return [self.unit_gens(0), [2]]
1231
+ else:
1232
+ return [[], []]
1233
+
1234
+ p = self.prime()
1235
+ I = self.ideal(n)
1236
+ gs = self.unit_gens(n)
1237
+ es = self.exponents(n)
1238
+ d = len(es)
1239
+
1240
+ A = ZZ**d
1241
+ R = [A.gen(i)*es[i] for i in range(d)]
1242
+ r = I.smallest_integer()
1243
+ S = [self.discrete_log(n, ZZ(s)) for s in Zmod(r).unit_gens() + (p,)]
1244
+ Q = A / A.span(R + S)
1245
+ t = None
1246
+ qgs = []
1247
+ for v in Q.gens():
1248
+ # choose a "nice" representative
1249
+ vv = v.lift()
1250
+ if vv[-1] < 0:
1251
+ vv *= -1
1252
+ while vv[-1] not in [0, 1]:
1253
+ if t is None:
1254
+ t = self.discrete_log(n, p)
1255
+ vv = [vv[i] - t[i] for i in range(d)]
1256
+ assert (Q(A(vv)) == v or Q(A(vv)) == -v)
1257
+ qgs.append( I.reduce(prod(gs[i] ** (vv[i] % es[i]) for i in range(d-1))) * gs[-1]**vv[-1] )
1258
+
1259
+ if len(qgs) == 2:
1260
+ x, y = qgs
1261
+ return [x * y, y]
1262
+ else:
1263
+ return qgs
1264
+
1265
+ def _reduce_Qp(self, level, x):
1266
+ r"""
1267
+ Utility function: given an element `x` of the number field of self,
1268
+ return an element of `\QQ_p^\times` which is congruent to `x` modulo a
1269
+ given power of the maximal ideal. An error will be raised if no such
1270
+ element exists.
1271
+
1272
+ EXAMPLES::
1273
+
1274
+ sage: from sage.modular.local_comp.smoothchar import SmoothCharacterGroupUnramifiedQuadratic
1275
+ sage: G = SmoothCharacterGroupUnramifiedQuadratic(2, QQ)
1276
+ sage: s = G.number_field().gen()
1277
+ sage: G._reduce_Qp(3, -2520*s-1007)
1278
+ 9
1279
+ sage: G._reduce_Qp(3, s)
1280
+ Traceback (most recent call last):
1281
+ ...
1282
+ ValueError: s not congruent mod Fractional ideal (8) to an elt of Qp
1283
+ """
1284
+ p = self.prime()
1285
+ r = ZZ(x.norm().valuation(p) / 2)
1286
+ y = x / p**r
1287
+ if p == 2 and y.trace().valuation(2) < 1:
1288
+ raise ValueError("%s not congruent mod %s to an elt of Qp" % (x, self.ideal(level)))
1289
+ Y = (y.trace() / 2) % self.ideal(level).smallest_integer()
1290
+ X = p**r * Y
1291
+ if not (X/x - 1).valuation(self.ideal(1)) >= level:
1292
+ if p != 2:
1293
+ raise ValueError("%s not congruent mod %s to an elt of Qp" % (x, self.ideal(level)))
1294
+ else:
1295
+ X += ZZ(2)**(r + level - 1)
1296
+ if not (X/x - 1).valuation(self.ideal(1)) >= level:
1297
+ raise ValueError("%s not congruent mod %s to an elt of Qp" % (x, self.ideal(level)))
1298
+ return X
1299
+
1300
+ def extend_character(self, level, chi, vals, check=True):
1301
+ r"""
1302
+ Return the unique character of `F^\times` which coincides with `\chi`
1303
+ on `\QQ_p^\times` and maps the generators of the quotient returned by
1304
+ :meth:`quotient_gens` to ``vals``.
1305
+
1306
+ INPUT:
1307
+
1308
+ - ``chi`` -- a smooth character of `\QQ_p`, where `p` is the residue
1309
+ characteristic of `F`, with values in the base ring of ``self`` (or some
1310
+ other ring coercible to it)
1311
+ - ``level`` -- the level of the new character (which should be at least
1312
+ the level of ``chi``)
1313
+ - ``vals`` -- a list of elements of the base ring of ``self`` (or some other
1314
+ ring coercible to it), specifying values on the quotients returned by
1315
+ :meth:`quotient_gens`
1316
+
1317
+ A :exc:`ValueError` will be raised if `x^t \ne \chi(\alpha^t)`, where `t`
1318
+ is the smallest integer such that `\alpha^t` is congruent modulo
1319
+ `p^{\rm level}` to an element of `\QQ_p`.
1320
+
1321
+ EXAMPLES:
1322
+
1323
+ We extend an unramified character of `\QQ_3^\times` to the unramified
1324
+ quadratic extension in various ways.
1325
+
1326
+ ::
1327
+
1328
+ sage: from sage.modular.local_comp.smoothchar import SmoothCharacterGroupQp, SmoothCharacterGroupUnramifiedQuadratic
1329
+ sage: chi = SmoothCharacterGroupQp(5, QQ).character(0, [7]); chi
1330
+ Character of Q_5*, of level 0, mapping 5 |--> 7
1331
+ sage: G = SmoothCharacterGroupUnramifiedQuadratic(5, QQ)
1332
+ sage: G.extend_character(1, chi, [-1])
1333
+ Character of unramified extension Q_5(s)* (s^2 + 4*s + 2 = 0), of level 1, mapping s |--> -1, 5 |--> 7
1334
+ sage: G.extend_character(2, chi, [-1])
1335
+ Character of unramified extension Q_5(s)* (s^2 + 4*s + 2 = 0), of level 1, mapping s |--> -1, 5 |--> 7
1336
+ sage: G.extend_character(3, chi, [1])
1337
+ Character of unramified extension Q_5(s)* (s^2 + 4*s + 2 = 0), of level 0, mapping 5 |--> 7
1338
+ sage: K.<z> = CyclotomicField(6); G.base_extend(K).extend_character(1, chi, [z])
1339
+ Character of unramified extension Q_5(s)* (s^2 + 4*s + 2 = 0), of level 1, mapping s |--> -z + 1, 5 |--> 7
1340
+
1341
+ We extend the nontrivial quadratic character::
1342
+
1343
+ sage: chi = SmoothCharacterGroupQp(5, QQ).character(1, [-1, 7])
1344
+ sage: K.<z> = CyclotomicField(24); G.base_extend(K).extend_character(1, chi, [z^6])
1345
+ Character of unramified extension Q_5(s)* (s^2 + 4*s + 2 = 0), of level 1, mapping s |--> -z^6, 5 |--> 7
1346
+
1347
+ Extensions of higher level::
1348
+
1349
+ sage: K.<z> = CyclotomicField(20); rho = G.base_extend(K).extend_character(2, chi, [z]); rho
1350
+ Character of unramified extension Q_5(s)* (s^2 + 4*s + 2 = 0), of level 2, mapping 11*s - 10 |--> z^5, 6 |--> 1, 5*s + 1 |--> z^4, 5 |--> 7
1351
+ sage: rho(3)
1352
+ -1
1353
+
1354
+ Examples where it doesn't work::
1355
+
1356
+ sage: G.extend_character(1, chi, [1])
1357
+ Traceback (most recent call last):
1358
+ ...
1359
+ ValueError: Invalid values for extension
1360
+
1361
+ sage: G = SmoothCharacterGroupQp(2, QQ); H = SmoothCharacterGroupUnramifiedQuadratic(2, QQ)
1362
+ sage: chi = G.character(3, [1, -1, 7])
1363
+ sage: H.extend_character(2, chi, [-1])
1364
+ Traceback (most recent call last):
1365
+ ...
1366
+ ValueError: Level of extended character cannot be smaller than level of character of Qp
1367
+ """
1368
+ chi = chi.base_extend(self.base_ring())
1369
+
1370
+ qs = self.quotient_gens(level)
1371
+ assert len(vals) == len(qs)
1372
+
1373
+ # initial sanity checks
1374
+ r = self.ideal(level).smallest_integer().valuation(self.prime())
1375
+ if chi.level() > r:
1376
+ raise ValueError("Level of extended character cannot be smaller than level of character of Qp")
1377
+
1378
+ # now do the calculation
1379
+ standard_gens = self.unit_gens(level)
1380
+ values_on_standard_gens = []
1381
+
1382
+ custom_gens = qs + chi.parent().unit_gens(r)
1383
+ values_on_custom_gens = vals + [chi(x) for x in chi.parent().unit_gens(r)]
1384
+ verbose("want to send %s to %s" % (custom_gens, values_on_custom_gens), level=1)
1385
+
1386
+ for x in standard_gens:
1387
+ d = self.discrete_log(level, x, custom_gens)
1388
+ chix = prod(values_on_custom_gens[i]**d[i] for i in range(len(d)))
1389
+ values_on_standard_gens.append(chix)
1390
+
1391
+ chiE = self.character(level, values_on_standard_gens)
1392
+ if not all( chiE(qs[i]) == vals[i] for i in range(len(qs)) ) or chiE.restrict_to_Qp() != chi:
1393
+ raise ValueError("Invalid values for extension")
1394
+ return chiE
1395
+
1396
+
1397
+ class SmoothCharacterGroupUnramifiedQuadratic(SmoothCharacterGroupQuadratic):
1398
+ r"""
1399
+ The group of smooth characters of `\QQ_{p^2}^\times`, where `\QQ_{p^2}` is
1400
+ the unique unramified quadratic extension of `\QQ_p`. We represent
1401
+ `\QQ_{p^2}^\times` internally as the completion at the prime above `p` of a
1402
+ quadratic number field, defined by (the obvious lift to `\ZZ` of) the
1403
+ Conway polynomial modulo `p` of degree 2.
1404
+
1405
+ EXAMPLES::
1406
+
1407
+ sage: from sage.modular.local_comp.smoothchar import SmoothCharacterGroupUnramifiedQuadratic
1408
+ sage: G = SmoothCharacterGroupUnramifiedQuadratic(3, QQ); G
1409
+ Group of smooth characters of unramified extension Q_3(s)* (s^2 + 2*s + 2 = 0) with values in Rational Field
1410
+ sage: G.unit_gens(3)
1411
+ [-11*s, 4, 3*s + 1, 3]
1412
+ sage: TestSuite(G).run()
1413
+ sage: TestSuite(SmoothCharacterGroupUnramifiedQuadratic(2, QQ)).run()
1414
+ """
1415
+
1416
+ def __init__(self, prime, base_ring, names='s'):
1417
+ r"""
1418
+ Standard initialisation function.
1419
+
1420
+ EXAMPLES::
1421
+
1422
+ sage: from sage.modular.local_comp.smoothchar import SmoothCharacterGroupUnramifiedQuadratic
1423
+ sage: G = SmoothCharacterGroupUnramifiedQuadratic(3, QQ, 'foo'); G
1424
+ Group of smooth characters of unramified extension Q_3(foo)* (foo^2 + 2*foo + 2 = 0) with values in Rational Field
1425
+ sage: G == loads(dumps(G))
1426
+ True
1427
+ """
1428
+ SmoothCharacterGroupGeneric.__init__(self, prime, base_ring)
1429
+ self._name = names
1430
+
1431
+ def change_ring(self, ring):
1432
+ r"""
1433
+ Return the character group of the same field, but with values in a
1434
+ different coefficient ring. This need not have anything to do with the
1435
+ original base ring, and in particular there won't generally be a
1436
+ coercion map from ``self`` to the new group -- use
1437
+ :meth:`~SmoothCharacterGroupGeneric.base_extend` if you want this.
1438
+
1439
+ EXAMPLES::
1440
+
1441
+ sage: from sage.modular.local_comp.smoothchar import SmoothCharacterGroupUnramifiedQuadratic
1442
+ sage: SmoothCharacterGroupUnramifiedQuadratic(7, Zmod(3), names='foo').change_ring(CC)
1443
+ Group of smooth characters of unramified extension Q_7(foo)* (foo^2 + 6*foo + 3 = 0) with values in Complex Field with 53 bits of precision
1444
+ """
1445
+ # We want to make sure that both G and the base-extended version have
1446
+ # the same values in the cache.
1447
+ from copy import copy
1448
+ G = SmoothCharacterGroupUnramifiedQuadratic(self.prime(), ring, self._name)
1449
+ try:
1450
+ G._cache___ideal = copy(self._cache___ideal)
1451
+ except AttributeError:
1452
+ pass
1453
+ return G
1454
+
1455
+ def _field_name(self):
1456
+ r"""
1457
+ A string representing the unit group of which this is the character group.
1458
+
1459
+ EXAMPLES::
1460
+
1461
+ sage: from sage.modular.local_comp.smoothchar import SmoothCharacterGroupUnramifiedQuadratic
1462
+ sage: SmoothCharacterGroupUnramifiedQuadratic(7, Zmod(3), 'a')._field_name()
1463
+ 'unramified extension Q_7(a)* (a^2 + 6*a + 3 = 0)'
1464
+ """
1465
+ return "unramified extension Q_%s(%s)* (%s = 0)" % (self.prime(), self._name, self.number_field().polynomial().change_variable_name(self._name))
1466
+
1467
+ def number_field(self):
1468
+ r"""
1469
+ Return a number field of which this is the completion at `p`, defined by a polynomial
1470
+ whose discriminant is not divisible by `p`.
1471
+
1472
+ EXAMPLES::
1473
+
1474
+ sage: from sage.modular.local_comp.smoothchar import SmoothCharacterGroupUnramifiedQuadratic
1475
+ sage: SmoothCharacterGroupUnramifiedQuadratic(7, QQ, 'a').number_field()
1476
+ Number Field in a with defining polynomial x^2 + 6*x + 3
1477
+ sage: SmoothCharacterGroupUnramifiedQuadratic(5, QQ, 'b').number_field()
1478
+ Number Field in b with defining polynomial x^2 + 4*x + 2
1479
+ sage: SmoothCharacterGroupUnramifiedQuadratic(2, QQ, 'c').number_field()
1480
+ Number Field in c with defining polynomial x^2 + x + 1
1481
+ """
1482
+ fbar = conway_polynomial(self.prime(), 2)
1483
+ f = PolynomialRing(QQ, 'x')([a.lift() for a in fbar])
1484
+ return NumberField(f, self._name)
1485
+
1486
+ @cached_method
1487
+ def ideal(self, c):
1488
+ r"""
1489
+ Return the ideal `p^c` of ``self.number_field()``. The result is
1490
+ cached, since we use the methods
1491
+ :meth:`~sage.rings.number_field.number_field_ideal.NumberFieldFractionalIdeal.idealstar` and
1492
+ :meth:`~sage.rings.number_field.number_field_ideal.NumberFieldFractionalIdeal.ideallog` which
1493
+ cache a Pari ``bid`` structure.
1494
+
1495
+ EXAMPLES::
1496
+
1497
+ sage: from sage.modular.local_comp.smoothchar import SmoothCharacterGroupUnramifiedQuadratic
1498
+ sage: G = SmoothCharacterGroupUnramifiedQuadratic(7, QQ, 'a'); I = G.ideal(3); I
1499
+ Fractional ideal (343)
1500
+ sage: I is G.ideal(3)
1501
+ True
1502
+ """
1503
+ return self.number_field().ideal(self.prime()**c)
1504
+
1505
+ @cached_method
1506
+ def unit_gens(self, c):
1507
+ r"""
1508
+ A list of generators `x_1, \dots, x_d` of the abelian group `F^\times /
1509
+ (1 + \mathfrak{p}^c)^\times`, where `c` is the given level, satisfying
1510
+ no relations other than `x_i^{n_i} = 1` for each `i` (where the
1511
+ integers `n_i` are returned by :meth:`exponents`). We adopt the
1512
+ convention that the final generator `x_d` is a uniformiser (and `n_d =
1513
+ 0`).
1514
+
1515
+ ALGORITHM: Use Teichmueller lifts.
1516
+
1517
+ EXAMPLES::
1518
+
1519
+ sage: from sage.modular.local_comp.smoothchar import SmoothCharacterGroupUnramifiedQuadratic
1520
+ sage: SmoothCharacterGroupUnramifiedQuadratic(7, QQ).unit_gens(0)
1521
+ [7]
1522
+ sage: SmoothCharacterGroupUnramifiedQuadratic(7, QQ).unit_gens(1)
1523
+ [s, 7]
1524
+ sage: SmoothCharacterGroupUnramifiedQuadratic(7, QQ).unit_gens(2)
1525
+ [22*s, 8, 7*s + 1, 7]
1526
+ sage: SmoothCharacterGroupUnramifiedQuadratic(7, QQ).unit_gens(3)
1527
+ [169*s + 49, 8, 7*s + 1, 7]
1528
+
1529
+ In the 2-adic case there can be more than 4 generators::
1530
+
1531
+ sage: SmoothCharacterGroupUnramifiedQuadratic(2, QQ).unit_gens(0)
1532
+ [2]
1533
+ sage: SmoothCharacterGroupUnramifiedQuadratic(2, QQ).unit_gens(1)
1534
+ [s, 2]
1535
+ sage: SmoothCharacterGroupUnramifiedQuadratic(2, QQ).unit_gens(2)
1536
+ [s, 2*s + 1, -1, 2]
1537
+ sage: SmoothCharacterGroupUnramifiedQuadratic(2, QQ).unit_gens(3)
1538
+ [s, 2*s + 1, 4*s + 1, -1, 2]
1539
+ """
1540
+ # special cases
1541
+
1542
+ p = self.prime()
1543
+ K = self.number_field()
1544
+ a = K.gen()
1545
+
1546
+ if c == 0:
1547
+ return [K(p)]
1548
+ elif c == 1:
1549
+ return [a, K(p)]
1550
+ elif p == 2:
1551
+ if c == 2:
1552
+ return [a, 1 + 2*a, K(-1), K(2)]
1553
+ else:
1554
+ return [a, 1 + 2*a, 1 + 4*a, K(-1), K(2)]
1555
+
1556
+ # general case
1557
+
1558
+ b = a
1559
+ I = self.ideal(c)
1560
+
1561
+ while b**(p**2 - 1) - 1 not in I:
1562
+ b = I.reduce(b**(self.prime()**2))
1563
+ return [b, K(1 + p), 1 + a*p, K(p)]
1564
+
1565
+ def exponents(self, c):
1566
+ r"""
1567
+ The orders `n_1, \dots, n_d` of the generators `x_i` of `F^\times / (1
1568
+ + \mathfrak{p}^c)^\times` returned by :meth:`unit_gens`.
1569
+
1570
+ EXAMPLES::
1571
+
1572
+ sage: from sage.modular.local_comp.smoothchar import SmoothCharacterGroupUnramifiedQuadratic
1573
+ sage: SmoothCharacterGroupUnramifiedQuadratic(7, QQ).exponents(2)
1574
+ [48, 7, 7, 0]
1575
+ sage: SmoothCharacterGroupUnramifiedQuadratic(2, QQ).exponents(3)
1576
+ [3, 4, 2, 2, 0]
1577
+ sage: SmoothCharacterGroupUnramifiedQuadratic(2, QQ).exponents(2)
1578
+ [3, 2, 2, 0]
1579
+ """
1580
+ p = self.prime()
1581
+ if c == 0:
1582
+ return [0]
1583
+ elif c == 1:
1584
+ return [p**2 - 1, 0]
1585
+ elif p == 2 and c >= 3:
1586
+ return [p**2 - 1, p**(c-1), p**(c-2), 2, 0]
1587
+ else:
1588
+ return [p**2 - 1, p**(c-1), p**(c-1), 0]
1589
+
1590
+ def subgroup_gens(self, level):
1591
+ r"""
1592
+ A set of elements of `(\mathcal{O}_F / \mathfrak{p}^c)^\times`
1593
+ generating the kernel of the reduction map to `(\mathcal{O}_F /
1594
+ \mathfrak{p}^{c-1})^\times`.
1595
+
1596
+ EXAMPLES::
1597
+
1598
+ sage: from sage.modular.local_comp.smoothchar import SmoothCharacterGroupUnramifiedQuadratic
1599
+ sage: SmoothCharacterGroupUnramifiedQuadratic(7, QQ).subgroup_gens(1)
1600
+ [s]
1601
+ sage: SmoothCharacterGroupUnramifiedQuadratic(7, QQ).subgroup_gens(2)
1602
+ [8, 7*s + 1]
1603
+ sage: SmoothCharacterGroupUnramifiedQuadratic(2, QQ).subgroup_gens(2)
1604
+ [3, 2*s + 1]
1605
+ """
1606
+ if level == 0:
1607
+ raise ValueError
1608
+ elif level == 1:
1609
+ return self.unit_gens(level)[:-1]
1610
+ else:
1611
+ return [1 + self.prime()**(level - 1), 1 + self.prime()**(level - 1) * self.number_field().gen()]
1612
+
1613
+
1614
+ class SmoothCharacterGroupRamifiedQuadratic(SmoothCharacterGroupQuadratic):
1615
+ r"""
1616
+ The group of smooth characters of `K^\times`, where `K` is a ramified
1617
+ quadratic extension of `\QQ_p`, and `p \ne 2`.
1618
+ """
1619
+ def __init__(self, prime, flag, base_ring, names='s'):
1620
+ r"""
1621
+ Standard initialisation function.
1622
+
1623
+ INPUT:
1624
+
1625
+ - ``prime`` -- prime integer
1626
+ - ``flag`` -- either 0 or 1
1627
+ - ``base_ring`` -- a ring
1628
+ - ``names`` -- a variable name (default: ``'s'``)
1629
+
1630
+ If ``flag`` is 0, return the group of characters of the multiplicative
1631
+ group of the field `\QQ_p(\sqrt{p})`. If ``flag`` is 1, use the
1632
+ extension `\QQ_p(\sqrt{dp})`, where `d` is `-1` (if `p = 3 \pmod 4`) or
1633
+ the smallest positive quadratic nonresidue mod `p` otherwise.
1634
+
1635
+ EXAMPLES::
1636
+
1637
+ sage: from sage.modular.local_comp.smoothchar import SmoothCharacterGroupRamifiedQuadratic
1638
+ sage: G1 = SmoothCharacterGroupRamifiedQuadratic(3, 0, QQ); G1
1639
+ Group of smooth characters of ramified extension Q_3(s)* (s^2 - 3 = 0) with values in Rational Field
1640
+ sage: G2 = SmoothCharacterGroupRamifiedQuadratic(3, 1, QQ); G2
1641
+ Group of smooth characters of ramified extension Q_3(s)* (s^2 - 6 = 0) with values in Rational Field
1642
+ sage: G3 = SmoothCharacterGroupRamifiedQuadratic(5, 1, QQ); G3
1643
+ Group of smooth characters of ramified extension Q_5(s)* (s^2 - 10 = 0) with values in Rational Field
1644
+
1645
+ TESTS:
1646
+
1647
+ .. link
1648
+
1649
+ ::
1650
+
1651
+ sage: TestSuite(G1).run()
1652
+ sage: TestSuite(G2).run()
1653
+ sage: TestSuite(G3).run()
1654
+ """
1655
+ prime = ZZ(prime)
1656
+ if prime == 2:
1657
+ raise NotImplementedError( "Wildly ramified extensions not supported" )
1658
+ SmoothCharacterGroupGeneric.__init__(self, prime, base_ring)
1659
+ self._name = names
1660
+ if flag not in [0, 1]:
1661
+ raise ValueError("Flag must be 0 (for Qp(sqrt(p)) ) or 1 (for the other ramified extension)")
1662
+ self._flag = flag
1663
+
1664
+ # Find an integer a such that sqrt(a*p) generates the right field and ZZ(sqrt(a*p)) is integrally closed
1665
+ for a in range(4 * prime):
1666
+ if (not a % prime) or (not ZZ(a).is_squarefree()) or ((a * prime) % 4 == 1):
1667
+ continue
1668
+ if (flag == 0 and Zmod(prime)(a).is_square()) or \
1669
+ (flag == 1 and not Zmod(prime)(a).is_square()):
1670
+ self._unif_sqr = a * prime
1671
+ break
1672
+ else:
1673
+ raise ValueError("Can't get here")
1674
+
1675
+ def change_ring(self, ring):
1676
+ r"""
1677
+ Return the character group of the same field, but with values in a
1678
+ different coefficient ring. This need not have anything to do with the
1679
+ original base ring, and in particular there won't generally be a
1680
+ coercion map from ``self`` to the new group -- use
1681
+ :meth:`~SmoothCharacterGroupGeneric.base_extend` if you want this.
1682
+
1683
+ EXAMPLES::
1684
+
1685
+ sage: from sage.modular.local_comp.smoothchar import SmoothCharacterGroupRamifiedQuadratic
1686
+ sage: SmoothCharacterGroupRamifiedQuadratic(7, 1, Zmod(3), names='foo').change_ring(CC)
1687
+ Group of smooth characters of ramified extension Q_7(foo)* (foo^2 - 35 = 0) with values in Complex Field with 53 bits of precision
1688
+ """
1689
+ return SmoothCharacterGroupRamifiedQuadratic(self.prime(), self._flag, ring, self._name)
1690
+
1691
+ def _field_name(self):
1692
+ r"""
1693
+ A string representing the unit group of which this is the character group.
1694
+
1695
+ EXAMPLES::
1696
+
1697
+ sage: from sage.modular.local_comp.smoothchar import SmoothCharacterGroupRamifiedQuadratic
1698
+ sage: SmoothCharacterGroupRamifiedQuadratic(7, 0, Zmod(3), 'a')._field_name()
1699
+ 'ramified extension Q_7(a)* (a^2 - 7 = 0)'
1700
+ """
1701
+ return "ramified extension Q_%s(%s)* (%s = 0)" % (self.prime(), self._name, self.number_field().polynomial().change_variable_name(self._name))
1702
+
1703
+ def number_field(self):
1704
+ r"""
1705
+ Return a number field of which this is the completion at `p`.
1706
+
1707
+ EXAMPLES::
1708
+
1709
+ sage: from sage.modular.local_comp.smoothchar import SmoothCharacterGroupRamifiedQuadratic
1710
+ sage: SmoothCharacterGroupRamifiedQuadratic(7, 0, QQ, 'a').number_field()
1711
+ Number Field in a with defining polynomial x^2 - 7
1712
+ sage: SmoothCharacterGroupRamifiedQuadratic(5, 1, QQ, 'b').number_field()
1713
+ Number Field in b with defining polynomial x^2 - 10
1714
+ sage: SmoothCharacterGroupRamifiedQuadratic(7, 1, Zmod(6), 'c').number_field()
1715
+ Number Field in c with defining polynomial x^2 - 35
1716
+ """
1717
+ from sage.rings.polynomial.polynomial_ring_constructor import PolynomialRing
1718
+ R, x = PolynomialRing(QQ, 'x').objgen()
1719
+ f = x**2 - self._unif_sqr
1720
+ return NumberField(f, self._name)
1721
+
1722
+ @cached_method
1723
+ def ideal(self, c):
1724
+ r"""
1725
+ Return the ideal `p^c` of ``self.number_field()``. The result is
1726
+ cached, since we use the methods
1727
+ :meth:`~sage.rings.number_field.number_field_ideal.NumberFieldFractionalIdeal.idealstar` and
1728
+ :meth:`~sage.rings.number_field.number_field_ideal.NumberFieldFractionalIdeal.ideallog` which
1729
+ cache a Pari ``bid`` structure.
1730
+
1731
+ EXAMPLES::
1732
+
1733
+ sage: from sage.modular.local_comp.smoothchar import SmoothCharacterGroupRamifiedQuadratic
1734
+ sage: G = SmoothCharacterGroupRamifiedQuadratic(5, 1, QQ, 'a'); I = G.ideal(3); I
1735
+ Fractional ideal (25, 5*a)
1736
+ sage: I is G.ideal(3)
1737
+ True
1738
+ """
1739
+ return self.number_field().ideal([self.prime(), self.number_field().gen()])**c
1740
+
1741
+ def unit_gens(self, c):
1742
+ r"""
1743
+ A list of generators `x_1, \dots, x_d` of the abelian group `F^\times /
1744
+ (1 + \mathfrak{p}^c)^\times`, where `c` is the given level, satisfying
1745
+ no relations other than `x_i^{n_i} = 1` for each `i` (where the
1746
+ integers `n_i` are returned by :meth:`exponents`). We adopt the
1747
+ convention that the final generator `x_d` is a uniformiser.
1748
+
1749
+ EXAMPLES::
1750
+
1751
+ sage: from sage.modular.local_comp.smoothchar import SmoothCharacterGroupRamifiedQuadratic
1752
+ sage: G = SmoothCharacterGroupRamifiedQuadratic(5, 0, QQ)
1753
+ sage: G.unit_gens(0)
1754
+ [s]
1755
+ sage: G.unit_gens(1)
1756
+ [2, s]
1757
+ sage: G.unit_gens(8)
1758
+ [2, s + 1, s]
1759
+ """
1760
+ d = ZZ(c + 1) // 2
1761
+ p = self.prime()
1762
+ K, s = self.number_field().objgen()
1763
+ zpgens = [K(ZZ(x)) for x in Zmod(p**d).unit_gens()]
1764
+ if c == 0:
1765
+ return [s]
1766
+ if c == 1:
1767
+ return zpgens + [s]
1768
+ elif p > 3 or self._unif_sqr == 3 or c <= 3:
1769
+ return zpgens + [1 + s, s]
1770
+ else:
1771
+ # Awkward case: K = Q_3(sqrt(-3)). Here the exponential map doesn't
1772
+ # converge on 1 + P, and the quotient (O_K*) / (Zp*) isn't
1773
+ # topologically cyclic. I don't know an explicit set of good
1774
+ # generators here, so we let Pari do the work and put up with the
1775
+ # rather arbitrary (nondeterministic?) results.
1776
+ return list(self.ideal(c).idealstar(2).gens_values()) + [s]
1777
+
1778
+ def exponents(self, c):
1779
+ r"""
1780
+ Return the orders of the independent generators of the unit group
1781
+ returned by :meth:`~unit_gens`.
1782
+
1783
+ EXAMPLES::
1784
+
1785
+ sage: from sage.modular.local_comp.smoothchar import SmoothCharacterGroupRamifiedQuadratic
1786
+ sage: G = SmoothCharacterGroupRamifiedQuadratic(5, 0, QQ)
1787
+ sage: G.exponents(0)
1788
+ (0,)
1789
+ sage: G.exponents(1)
1790
+ (4, 0)
1791
+ sage: G.exponents(8)
1792
+ (500, 625, 0)
1793
+ """
1794
+ c = ZZ(c)
1795
+ p = self.prime()
1796
+ if c == 0:
1797
+ return (0,)
1798
+ elif c == 1:
1799
+ return (p - 1, 0)
1800
+ elif p > 3 or self._unif_sqr == 3 or c <= 3:
1801
+ d = (c + 1) // 2
1802
+ return (p**(d - 1) * (p - 1), p**(c // 2), 0)
1803
+ else:
1804
+ # awkward case, see above
1805
+ return self.ideal(c).idealstar(2).gens_orders() + (0,)
1806
+
1807
+ def subgroup_gens(self, level):
1808
+ r"""
1809
+ A set of elements of `(\mathcal{O}_F / \mathfrak{p}^c)^\times`
1810
+ generating the kernel of the reduction map to `(\mathcal{O}_F /
1811
+ \mathfrak{p}^{c-1})^\times`.
1812
+
1813
+ EXAMPLES::
1814
+
1815
+ sage: from sage.modular.local_comp.smoothchar import SmoothCharacterGroupRamifiedQuadratic
1816
+ sage: G = SmoothCharacterGroupRamifiedQuadratic(3, 1, QQ)
1817
+ sage: G.subgroup_gens(2)
1818
+ [s + 1]
1819
+ """
1820
+ if level == 0:
1821
+ raise ValueError
1822
+ elif level == 1:
1823
+ return self.unit_gens(level)[:-1]
1824
+ else:
1825
+ return [1 + self.number_field().gen()**(level - 1)]