Path: blob/master/sage/modular/local_comp/smoothchar.py
4057 views
r"""1Smooth characters of `p`-adic fields23Let `F` be a finite extension of `\QQ_p`. Then we may consider the group of4smooth (i.e. locally constant) group homomorphisms `F^\times \to L^\times`, for5`L` any field. Such characters are important since they can be used to6parametrise smooth representations of `\mathrm{GL}_2(\QQ_p)`, which arise as7the local components of modular forms.89This module contains classes to represent such characters when `F` is `\QQ_p`10or a quadratic extension. In the latter case, we choose a quadratic extension11`K` of `\QQ` whose completion at `p` is `F`, and use Sage's wrappers of the12Pari ``idealstar`` and ``ideallog`` methods to work in the finite group13`\mathcal{O}_K / p^c` for `c \ge 0`.1415An example with characters of `\QQ_7`::1617sage: from sage.modular.local_comp.smoothchar import SmoothCharacterGroupQp18sage: K.<z> = CyclotomicField(42)19sage: G = SmoothCharacterGroupQp(7, K)20sage: G.unit_gens(2), G.exponents(2)21([3, 7], [42, 0])2223The output of the last line means that the group `\QQ_7^\times / (1 + 7^224\ZZ_7)` is isomorphic to `C_{42} \times \ZZ`, with the two factors being25generated by `3` and `7` respectively. We create a character by specifying the26images of these generators::2728sage: chi = G.character(2, [z^5, 11 + z]); chi29Character of Q_7*, of level 2, mapping 3 |--> z^5, 7 |--> z + 1130sage: chi(4)31z^832sage: chi(42)33z^10 + 11*z^93435Characters are themselves group elements, and basic arithmetic on them works::3637sage: chi**338Character of Q_7*, of level 2, mapping 3 |--> z^8 - z, 7 |--> z^3 + 33*z^2 + 363*z + 133139sage: chi.multiplicative_order()40+Infinity41"""4243import operator44from sage.structure.element import MultiplicativeGroupElement45from sage.structure.parent_base import ParentWithBase46from sage.structure.sequence import Sequence47from sage.rings.all import QQ, ZZ, Zmod, NumberField, is_Ring48from sage.misc.cachefunc import cached_method49from sage.misc.abstract_method import abstract_method50from sage.misc.misc_c import prod51from sage.categories.groups import Groups52from sage.functions.other import ceil53from sage.misc.mrange import xmrange5455from sage.structure.element import FieldElement5657class SmoothCharacterGeneric(MultiplicativeGroupElement):58r"""59A smooth (i.e. locally constant) character of `F^\times`, for `F` some60finite extension of `\QQ_p`.61"""62def __init__(self, parent, c, values_on_gens):63r"""64Standard init function.6566EXAMPLES::6768sage: from sage.modular.local_comp.smoothchar import SmoothCharacterGroupUnramifiedQuadratic69sage: G = SmoothCharacterGroupUnramifiedQuadratic(2, QQ)70sage: G.character(0, [17]) # indirect doctest71Character of unramified extension Q_2(s)* (s^2 + s + 1 = 0), of level 0, mapping 2 |--> 1772sage: G.character(1, [1, 17]) # indirect doctest73Character of unramified extension Q_2(s)* (s^2 + s + 1 = 0), of level 0, mapping 2 |--> 1774sage: G.character(2, [1, -1, 1, 17]) # indirect doctest75Character of unramified extension Q_2(s)* (s^2 + s + 1 = 0), of level 2, mapping s |--> 1, 2*s + 1 |--> -1, -1 |--> 1, 2 |--> 1776sage: G.character(2, [1, 1, 1, 17]) # indirect doctest77Character of unramified extension Q_2(s)* (s^2 + s + 1 = 0), of level 0, mapping 2 |--> 1778"""79MultiplicativeGroupElement.__init__(self, parent)80self._c = c81self._values_on_gens = values_on_gens82self._check_level()8384def _check_level(self):85r"""86Checks that this character has the level it claims to have, and if not,87decrement the level by 1. This is called by :meth:`__init__`.8889EXAMPLES::9091sage: from sage.modular.local_comp.smoothchar import SmoothCharacterGroupQp92sage: SmoothCharacterGroupQp(5, QQ).character(5, [-1, 7]) # indirect doctest93Character of Q_5*, of level 1, mapping 2 |--> -1, 5 |--> 794"""95if self.level() == 0: return96v = self.parent().subgroup_gens(self.level())97if all([self(x) == 1 for x in v]):98new_gens = self.parent().unit_gens(self.level() - 1)99new_values = [self(x) for x in new_gens]100self._values_on_gens = Sequence(new_values, universe=self.base_ring(), immutable=True)101self._c = self._c - 1102self._check_level()103104def __cmp__(self, other):105r"""106Compare self and other. Note that this only gets called when the107parents of self and other are identical.108109EXAMPLE::110111sage: from sage.modular.local_comp.smoothchar import SmoothCharacterGroupQp, SmoothCharacterGroupUnramifiedQuadratic112sage: SmoothCharacterGroupQp(7, Zmod(3)).character(1, [2, 1]) == SmoothCharacterGroupQp(7, ZZ).character(1, [-1, 1])113True114sage: chi1 = SmoothCharacterGroupUnramifiedQuadratic(7, QQ).character(0, [1])115sage: chi2 = SmoothCharacterGroupQp(7, QQ).character(0, [1])116sage: chi1 == chi2117False118sage: chi2.parent()(chi1) == chi2119True120sage: chi1 == loads(dumps(chi1))121True122"""123assert other.parent() is self.parent()124return cmp(self.level(), other.level()) or cmp(self._values_on_gens, other._values_on_gens)125126def multiplicative_order(self):127r"""128Return the order of this character as an element of the character group.129130EXAMPLE::131132sage: from sage.modular.local_comp.smoothchar import SmoothCharacterGroupQp133sage: K.<z> = CyclotomicField(42)134sage: G = SmoothCharacterGroupQp(7, K)135sage: G.character(3, [z^10 - z^3, 11]).multiplicative_order()136+Infinity137sage: G.character(3, [z^10 - z^3, 1]).multiplicative_order()13842139sage: G.character(1, [z^7, z^14]).multiplicative_order()1406141sage: G.character(0, [1]).multiplicative_order()1421143"""144from sage.rings.arith import lcm145from sage.rings.infinity import Infinity146if self._values_on_gens[-1].multiplicative_order() == Infinity:147return Infinity148else:149return lcm([x.multiplicative_order() for x in self._values_on_gens])150151def level(self):152r"""153Return the level of this character, i.e. the smallest integer `c \ge 0`154such that it is trivial on `1 + \mathfrak{p}^c`.155156EXAMPLES::157158sage: from sage.modular.local_comp.smoothchar import SmoothCharacterGroupQp159sage: SmoothCharacterGroupQp(7, QQ).character(2, [-1, 1]).level()1601161"""162return self._c163164def __call__(self, x):165r"""166Evaluate the character at ``x``, which should be a nonzero element of167the number field of the parent group.168169EXAMPLES::170171sage: from sage.modular.local_comp.smoothchar import SmoothCharacterGroupQp172sage: K.<z> = CyclotomicField(42)173sage: chi = SmoothCharacterGroupQp(7, K).character(3, [z^10 - z^3, 11])174sage: [chi(x) for x in [1, 2, 3, 9, 21, 1/12345678]]175[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]176177Non-examples::178179sage: chi(QuadraticField(-1,'i').gen())180Traceback (most recent call last):181...182TypeError: no canonical coercion from Number Field in i with defining polynomial x^2 + 1 to Rational Field183sage: chi(0)184Traceback (most recent call last):185...186ValueError: cannot evaluate at zero187sage: chi(Mod(1, 12))188Traceback (most recent call last):189...190TypeError: no canonical coercion from Ring of integers modulo 12 to Rational Field191192Some examples with an unramified quadratic extension, where the choice193of generators is arbitrary (but deterministic)::194195sage: from sage.modular.local_comp.smoothchar import SmoothCharacterGroupUnramifiedQuadratic196sage: K.<z> = CyclotomicField(30)197sage: G = SmoothCharacterGroupUnramifiedQuadratic(5, K)198sage: chi = G.character(2, [z**5, z**(-6), z**6, 3]); chi199Character 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 |--> 3200sage: chi(G.unit_gens(2)[0]**7 / G.unit_gens(2)[1]/5)2011/3*z^6 - 1/3*z202sage: chi(2)203-z^3204"""205v = self.parent().discrete_log(self.level(), x)206return prod([self._values_on_gens[i] ** v[i] for i in xrange(len(v))])207208def _repr_(self):209r"""210String representation of this character.211212EXAMPLES::213214sage: from sage.modular.local_comp.smoothchar import SmoothCharacterGroupQp215sage: K.<z> = CyclotomicField(20)216sage: SmoothCharacterGroupQp(5, K).character(2, [z, z+1])._repr_()217'Character of Q_5*, of level 2, mapping 2 |--> z, 5 |--> z + 1'218219Examples over field extensions::220221sage: from sage.modular.local_comp.smoothchar import SmoothCharacterGroupUnramifiedQuadratic222sage: K.<z> = CyclotomicField(15)223sage: SmoothCharacterGroupUnramifiedQuadratic(5, K).character(2, [z**5, z**3, 1, z+1])._repr_()224'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'225"""226gens = self.parent().unit_gens(self.level())227mapst = ", ".join( str(gens[i]) + ' |--> ' + str(self._values_on_gens[i]) for i in range(len(gens)) )228return "Character of %s, of level %s, mapping %s" % (self.parent()._field_name(), self.level(), mapst)229230def _mul_(self, other):231r"""232Product of self and other.233234EXAMPLES::235236sage: from sage.modular.local_comp.smoothchar import SmoothCharacterGroupQp237sage: K.<z> = CyclotomicField(20)238sage: chi1 = SmoothCharacterGroupQp(5, K).character(2, [z, z+1])239sage: chi2 = SmoothCharacterGroupQp(5, K).character(2, [z^4, 3])240sage: chi1 * chi2 # indirect doctest241Character of Q_5*, of level 1, mapping 2 |--> z^5, 5 |--> 3*z + 3242sage: chi2 * chi1 # indirect doctest243Character of Q_5*, of level 1, mapping 2 |--> z^5, 5 |--> 3*z + 3244sage: chi1 * SmoothCharacterGroupQp(5, QQ).character(2, [-1, 7]) # indirect doctest245Character of Q_5*, of level 2, mapping 2 |--> -z, 5 |--> 7*z + 7246"""247if other.level() > self.level():248return other * self249return self.parent().character(self.level(), [self(x) * other(x) for x in self.parent().unit_gens(self.level())])250251def __invert__(self):252r"""253Multiplicative inverse of self.254255EXAMPLES::256257sage: from sage.modular.local_comp.smoothchar import SmoothCharacterGroupUnramifiedQuadratic258sage: K.<z> = CyclotomicField(12)259sage: chi = SmoothCharacterGroupUnramifiedQuadratic(2, K).character(4, [z**4, z**3, z**9, -1, 7]); chi260Character 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 |--> 7261sage: chi**(-1) # indirect doctest262Character 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/7263sage: SmoothCharacterGroupUnramifiedQuadratic(2, QQ).character(0, [7]) / chi # indirect doctest264Character 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 |--> 1265"""266return self.parent().character(self.level(), [~self(x) for x in self.parent().unit_gens(self.level())])267268def restrict_to_Qp(self):269r"""270Return the restriction of this character to `\QQ_p^\times`, embedded as271a subfield of `F^\times`.272273EXAMPLE::274275sage: from sage.modular.local_comp.smoothchar import SmoothCharacterGroupRamifiedQuadratic276sage: SmoothCharacterGroupRamifiedQuadratic(3, 0, QQ).character(0, [2]).restrict_to_Qp()277Character of Q_3*, of level 0, mapping 3 |--> 4278"""279G = SmoothCharacterGroupQp(self.parent().prime(), self.base_ring())280ugs = G.unit_gens(self.level())281return G.character(self.level(), [self(x) for x in ugs])282283def galois_conjugate(self):284r"""285Return the composite of this character with the order `2` automorphism of286`K / \QQ_p` (assuming `K` is quadratic).287288Note that this is the Galois operation on the *domain*, not on the289*codomain*.290291EXAMPLE::292293sage: from sage.modular.local_comp.smoothchar import SmoothCharacterGroupUnramifiedQuadratic294sage: K.<w> = CyclotomicField(3)295sage: G = SmoothCharacterGroupUnramifiedQuadratic(2, K)296sage: chi = G.character(2, [w, -1,-1, 3*w])297sage: chi2 = chi.galois_conjugate(); chi2298Character 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*w299300sage: chi.restrict_to_Qp() == chi2.restrict_to_Qp()301True302sage: chi * chi2 == chi.parent().compose_with_norm(chi.restrict_to_Qp())303True304"""305K,s = self.parent().number_field().objgen()306if K.absolute_degree() != 2:307raise ValueError( "Character must be defined on a quadratic extension" )308sigs = K.embeddings(K)309sig = [x for x in sigs if x(s) != s][0]310return self.parent().character(self.level(), [self(sig(x)) for x in self.parent().unit_gens(self.level())])311312313class SmoothCharacterGroupGeneric(ParentWithBase):314r"""315The group of smooth (i.e. locally constant) characters of a `p`-adic field,316with values in some ring `R`. This is an abstract base class and should not317be instantiated directly.318"""319320Element = SmoothCharacterGeneric321322def __init__(self, p, base_ring):323r"""324TESTS::325326sage: from sage.modular.local_comp.smoothchar import SmoothCharacterGroupGeneric327sage: G = SmoothCharacterGroupGeneric(3, QQ)328sage: SmoothCharacterGroupGeneric(3, "hello")329Traceback (most recent call last):330...331TypeError: base ring (=hello) must be a ring332"""333if not is_Ring(base_ring):334raise TypeError( "base ring (=%s) must be a ring" % base_ring )335ParentWithBase.__init__(self, base=base_ring, category=Groups())336if not (p in ZZ and ZZ(p).is_prime()):337raise ValueError( "p (=%s) must be a prime integer" % p )338self._p = ZZ.coerce(p)339340def _element_constructor_(self, x):341r"""342Construct an element of this group from ``x`` (possibly noncanonically).343This only works if ``x`` is a character of a field containing the field of344self, whose values lie in a field that can be converted into self.345346EXAMPLES::347348sage: from sage.modular.local_comp.smoothchar import SmoothCharacterGroupQp349sage: K.<i> = QuadraticField(-1)350sage: G = SmoothCharacterGroupQp(3, QQ)351sage: GK = SmoothCharacterGroupQp(3, K)352sage: chi = GK(G.character(0, [4])); chi # indirect doctest353Character of Q_3*, of level 0, mapping 3 |--> 4354sage: chi.parent() is GK355True356sage: G(GK.character(0, [7])) # indirect doctest357Character of Q_3*, of level 0, mapping 3 |--> 7358sage: G(GK.character(0, [i])) # indirect doctest359Traceback (most recent call last):360...361TypeError: Unable to coerce i to a rational362"""363if x == 1:364return self.character(0, [1])365if hasattr(x, 'parent') \366and isinstance(x.parent(), SmoothCharacterGroupGeneric) \367and x.parent().number_field().has_coerce_map_from(self.number_field()):368return self.character(x.level(), [x(v) for v in self.unit_gens(x.level())])369else:370raise TypeError371372def __cmp__(self, other):373r"""374TESTS::375376sage: from sage.modular.local_comp.smoothchar import SmoothCharacterGroupQp377sage: G = SmoothCharacterGroupQp(3, QQ)378sage: G == SmoothCharacterGroupQp(3, QQ[I])379False380sage: G == 7381False382sage: G == SmoothCharacterGroupQp(7, QQ)383False384sage: G == SmoothCharacterGroupQp(3, QQ)385True386"""387return cmp(type(self), type(other)) \388or cmp(self.prime(), other.prime()) \389or cmp(self.number_field(), other.number_field()) \390or cmp(self.base_ring(), other.base_ring())391392def _coerce_map_from_(self, other):393r"""394Return True if self has a canonical coerce map from other.395396EXAMPLES::397398sage: from sage.modular.local_comp.smoothchar import SmoothCharacterGroupQp399sage: K.<i> = QuadraticField(-1)400sage: G = SmoothCharacterGroupQp(3, QQ)401sage: GK = SmoothCharacterGroupQp(3, K)402sage: G.has_coerce_map_from(GK)403False404sage: GK.has_coerce_map_from(G)405True406sage: GK.coerce(G.character(0, [4]))407Character of Q_3*, of level 0, mapping 3 |--> 4408sage: G.coerce(GK.character(0, [4]))409Traceback (most recent call last):410...411TypeError: no canonical coercion from Group of smooth characters of Q_3* with values in Number Field in i with defining polynomial x^2 + 1 to Group of smooth characters of Q_3* with values in Rational Field412sage: G.character(0, [4]) in GK # indirect doctest413True414415The coercion framework handles base extension, so we test that too::416417sage: K.<i> = QuadraticField(-1)418sage: from sage.modular.local_comp.smoothchar import SmoothCharacterGroupUnramifiedQuadratic419sage: G = SmoothCharacterGroupUnramifiedQuadratic(3, QQ)420sage: G.character(0, [1]).base_extend(K)421Character of unramified extension Q_3(s)* (s^2 + 2*s + 2 = 0), of level 0, mapping 3 |--> 1422423"""424if isinstance(other, SmoothCharacterGroupGeneric) \425and other.number_field() == self.number_field() \426and self.base_ring().has_coerce_map_from(other.base_ring()):427return True428else:429return False430431def prime(self):432r"""433The residue characteristic of the underlying field.434435EXAMPLE::436437sage: from sage.modular.local_comp.smoothchar import SmoothCharacterGroupGeneric438sage: SmoothCharacterGroupGeneric(3, QQ).prime()4393440"""441return self._p442443@abstract_method444def change_ring(self, ring):445r"""446Return the character group of the same field, but with values in a447different coefficient ring. To be implemented by all derived classes448(since the generic base class can't know the parameters).449450EXAMPLE::451452sage: from sage.modular.local_comp.smoothchar import SmoothCharacterGroupGeneric453sage: SmoothCharacterGroupGeneric(3, QQ).change_ring(ZZ)454Traceback (most recent call last):455...456NotImplementedError: <abstract method change_ring at ...>457"""458pass459460def base_extend(self, ring):461r"""462Return the character group of the same field, but with values in a new463coefficient ring into which the old coefficient ring coerces. An error464will be raised if there is no coercion map from the old coefficient465ring to the new one.466467EXAMPLE::468469sage: from sage.modular.local_comp.smoothchar import SmoothCharacterGroupQp470sage: G = SmoothCharacterGroupQp(3, QQ)471sage: G.base_extend(QQbar)472Group of smooth characters of Q_3* with values in Algebraic Field473sage: G.base_extend(Zmod(3))474Traceback (most recent call last):475...476TypeError: no canonical coercion from Rational Field to Ring of integers modulo 3477478"""479if not ring.has_coerce_map_from(self.base_ring()) :480ring.coerce(self.base_ring().an_element())481# this is here to flush out errors482483return self.change_ring(ring)484485@abstract_method486def _field_name(self):487r"""488A string representing the name of the p-adic field of which this is the489character group. To be overridden by derived subclasses.490491EXAMPLE::492493sage: from sage.modular.local_comp.smoothchar import SmoothCharacterGroupGeneric494sage: SmoothCharacterGroupGeneric(3, QQ)._field_name()495Traceback (most recent call last):496...497NotImplementedError: <abstract method _field_name at ...>498"""499pass500501def _repr_(self):502r"""503String representation of self.504505EXAMPLE::506507sage: from sage.modular.local_comp.smoothchar import SmoothCharacterGroupQp508sage: SmoothCharacterGroupQp(7, QQ)._repr_()509'Group of smooth characters of Q_7* with values in Rational Field'510"""511return "Group of smooth characters of %s with values in %s" % (self._field_name(), self.base_ring())512513@abstract_method514def ideal(self, level):515r"""516Return the ``level``-th power of the maximal ideal of the ring of517integers of the p-adic field. Since we approximate by using number518field arithmetic, what is actually returned is an ideal in a number519field.520521EXAMPLE::522523sage: from sage.modular.local_comp.smoothchar import SmoothCharacterGroupGeneric524sage: SmoothCharacterGroupGeneric(3, QQ).ideal(3)525Traceback (most recent call last):526...527NotImplementedError: <abstract method ideal at ...>528"""529pass530531@abstract_method532def unit_gens(self, level):533r"""534A list of generators `x_1, \dots, x_d` of the abelian group `F^\times /535(1 + \mathfrak{p}^c)^\times`, where `c` is the given level, satisfying536no relations other than `x_i^{n_i} = 1` for each `i` (where the537integers `n_i` are returned by :meth:`exponents`). We adopt the538convention that the final generator `x_d` is a uniformiser (and `n_d =5390`).540541EXAMPLE::542543sage: from sage.modular.local_comp.smoothchar import SmoothCharacterGroupGeneric544sage: SmoothCharacterGroupGeneric(3, QQ).unit_gens(3)545Traceback (most recent call last):546...547NotImplementedError: <abstract method unit_gens at ...>548"""549pass550551@abstract_method552def exponents(self, level):553r"""554The orders `n_1, \dots, n_d` of the generators `x_i` of `F^\times / (1555+ \mathfrak{p}^c)^\times` returned by :meth:`unit_gens`.556557EXAMPLE::558559sage: from sage.modular.local_comp.smoothchar import SmoothCharacterGroupGeneric560sage: SmoothCharacterGroupGeneric(3, QQ).exponents(3)561Traceback (most recent call last):562...563NotImplementedError: <abstract method exponents at ...>564"""565pass566567@abstract_method568def subgroup_gens(self, level):569r"""570A set of elements of `(\mathcal{O}_F / \mathfrak{p}^c)^\times`571generating the kernel of the reduction map to `(\mathcal{O}_F /572\mathfrak{p}^{c-1})^\times`.573574EXAMPLE::575576sage: from sage.modular.local_comp.smoothchar import SmoothCharacterGroupGeneric577sage: SmoothCharacterGroupGeneric(3, QQ).subgroup_gens(3)578Traceback (most recent call last):579...580NotImplementedError: <abstract method subgroup_gens at ...>581"""582pass583584@abstract_method585def discrete_log(self, level):586r"""587Given an element `x \in F^\times` (lying in the number field `K` of588which `F` is a completion, see module docstring), express the class of589`x` in terms of the generators of `F^\times / (1 +590\mathfrak{p}^c)^\times` returned by :meth:`unit_gens`.591592This should be overridden by all derived classes. The method should593first attempt to canonically coerce `x` into ``self.number_field()``,594and check that the result is not zero.595596EXAMPLE::597598sage: from sage.modular.local_comp.smoothchar import SmoothCharacterGroupGeneric599sage: SmoothCharacterGroupGeneric(3, QQ).discrete_log(3)600Traceback (most recent call last):601...602NotImplementedError: <abstract method discrete_log at ...>603"""604pass605606def character(self, level, values_on_gens):607r"""608Return the unique character of the given level whose values on the609generators returned by ``self.unit_gens(level)`` are610``values_on_gens``.611612INPUT:613614- ``level`` (integer) an integer `\ge 0`615- ``values_on_gens`` (sequence) a sequence of elements of length equal616to the length of ``self.unit_gens(level)``. The values should be617convertible (that is, possibly noncanonically) into the base ring of self; they618should all be units, and all but the last must be roots of unity (of619the orders given by ``self.exponents(level)``.620621.. note::622623The character returned may have level less than ``level`` in general.624625EXAMPLES::626627sage: from sage.modular.local_comp.smoothchar import SmoothCharacterGroupQp628sage: K.<z> = CyclotomicField(42)629sage: G = SmoothCharacterGroupQp(7, K)630sage: G.character(2, [z^6, 8])631Character of Q_7*, of level 2, mapping 3 |--> z^6, 7 |--> 8632sage: G.character(2, [z^7, 8])633Character of Q_7*, of level 1, mapping 3 |--> z^7, 7 |--> 8634635Non-examples::636637sage: G.character(1, [z, 1])638Traceback (most recent call last):639...640ValueError: value on generator 3 (=z) should be a root of unity of order 6641sage: G.character(1, [1, 0])642Traceback (most recent call last):643...644ValueError: value on uniformiser 7 (=0) should be a unit645646An example with a funky coefficient ring::647648sage: G = SmoothCharacterGroupQp(7, Zmod(9))649sage: G.character(1, [2, 2])650Character of Q_7*, of level 1, mapping 3 |--> 2, 7 |--> 2651sage: G.character(1, [2, 3])652Traceback (most recent call last):653...654ValueError: value on uniformiser 7 (=3) should be a unit655656TESTS::657658sage: G.character(1, [2])659Traceback (most recent call last):660...661AssertionError: 2 images must be given662"""663S = Sequence(values_on_gens, universe=self.base_ring(), immutable=True)664assert len(S) == len(self.unit_gens(level)), "{0} images must be given".format(len(self.unit_gens(level)))665n = self.exponents(level)666for i in xrange(len(S)):667if n[i] != 0 and not S[i]**n[i] == 1:668raise ValueError( "value on generator %s (=%s) should be a root of unity of order %s" % (self.unit_gens(level)[i], S[i], n[i]) )669elif n[i] == 0 and not S[i].is_unit():670raise ValueError( "value on uniformiser %s (=%s) should be a unit" % (self.unit_gens(level)[i], S[i]) )671return self.element_class(self, level, S)672673def _an_element_(self):674r"""675Return an element of this group. Required by the coercion machinery.676677EXAMPLE::678679sage: from sage.modular.local_comp.smoothchar import SmoothCharacterGroupQp680sage: K.<z> = CyclotomicField(42)681sage: G = SmoothCharacterGroupQp(7, K)682sage: G.an_element() # indirect doctest683Character of Q_7*, of level 0, mapping 7 |--> z684"""685return self.character(0, [self.base_ring().an_element()])686687688689def _test_unitgens(self, **options):690r"""691Test that the generators returned by ``unit_gens`` are consistent with692the exponents returned by ``exponents``.693694EXAMPLE::695696sage: from sage.modular.local_comp.smoothchar import SmoothCharacterGroupUnramifiedQuadratic697sage: SmoothCharacterGroupUnramifiedQuadratic(2, Zmod(8))._test_unitgens()698"""699T = self._tester(**options)700for c in xrange(6):701gens = self.unit_gens(c)702exps = self.exponents(c)703T.assert_(exps[-1] == 0)704T.assert_(all([u != 0 for u in exps[:-1]]))705T.assert_(all([u.parent() is self.number_field() for u in gens]))706707I = self.ideal(c)708for i in xrange(len(exps[:-1])):709g = gens[i]710for m in xrange(1, exps[i]):711if (g - 1 in I):712T.fail("For generator g=%s, g^%s = %s = 1 mod I, but order should be %s" % (gens[i], m, g, exps[i]))713g = g * gens[i]714# reduce g mod I715if hasattr(I, "small_residue"):716g = I.small_residue(g)717else: # I is an ideal of ZZ718g = g % (I.gen())719if not (g - 1 in I):720T.fail("For generator g=%s, g^%s = %s, which is not 1 mod I" % (gens[i], exps[i], g))721I = self.prime() if self.number_field() == QQ else self.ideal(1)722T.assert_(gens[-1].valuation(I) == 1)723724# This implicitly tests that the gens really are gens!725_ = self.discrete_log(c, -1)726727def _test_subgroupgens(self, **options):728r"""729Test that the values returned by :meth:`~subgroup_gens` are valid.730731EXAMPLE::732733sage: from sage.modular.local_comp.smoothchar import SmoothCharacterGroupQp734sage: SmoothCharacterGroupQp(2, CC)._test_subgroupgens()735"""736T = self._tester(**options)737for c in xrange(1, 6):738sgs = self.subgroup_gens(c)739I2 = self.ideal(c-1)740T.assert_(all([x-1 in I2 for x in sgs]), "Kernel gens at level %s not in kernel!" % c)741742# now find the exponent of the kernel743744n1 = prod(self.exponents(c)[:-1])745n2 = prod(self.exponents(c-1)[:-1])746n = n1 // n2747# if c > 1, n will be a prime here, so that logs below gets calculated correctly748749logs = []750for idx in xmrange(len(sgs)*[n]):751y = prod( map(operator.pow, sgs, idx) )752L = tuple(self.discrete_log(c, y))753if L not in logs:754logs.append(L)755T.assert_(n2 * len(logs) == n1, "Kernel gens at level %s don't generate everything!" % c)756757def compose_with_norm(self, chi):758r"""759Calculate the character of `K^\times` given by `\chi \circ \mathrm{Norm}_{K/\QQ_p}`.760Here `K` should be a quadratic extension and `\chi` a character of `\QQ_p^\times`.761762EXAMPLE:763764When `K` is the unramified quadratic extension, the level of the new character is the same as the old::765766sage: from sage.modular.local_comp.smoothchar import SmoothCharacterGroupQp, SmoothCharacterGroupRamifiedQuadratic, SmoothCharacterGroupUnramifiedQuadratic767sage: K.<w> = CyclotomicField(6)768sage: G = SmoothCharacterGroupQp(3, K)769sage: chi = G.character(2, [w, 5])770sage: H = SmoothCharacterGroupUnramifiedQuadratic(3, K)771sage: H.compose_with_norm(chi)772Character 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 |--> 25773774In ramified cases, the level of the new character may be larger:775776.. link777778::779780sage: H = SmoothCharacterGroupRamifiedQuadratic(3, 0, K)781sage: H.compose_with_norm(chi)782Character of ramified extension Q_3(s)* (s^2 - 3 = 0), of level 3, mapping 2 |--> w - 1, s + 1 |--> -w, s |--> -5783784On the other hand, since norm is not surjective, the result can even be trivial:785786.. link787788::789790sage: chi = G.character(1, [-1, -1]); chi791Character of Q_3*, of level 1, mapping 2 |--> -1, 3 |--> -1792sage: H.compose_with_norm(chi)793Character of ramified extension Q_3(s)* (s^2 - 3 = 0), of level 0, mapping s |--> 1794"""795if chi.parent().number_field() != QQ: raise ValueError796if self.number_field().absolute_degree() != 2: raise ValueError797n = chi.level()798P = chi.parent().prime() ** n799m = self.number_field()(P).valuation(self.ideal(1))800return self.character(m, [chi(x.norm(QQ)) for x in self.unit_gens(m)])801802class SmoothCharacterGroupQp(SmoothCharacterGroupGeneric):803r"""804The group of smooth characters of `\QQ_p^\times`, with values in some fixed805base ring.806807EXAMPLES::808809sage: from sage.modular.local_comp.smoothchar import SmoothCharacterGroupQp810sage: G = SmoothCharacterGroupQp(7, QQ); G811Group of smooth characters of Q_7* with values in Rational Field812sage: TestSuite(G).run()813sage: G == loads(dumps(G))814True815"""816def unit_gens(self, level):817r"""818Return a set of generators `x_1, \dots, x_d` for `\QQ_p^\times / (1 +819p^c \ZZ_p)^\times`. These must be independent in the sense that there820are no relations between them other than relations of the form821`x_i^{n_i} = 1`. They need not, however, be in Smith normal form.822823EXAMPLE::824825sage: from sage.modular.local_comp.smoothchar import SmoothCharacterGroupQp826sage: SmoothCharacterGroupQp(7, QQ).unit_gens(3)827[3, 7]828sage: SmoothCharacterGroupQp(2, QQ).unit_gens(4)829[15, 5, 2]830"""831if level == 0:832return [QQ(self.prime())]833else:834return [QQ(x) for x in Zmod(self.prime()**level).unit_gens()] + [QQ(self.prime())]835836def exponents(self, level):837r"""838Return the exponents of the generators returned by :meth:`unit_gens`.839840EXAMPLE::841842sage: from sage.modular.local_comp.smoothchar import SmoothCharacterGroupQp843sage: SmoothCharacterGroupQp(7, QQ).exponents(3)844[294, 0]845sage: SmoothCharacterGroupQp(2, QQ).exponents(4)846[2, 4, 0]847"""848if level == 0: return [0]849return [x.multiplicative_order() for x in Zmod(self.prime()**level).unit_gens()] + [0]850851def change_ring(self, ring):852r"""853Return the group of characters of the same field but with values in a854different ring. This need not have anything to do with the original855base ring, and in particular there won't generally be a coercion map856from self to the new group -- use857:meth:`~SmoothCharacterGroupGeneric.base_extend` if you want this.858859EXAMPLE::860861sage: from sage.modular.local_comp.smoothchar import SmoothCharacterGroupQp862sage: SmoothCharacterGroupQp(7, Zmod(3)).change_ring(CC)863Group of smooth characters of Q_7* with values in Complex Field with 53 bits of precision864"""865return SmoothCharacterGroupQp(self.prime(), ring)866867def number_field(self):868r"""869Return the number field used for calculations (a dense subfield of the870local field of which this is the character group). In this case, this871is always the rational field.872873EXAMPLE::874875sage: from sage.modular.local_comp.smoothchar import SmoothCharacterGroupQp876sage: SmoothCharacterGroupQp(7, Zmod(3)).number_field()877Rational Field878"""879return QQ880881def ideal(self, level):882r"""883Return the ``level``-th power of the maximal ideal. Since we884approximate by using rational arithmetic, what is actually returned is885an ideal of `\ZZ`.886887EXAMPLE::888889sage: from sage.modular.local_comp.smoothchar import SmoothCharacterGroupQp890sage: SmoothCharacterGroupQp(7, Zmod(3)).ideal(2)891Principal ideal (49) of Integer Ring892"""893return ZZ.ideal(self.prime() ** level)894895def _field_name(self):896r"""897Return a string representation of the field unit group of which this is898the character group.899900EXAMPLE::901902sage: from sage.modular.local_comp.smoothchar import SmoothCharacterGroupQp903sage: SmoothCharacterGroupQp(7, Zmod(3))._field_name()904'Q_7*'905"""906return "Q_%s*" % self.prime()907908def discrete_log(self, level, x):909r"""910Express the class of `x` in `\QQ_p^\times / (1 + p^c)^\times` in terms911of the generators returned by :meth:`unit_gens`.912913EXAMPLE::914915sage: from sage.modular.local_comp.smoothchar import SmoothCharacterGroupQp916sage: G = SmoothCharacterGroupQp(7, QQ)917sage: G.discrete_log(0, 14)918[1]919sage: G.discrete_log(1, 14)920[2, 1]921sage: G.discrete_log(5, 14)922[9308, 1]923"""924x = self.number_field().coerce(x)925if x == 0: raise ValueError( "cannot evaluate at zero" )926s = x.valuation(self.prime())927return Zmod(self.prime()**level)(x / self.prime()**s).generalised_log() + [s]928929def subgroup_gens(self, level):930r"""931Return a list of generators for the kernel of the map `(\ZZ_p / p^c)^\times932\to (\ZZ_p / p^{c-1})^\times`.933934INPUT:935936- ``c`` (integer) an integer `\ge 1`937938EXAMPLES::939940sage: from sage.modular.local_comp.smoothchar import SmoothCharacterGroupQp941sage: G = SmoothCharacterGroupQp(7, QQ)942sage: G.subgroup_gens(1)943[3]944sage: G.subgroup_gens(2)945[8]946947sage: G = SmoothCharacterGroupQp(2, QQ)948sage: G.subgroup_gens(1)949[]950sage: G.subgroup_gens(2)951[3]952sage: G.subgroup_gens(3)953[5]954"""955if level == 0:956raise ValueError957elif level == 1:958return self.unit_gens(level)[:-1]959else:960return [1 + self.prime()**(level - 1)]961962class SmoothCharacterGroupUnramifiedQuadratic(SmoothCharacterGroupGeneric):963r"""964The group of smooth characters of `\QQ_{p^2}^\times`, where `\QQ_{p^2}` is965the unique unramified quadratic extension of `\QQ_p`. We represent966`\QQ_{p^2}^\times` internally as the completion at the prime above `p` of a967quadratic number field, defined by (the obvious lift to `\ZZ` of) the968Conway polynomial modulo `p` of degree 2.969970EXAMPLE::971972sage: from sage.modular.local_comp.smoothchar import SmoothCharacterGroupUnramifiedQuadratic973sage: G = SmoothCharacterGroupUnramifiedQuadratic(3, QQ); G974Group of smooth characters of unramified extension Q_3(s)* (s^2 + 2*s + 2 = 0) with values in Rational Field975sage: G.unit_gens(3)976[-11*s, 4, 3*s + 1, 3]977sage: TestSuite(G).run()978sage: TestSuite(SmoothCharacterGroupUnramifiedQuadratic(2, QQ)).run()979"""980981def __init__(self, prime, base_ring, names='s'):982r"""983Standard initialisation function.984985EXAMPLE::986987sage: from sage.modular.local_comp.smoothchar import SmoothCharacterGroupUnramifiedQuadratic988sage: G = SmoothCharacterGroupUnramifiedQuadratic(3, QQ, 'foo'); G989Group of smooth characters of unramified extension Q_3(foo)* (foo^2 + 2*foo + 2 = 0) with values in Rational Field990sage: G == loads(dumps(G))991True992"""993SmoothCharacterGroupGeneric.__init__(self, prime, base_ring)994self._name = names995996def change_ring(self, ring):997r"""998Return the character group of the same field, but with values in a999different coefficient ring. This need not have anything to do with the1000original base ring, and in particular there won't generally be a1001coercion map from self to the new group -- use1002:meth:`~SmoothCharacterGroupGeneric.base_extend` if you want this.10031004EXAMPLE::10051006sage: from sage.modular.local_comp.smoothchar import SmoothCharacterGroupUnramifiedQuadratic1007sage: SmoothCharacterGroupUnramifiedQuadratic(7, Zmod(3), names='foo').change_ring(CC)1008Group of smooth characters of unramified extension Q_7(foo)* (foo^2 + 6*foo + 3 = 0) with values in Complex Field with 53 bits of precision1009"""1010# We want to make sure that both G and the base-extended version have1011# the same values in the cache.1012from copy import copy1013G = SmoothCharacterGroupUnramifiedQuadratic(self.prime(), ring, self._name)1014try:1015G._cache___ideal = copy(self._cache___ideal)1016except AttributeError:1017pass1018return G10191020def _field_name(self):1021r"""1022A string representing the unit group of which this is the character group.10231024EXAMPLE::10251026sage: from sage.modular.local_comp.smoothchar import SmoothCharacterGroupUnramifiedQuadratic1027sage: SmoothCharacterGroupUnramifiedQuadratic(7, Zmod(3), 'a')._field_name()1028'unramified extension Q_7(a)* (a^2 + 6*a + 3 = 0)'1029"""1030return "unramified extension Q_%s(%s)* (%s = 0)" % (self.prime(), self._name, self.number_field().polynomial().change_variable_name(self._name))10311032def number_field(self):1033r"""1034Return a number field of which this is the completion at `p`, defined by a polynomial1035whose discriminant is not divisible by `p`.10361037EXAMPLES::10381039sage: from sage.modular.local_comp.smoothchar import SmoothCharacterGroupUnramifiedQuadratic1040sage: SmoothCharacterGroupUnramifiedQuadratic(7, QQ, 'a').number_field()1041Number Field in a with defining polynomial x^2 + 6*x + 31042sage: SmoothCharacterGroupUnramifiedQuadratic(5, QQ, 'b').number_field()1043Number Field in b with defining polynomial x^2 + 4*x + 21044sage: SmoothCharacterGroupUnramifiedQuadratic(2, QQ, 'c').number_field()1045Number Field in c with defining polynomial x^2 + x + 11046"""1047from sage.rings.all import conway_polynomial, PolynomialRing1048fbar = conway_polynomial(self.prime(), 2)1049f = PolynomialRing(QQ,'x')([a.lift() for a in fbar])1050return NumberField(f, self._name)10511052@cached_method1053def ideal(self, c):1054r"""1055Return the ideal `p^c` of ``self.number_field()``. The result is1056cached, since we use the methods1057:meth:`~sage.rings.number_field.number_field_ideal.NumberFieldFractionalIdeal.idealstar` and1058:meth:`~sage.rings.number_field.number_field_ideal.NumberFieldFractionalIdeal.ideallog` which1059cache a Pari ``bid`` structure.10601061EXAMPLES::10621063sage: from sage.modular.local_comp.smoothchar import SmoothCharacterGroupUnramifiedQuadratic1064sage: G = SmoothCharacterGroupUnramifiedQuadratic(7, QQ, 'a'); I = G.ideal(3); I1065Fractional ideal (343)1066sage: I is G.ideal(3)1067True1068"""1069return self.number_field().ideal(self.prime()**c)10701071@cached_method1072def unit_gens(self, c):1073r"""1074A list of generators `x_1, \dots, x_d` of the abelian group `F^\times /1075(1 + \mathfrak{p}^c)^\times`, where `c` is the given level, satisfying1076no relations other than `x_i^{n_i} = 1` for each `i` (where the1077integers `n_i` are returned by :meth:`exponents`). We adopt the1078convention that the final generator `x_d` is a uniformiser (and `n_d =10790`).10801081ALGORITHM: Use Teichmueller lifts.10821083EXAMPLE::10841085sage: from sage.modular.local_comp.smoothchar import SmoothCharacterGroupUnramifiedQuadratic1086sage: SmoothCharacterGroupUnramifiedQuadratic(7, QQ).unit_gens(0)1087[7]1088sage: SmoothCharacterGroupUnramifiedQuadratic(7, QQ).unit_gens(1)1089[s, 7]1090sage: SmoothCharacterGroupUnramifiedQuadratic(7, QQ).unit_gens(2)1091[22*s, 8, 7*s + 1, 7]1092sage: SmoothCharacterGroupUnramifiedQuadratic(7, QQ).unit_gens(3)1093[169*s + 49, 8, 7*s + 1, 7]10941095In the 2-adic case there can be more than 4 generators::10961097sage: SmoothCharacterGroupUnramifiedQuadratic(2, QQ).unit_gens(0)1098[2]1099sage: SmoothCharacterGroupUnramifiedQuadratic(2, QQ).unit_gens(1)1100[s, 2]1101sage: SmoothCharacterGroupUnramifiedQuadratic(2, QQ).unit_gens(2)1102[s, 2*s + 1, -1, 2]1103sage: SmoothCharacterGroupUnramifiedQuadratic(2, QQ).unit_gens(3)1104[s, 2*s + 1, 4*s + 1, -1, 2]1105"""1106# special cases11071108p = self.prime()1109K = self.number_field()1110a = K.gen()11111112if c == 0:1113return [K(p)]1114elif c == 1:1115return [a, K(p)]1116elif p == 2:1117if c == 2:1118return [a, 1 + 2*a, K(-1), K(2)]1119else:1120return [a, 1 + 2*a, 1 + 4*a, K(-1), K(2)]11211122# general case11231124b = a1125I = self.ideal(c)11261127while b**(p**2 - 1) - 1 not in I:1128b = I.reduce(b**(self.prime()**2))1129return [b, K(1 + p), 1 + a*p, K(p)]11301131def exponents(self, c):1132r"""1133The orders `n_1, \dots, n_d` of the generators `x_i` of `F^\times / (11134+ \mathfrak{p}^c)^\times` returned by :meth:`unit_gens`.11351136EXAMPLE::11371138sage: from sage.modular.local_comp.smoothchar import SmoothCharacterGroupUnramifiedQuadratic1139sage: SmoothCharacterGroupUnramifiedQuadratic(7, QQ).exponents(2)1140[48, 7, 7, 0]1141sage: SmoothCharacterGroupUnramifiedQuadratic(2, QQ).exponents(3)1142[3, 4, 2, 2, 0]1143sage: SmoothCharacterGroupUnramifiedQuadratic(2, QQ).exponents(2)1144[3, 2, 2, 0]1145"""1146p = self.prime()1147if c == 0: return [0]1148elif c == 1: return [p**2 - 1, 0]1149elif p == 2 and c >= 3:1150return [p**2 - 1, p**(c-1), p**(c-2), 2, 0]1151else: return [p**2 - 1, p**(c-1), p**(c-1),0]11521153def subgroup_gens(self, level):1154r"""1155A set of elements of `(\mathcal{O}_F / \mathfrak{p}^c)^\times`1156generating the kernel of the reduction map to `(\mathcal{O}_F /1157\mathfrak{p}^{c-1})^\times`.11581159EXAMPLE::11601161sage: from sage.modular.local_comp.smoothchar import SmoothCharacterGroupUnramifiedQuadratic1162sage: SmoothCharacterGroupUnramifiedQuadratic(7, QQ).subgroup_gens(1)1163[s]1164sage: SmoothCharacterGroupUnramifiedQuadratic(7, QQ).subgroup_gens(2)1165[8, 7*s + 1]1166sage: SmoothCharacterGroupUnramifiedQuadratic(2, QQ).subgroup_gens(2)1167[3, 2*s + 1]1168"""1169if level == 0:1170raise ValueError1171elif level == 1:1172return self.unit_gens(level)[:-1]1173else:1174return [1 + self.prime()**(level - 1), 1 + self.prime()**(level - 1) * self.number_field().gen()]11751176def quotient_gen(self, level):1177r"""1178Find an element generating the quotient11791180.. math::11811182\mathcal{O}_F^\times / \ZZ_p^\times \cdot (1 + p^c \mathcal{O}_F),11831184where `c` is the given level.11851186EXAMPLE::11871188sage: from sage.modular.local_comp.smoothchar import SmoothCharacterGroupUnramifiedQuadratic1189sage: G = SmoothCharacterGroupUnramifiedQuadratic(7,QQ)1190sage: G.quotient_gen(1)1191s1192sage: G.quotient_gen(2)1193-20*s - 211194sage: G.quotient_gen(3)1195-69*s - 7011961197For `p = 2` an error will be raised for level `\ge 3`, as the quotient is not cyclic::11981199sage: G = SmoothCharacterGroupUnramifiedQuadratic(2,QQ)1200sage: G.quotient_gen(1)1201s1202sage: G.quotient_gen(2)1203-s + 21204sage: G.quotient_gen(3)1205Traceback (most recent call last):1206...1207ValueError: Quotient group not cyclic1208"""1209if level == 0:1210raise ValueError( "Quotient group is trivial" )1211elif self.prime() == 2 and level >= 3:1212raise ValueError( "Quotient group not cyclic" )1213elif level == 1:1214return self.unit_gens(level)[0]1215else:1216return self.ideal(level).reduce(self.unit_gens(level)[0] * (1 + self.prime() * self.number_field().gen()))12171218def extend_character(self, level, chi, x, check=True):1219r"""1220Return the unique character of `F^\times` which coincides with `\chi`1221on `\QQ_p^\times` and maps the generator `\alpha` returned by1222:meth:`quotient_gen` to `x`.12231224INPUT:12251226- ``chi``: a smooth character of `\QQ_p`, where `p` is the residue1227characteristic of `F`, with values in the base ring of self (or some1228other ring coercible to it)1229- ``level``: the level of the new character (which should be at least1230the level of ``chi``)1231- ``x``: an element of the base ring of self (or some other ring1232coercible to it).12331234A ``ValueError`` will be raised if `x^t \ne \chi(\alpha^t)`, where `t`1235is the smallest integer such that `\alpha^t` is congruent modulo1236`p^{\rm level}` to an element of `\QQ_p`.12371238EXAMPLES:12391240We extend an unramified character of `\QQ_3^\times` to the unramified1241quadratic extension in various ways.12421243::12441245sage: from sage.modular.local_comp.smoothchar import SmoothCharacterGroupQp, SmoothCharacterGroupUnramifiedQuadratic1246sage: chi = SmoothCharacterGroupQp(5, QQ).character(0, [7]); chi1247Character of Q_5*, of level 0, mapping 5 |--> 71248sage: G = SmoothCharacterGroupUnramifiedQuadratic(5, QQ)1249sage: G.extend_character(1, chi, -1)1250Character of unramified extension Q_5(s)* (s^2 + 4*s + 2 = 0), of level 1, mapping s |--> -1, 5 |--> 71251sage: G.extend_character(2, chi, -1)1252Character of unramified extension Q_5(s)* (s^2 + 4*s + 2 = 0), of level 1, mapping s |--> -1, 5 |--> 71253sage: G.extend_character(3, chi, 1)1254Character of unramified extension Q_5(s)* (s^2 + 4*s + 2 = 0), of level 0, mapping 5 |--> 71255sage: K.<z> = CyclotomicField(6); G.base_extend(K).extend_character(1, chi, z)1256Character of unramified extension Q_5(s)* (s^2 + 4*s + 2 = 0), of level 1, mapping s |--> z, 5 |--> 712571258We extend the nontrivial quadratic character::12591260sage: chi = SmoothCharacterGroupQp(5, QQ).character(1, [-1, 7])1261sage: K.<z> = CyclotomicField(24); G.base_extend(K).extend_character(1, chi, z^6)1262Character of unramified extension Q_5(s)* (s^2 + 4*s + 2 = 0), of level 1, mapping s |--> z^6, 5 |--> 712631264Extensions of higher level::12651266sage: K.<z> = CyclotomicField(20); rho = G.base_extend(K).extend_character(2, chi, z); rho1267Character 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^6, 5 |--> 71268sage: rho(3)1269-112701271Examples where it doesn't work::12721273sage: G.extend_character(1, chi, 1)1274Traceback (most recent call last):1275...1276ValueError: Value at s must satisfy x^6 = chi(2) = -1, but it does not12771278sage: G = SmoothCharacterGroupQp(2, QQ); H = SmoothCharacterGroupUnramifiedQuadratic(2, QQ)1279sage: chi = G.character(3, [1, -1, 7])1280sage: H.extend_character(2, chi, -1)1281Traceback (most recent call last):1282...1283ValueError: Level of extended character cannot be smaller than level of character of Qp1284"""1285chi = chi.base_extend(self.base_ring())1286if chi.level() > level:1287raise ValueError, "Level of extended character cannot be smaller than level of character of Qp"12881289# check it makes sense1290e = (self.prime() + 1) * (self.prime()**(level - 1))1291v = self.ideal(level).reduce(self.quotient_gen(level) ** e)12921293v = QQ(v)1294if x**e != chi(v):1295raise ValueError( "Value at %s must satisfy x^%s = chi(%s) = %s, but it does not" % (self.quotient_gen(level), e, v, chi(v)) )12961297# now do the calculation1298values_on_standard_gens = []1299other_gens = [self.quotient_gen(level)] + [ZZ(z) for z in Zmod(self.prime()**level).unit_gens()]1300values_on_other_gens = [x] + [chi(u) for u in other_gens[1:]]1301for s in self.unit_gens(level)[:-1]:1302t = self.ideal(level).ideallog(s, other_gens)1303values_on_standard_gens.append( prod([values_on_other_gens[i] ** t[i] for i in xrange(len(t))]) )1304values_on_standard_gens.append(chi(self.prime()))1305chiE = self.character(level, values_on_standard_gens)13061307# check it makes sense (optional but on by default)1308if check:1309assert chiE(self.quotient_gen(level)) == x1310assert chiE.restrict_to_Qp() == chi13111312return chiE13131314def discrete_log(self, level, x):1315r"""1316Express the class of `x` in `F^\times / (1 + \mathfrak{p}^c)^\times` in1317terms of the generators returned by ``self.unit_gens(level)``.13181319EXAMPLE::13201321sage: from sage.modular.local_comp.smoothchar import SmoothCharacterGroupUnramifiedQuadratic1322sage: G = SmoothCharacterGroupUnramifiedQuadratic(2, QQ)1323sage: G.discrete_log(0, 12)1324[2]1325sage: G.discrete_log(1, 12)1326[0, 2]1327sage: v = G.discrete_log(5, 12); v1328[0, 2, 0, 1, 2]1329sage: g = G.unit_gens(5); prod([g[i]**v[i] for i in [0..4]])/12 - 1 in G.ideal(5)1330True1331sage: G.discrete_log(3,G.number_field()([1,1]))1332[2, 0, 0, 1, 0]1333sage: H = SmoothCharacterGroupUnramifiedQuadratic(5, QQ)1334sage: x = H.number_field()([1,1]); x1335s + 11336sage: v = H.discrete_log(5, x); v1337[22, 263, 379, 0]1338sage: h = H.unit_gens(5); prod([h[i]**v[i] for i in [0..3]])/x - 1 in H.ideal(5)1339True1340"""1341x = self.number_field().coerce(x)1342if x == 0: raise ValueError( "cannot evaluate at zero" )1343n1 = x.valuation(self.number_field().ideal(self.prime()))1344x1 = x / self.prime() ** n11345if level == 0:1346return [n1]1347else:1348return self.ideal(level).ideallog(x1, self.unit_gens(level)[:-1]) + [n1]134913501351class SmoothCharacterGroupRamifiedQuadratic(SmoothCharacterGroupGeneric):1352r"""1353The group of smooth characters of `K^\times`, where `K` is a ramified1354quadratic extension of `\QQ_p`, and `p \ne 2`.1355"""1356def __init__(self, prime, flag, base_ring, names='s'):1357r"""1358Standard initialisation function.13591360INPUT:13611362- ``prime`` -- a prime integer1363- ``flag`` -- either 0 or 11364- ``base_ring`` -- a ring1365- ``names`` -- a variable name (default ``s``)13661367If ``flag`` is 0, return the group of characters of the multiplicative1368group of the field `\QQ_p(\sqrt{p})`. If ``flag`` is 1, use the1369extension `\QQ_p(\sqrt{dp})`, where `d` is `-1` (if `p = 3 \pmod 4`) or1370the smallest positive quadratic nonresidue mod `p` otherwise.13711372EXAMPLE::13731374sage: from sage.modular.local_comp.smoothchar import SmoothCharacterGroupRamifiedQuadratic1375sage: G1 = SmoothCharacterGroupRamifiedQuadratic(3, 0, QQ); G11376Group of smooth characters of ramified extension Q_3(s)* (s^2 - 3 = 0) with values in Rational Field1377sage: G2 = SmoothCharacterGroupRamifiedQuadratic(3, 1, QQ); G21378Group of smooth characters of ramified extension Q_3(s)* (s^2 + 3 = 0) with values in Rational Field1379sage: G3 = SmoothCharacterGroupRamifiedQuadratic(5, 1, QQ); G31380Group of smooth characters of ramified extension Q_5(s)* (s^2 - 10 = 0) with values in Rational Field13811382TESTS:13831384.. link13851386::13871388sage: TestSuite(G1).run()1389sage: TestSuite(G2).run()1390sage: TestSuite(G3).run()1391"""1392if prime == 2: raise NotImplementedError( "Wildly ramified extensions not supported" )1393SmoothCharacterGroupGeneric.__init__(self, prime, base_ring)1394self._name = names1395if flag not in [0, 1]:1396raise ValueError( "Flag must be 0 (for Qp(sqrt(p)) ) or 1 (for the other ramified extension)" )1397self._flag = flag1398if flag == 0:1399self._unif_sqr = self.prime()1400else:1401if self.prime() % 4 == 3:1402self._unif_sqr = -self.prime()1403else:1404self._unif_sqr = ZZ(Zmod(self.prime()).quadratic_nonresidue()) * self.prime()14051406def change_ring(self, ring):1407r"""1408Return the character group of the same field, but with values in a1409different coefficient ring. This need not have anything to do with the1410original base ring, and in particular there won't generally be a1411coercion map from self to the new group -- use1412:meth:`~SmoothCharacterGroupGeneric.base_extend` if you want this.14131414EXAMPLE::14151416sage: from sage.modular.local_comp.smoothchar import SmoothCharacterGroupRamifiedQuadratic1417sage: SmoothCharacterGroupRamifiedQuadratic(7, 1, Zmod(3), names='foo').change_ring(CC)1418Group of smooth characters of ramified extension Q_7(foo)* (foo^2 + 7 = 0) with values in Complex Field with 53 bits of precision1419"""1420return SmoothCharacterGroupRamifiedQuadratic(self.prime(), self._flag, ring, self._name)14211422def _field_name(self):1423r"""1424A string representing the unit group of which this is the character group.14251426EXAMPLE::14271428sage: from sage.modular.local_comp.smoothchar import SmoothCharacterGroupRamifiedQuadratic1429sage: SmoothCharacterGroupRamifiedQuadratic(7, 0, Zmod(3), 'a')._field_name()1430'ramified extension Q_7(a)* (a^2 - 7 = 0)'1431"""1432return "ramified extension Q_%s(%s)* (%s = 0)" % (self.prime(), self._name, self.number_field().polynomial().change_variable_name(self._name))14331434def number_field(self):1435r"""1436Return a number field of which this is the completion at `p`.14371438EXAMPLES::14391440sage: from sage.modular.local_comp.smoothchar import SmoothCharacterGroupRamifiedQuadratic1441sage: SmoothCharacterGroupRamifiedQuadratic(7, 0, QQ, 'a').number_field()1442Number Field in a with defining polynomial x^2 - 71443sage: SmoothCharacterGroupRamifiedQuadratic(5, 1, QQ, 'b').number_field()1444Number Field in b with defining polynomial x^2 - 101445sage: SmoothCharacterGroupRamifiedQuadratic(7, 1, Zmod(6), 'c').number_field()1446Number Field in c with defining polynomial x^2 + 71447"""1448from sage.rings.all import PolynomialRing1449R, x = PolynomialRing(QQ, 'x').objgen()1450f = x**2 - self._unif_sqr1451return NumberField(f, self._name)14521453@cached_method1454def ideal(self, c):1455r"""1456Return the ideal `p^c` of ``self.number_field()``. The result is1457cached, since we use the methods1458:meth:`~sage.rings.number_field.number_field_ideal.NumberFieldFractionalIdeal.idealstar` and1459:meth:`~sage.rings.number_field.number_field_ideal.NumberFieldFractionalIdeal.ideallog` which1460cache a Pari ``bid`` structure.14611462EXAMPLES::14631464sage: from sage.modular.local_comp.smoothchar import SmoothCharacterGroupRamifiedQuadratic1465sage: G = SmoothCharacterGroupRamifiedQuadratic(5, 1, QQ, 'a'); I = G.ideal(3); I1466Fractional ideal (25, 5*a)1467sage: I is G.ideal(3)1468True1469"""1470return self.number_field().ideal([self.prime(), self.number_field().gen()])**c14711472def unit_gens(self, c):1473r"""1474A list of generators `x_1, \dots, x_d` of the abelian group `F^\times /1475(1 + \mathfrak{p}^c)^\times`, where `c` is the given level, satisfying1476no relations other than `x_i^{n_i} = 1` for each `i` (where the1477integers `n_i` are returned by :meth:`exponents`). We adopt the1478convention that the final generator `x_d` is a uniformiser.14791480EXAMPLE::14811482sage: from sage.modular.local_comp.smoothchar import SmoothCharacterGroupRamifiedQuadratic1483sage: G = SmoothCharacterGroupRamifiedQuadratic(5, 0, QQ)1484sage: G.unit_gens(0)1485[s]1486sage: G.unit_gens(1)1487[2, s]1488sage: G.unit_gens(8)1489[2, s + 1, s]1490"""1491d = ceil(ZZ(c) / 2)1492p = self.prime()1493K,s = self.number_field().objgen()1494zpgens = [K(ZZ(x)) for x in Zmod(p**d).unit_gens()]1495if c == 0:1496return [s]1497if c == 1:1498return zpgens + [s]1499elif p > 3 or self._unif_sqr == 3 or c <= 3:1500return zpgens + [1 + s, s]1501else:1502# Awkward case: K = Q_3(sqrt(-3)). Here the exponential map doesn't1503# converge on 1 + P, and the quotient (O_K*) / (Zp*) isn't1504# topologically cyclic. I don't know an explicit set of good1505# generators here, so we let Pari do the work and put up with the1506# rather arbitrary (nondeterministic?) results.1507return list(self.ideal(c).idealstar(2).gens()) + [s]15081509def exponents(self, c):1510r"""1511Return the orders of the independent generators of the unit group1512returned by :meth:`~unit_gens`.15131514EXAMPLE::15151516sage: from sage.modular.local_comp.smoothchar import SmoothCharacterGroupRamifiedQuadratic1517sage: G = SmoothCharacterGroupRamifiedQuadratic(5, 0, QQ)1518sage: G.exponents(0)1519[0]1520sage: G.exponents(1)1521[4, 0]1522sage: G.exponents(8)1523[500, 625, 0]1524"""1525c = ZZ(c)1526d = ceil(c / 2)1527p = self.prime()1528if c == 0:1529return [0]1530elif c == 1:1531return [p - 1, 0]1532elif p > 3 or self._unif_sqr == 3 or c <= 3:1533return [p**(d-1)*(p - 1), p**ceil((c - 1)/2), 0]1534else:1535# awkward case, see above1536return self.ideal(c).idealstar(2).invariants() + [0]15371538def subgroup_gens(self, level):1539r"""1540A set of elements of `(\mathcal{O}_F / \mathfrak{p}^c)^\times`1541generating the kernel of the reduction map to `(\mathcal{O}_F /1542\mathfrak{p}^{c-1})^\times`.15431544EXAMPLE::15451546sage: from sage.modular.local_comp.smoothchar import SmoothCharacterGroupRamifiedQuadratic1547sage: G = SmoothCharacterGroupRamifiedQuadratic(3, 1, QQ)1548sage: G.subgroup_gens(2)1549[s + 1]1550"""1551if level == 0:1552raise ValueError1553elif level == 1:1554return self.unit_gens(level)[:-1]1555else:1556return [1 + self.number_field().gen()**(level - 1)]15571558def discrete_log(self, level, x):1559r"""1560Solve the discrete log problem in the unit group.15611562EXAMPLE::15631564sage: from sage.modular.local_comp.smoothchar import SmoothCharacterGroupRamifiedQuadratic1565sage: G = SmoothCharacterGroupRamifiedQuadratic(3, 1, QQ)1566sage: s = G.number_field().gen()1567sage: G.discrete_log(4, 3 + 2*s)1568[5, 2, 1, 1]1569sage: gs = G.unit_gens(4); gs[0]^5 * gs[1]^2 * gs[2] * gs[3] - (3 + 2*s) in G.ideal(4)1570True1571"""1572x = self.number_field().coerce(x)1573if x == 0: raise ValueError, "cannot evaluate at zero"1574n1 = x.valuation(self.ideal(1))1575x1 = x / self.number_field().gen()**n11576if level == 0:1577return [n1]1578else:1579return self.ideal(level).ideallog(x1, self.unit_gens(level)[:-1]) + [n1]158015811582