Path: blob/master/src/sage/modular/local_comp/smoothchar.py
8821 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, NumberField48from sage.rings.ring import is_Ring49from sage.misc.cachefunc import cached_method50from sage.misc.abstract_method import abstract_method51from sage.misc.misc_c import prod52from sage.categories.groups import Groups53from sage.functions.other import ceil54from sage.misc.mrange import xmrange5556from sage.structure.element import FieldElement5758class SmoothCharacterGeneric(MultiplicativeGroupElement):59r"""60A smooth (i.e. locally constant) character of `F^\times`, for `F` some61finite extension of `\QQ_p`.62"""63def __init__(self, parent, c, values_on_gens):64r"""65Standard init function.6667EXAMPLES::6869sage: from sage.modular.local_comp.smoothchar import SmoothCharacterGroupUnramifiedQuadratic70sage: G = SmoothCharacterGroupUnramifiedQuadratic(2, QQ)71sage: G.character(0, [17]) # indirect doctest72Character of unramified extension Q_2(s)* (s^2 + s + 1 = 0), of level 0, mapping 2 |--> 1773sage: G.character(1, [1, 17]) # indirect doctest74Character of unramified extension Q_2(s)* (s^2 + s + 1 = 0), of level 0, mapping 2 |--> 1775sage: G.character(2, [1, -1, 1, 17]) # indirect doctest76Character of unramified extension Q_2(s)* (s^2 + s + 1 = 0), of level 2, mapping s |--> 1, 2*s + 1 |--> -1, -1 |--> 1, 2 |--> 1777sage: G.character(2, [1, 1, 1, 17]) # indirect doctest78Character of unramified extension Q_2(s)* (s^2 + s + 1 = 0), of level 0, mapping 2 |--> 1779"""80MultiplicativeGroupElement.__init__(self, parent)81self._c = c82self._values_on_gens = values_on_gens83self._check_level()8485def _check_level(self):86r"""87Checks that this character has the level it claims to have, and if not,88decrement the level by 1. This is called by :meth:`__init__`.8990EXAMPLES::9192sage: from sage.modular.local_comp.smoothchar import SmoothCharacterGroupQp93sage: SmoothCharacterGroupQp(5, QQ).character(5, [-1, 7]) # indirect doctest94Character of Q_5*, of level 1, mapping 2 |--> -1, 5 |--> 795"""96if self.level() == 0: return97v = self.parent().subgroup_gens(self.level())98if all([self(x) == 1 for x in v]):99new_gens = self.parent().unit_gens(self.level() - 1)100new_values = [self(x) for x in new_gens]101self._values_on_gens = Sequence(new_values, universe=self.base_ring(), immutable=True)102self._c = self._c - 1103self._check_level()104105def __cmp__(self, other):106r"""107Compare self and other. Note that this only gets called when the108parents of self and other are identical.109110EXAMPLE::111112sage: from sage.modular.local_comp.smoothchar import SmoothCharacterGroupQp, SmoothCharacterGroupUnramifiedQuadratic113sage: SmoothCharacterGroupQp(7, Zmod(3)).character(1, [2, 1]) == SmoothCharacterGroupQp(7, ZZ).character(1, [-1, 1])114True115sage: chi1 = SmoothCharacterGroupUnramifiedQuadratic(7, QQ).character(0, [1])116sage: chi2 = SmoothCharacterGroupQp(7, QQ).character(0, [1])117sage: chi1 == chi2118False119sage: chi2.parent()(chi1) == chi2120True121sage: chi1 == loads(dumps(chi1))122True123"""124assert other.parent() is self.parent()125return cmp(self.level(), other.level()) or cmp(self._values_on_gens, other._values_on_gens)126127def multiplicative_order(self):128r"""129Return the order of this character as an element of the character group.130131EXAMPLE::132133sage: from sage.modular.local_comp.smoothchar import SmoothCharacterGroupQp134sage: K.<z> = CyclotomicField(42)135sage: G = SmoothCharacterGroupQp(7, K)136sage: G.character(3, [z^10 - z^3, 11]).multiplicative_order()137+Infinity138sage: G.character(3, [z^10 - z^3, 1]).multiplicative_order()13942140sage: G.character(1, [z^7, z^14]).multiplicative_order()1416142sage: G.character(0, [1]).multiplicative_order()1431144"""145from sage.rings.arith import lcm146from sage.rings.infinity import Infinity147if self._values_on_gens[-1].multiplicative_order() == Infinity:148return Infinity149else:150return lcm([x.multiplicative_order() for x in self._values_on_gens])151152def level(self):153r"""154Return the level of this character, i.e. the smallest integer `c \ge 0`155such that it is trivial on `1 + \mathfrak{p}^c`.156157EXAMPLES::158159sage: from sage.modular.local_comp.smoothchar import SmoothCharacterGroupQp160sage: SmoothCharacterGroupQp(7, QQ).character(2, [-1, 1]).level()1611162"""163return self._c164165def __call__(self, x):166r"""167Evaluate the character at ``x``, which should be a nonzero element of168the number field of the parent group.169170EXAMPLES::171172sage: from sage.modular.local_comp.smoothchar import SmoothCharacterGroupQp173sage: K.<z> = CyclotomicField(42)174sage: chi = SmoothCharacterGroupQp(7, K).character(3, [z^10 - z^3, 11])175sage: [chi(x) for x in [1, 2, 3, 9, 21, 1/12345678]]176[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]177178Non-examples::179180sage: chi(QuadraticField(-1,'i').gen())181Traceback (most recent call last):182...183TypeError: no canonical coercion from Number Field in i with defining polynomial x^2 + 1 to Rational Field184sage: chi(0)185Traceback (most recent call last):186...187ValueError: cannot evaluate at zero188sage: chi(Mod(1, 12))189Traceback (most recent call last):190...191TypeError: no canonical coercion from Ring of integers modulo 12 to Rational Field192193Some examples with an unramified quadratic extension, where the choice194of generators is arbitrary (but deterministic)::195196sage: from sage.modular.local_comp.smoothchar import SmoothCharacterGroupUnramifiedQuadratic197sage: K.<z> = CyclotomicField(30)198sage: G = SmoothCharacterGroupUnramifiedQuadratic(5, K)199sage: chi = G.character(2, [z**5, z**(-6), z**6, 3]); chi200Character 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 |--> 3201sage: chi(G.unit_gens(2)[0]**7 / G.unit_gens(2)[1]/5)2021/3*z^6 - 1/3*z203sage: chi(2)204-z^3205"""206v = self.parent().discrete_log(self.level(), x)207return prod([self._values_on_gens[i] ** v[i] for i in xrange(len(v))])208209def _repr_(self):210r"""211String representation of this character.212213EXAMPLES::214215sage: from sage.modular.local_comp.smoothchar import SmoothCharacterGroupQp216sage: K.<z> = CyclotomicField(20)217sage: SmoothCharacterGroupQp(5, K).character(2, [z, z+1])._repr_()218'Character of Q_5*, of level 2, mapping 2 |--> z, 5 |--> z + 1'219220Examples over field extensions::221222sage: from sage.modular.local_comp.smoothchar import SmoothCharacterGroupUnramifiedQuadratic223sage: K.<z> = CyclotomicField(15)224sage: SmoothCharacterGroupUnramifiedQuadratic(5, K).character(2, [z**5, z**3, 1, z+1])._repr_()225'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'226"""227gens = self.parent().unit_gens(self.level())228mapst = ", ".join( str(gens[i]) + ' |--> ' + str(self._values_on_gens[i]) for i in range(len(gens)) )229return "Character of %s, of level %s, mapping %s" % (self.parent()._field_name(), self.level(), mapst)230231def _mul_(self, other):232r"""233Product of self and other.234235EXAMPLES::236237sage: from sage.modular.local_comp.smoothchar import SmoothCharacterGroupQp238sage: K.<z> = CyclotomicField(20)239sage: chi1 = SmoothCharacterGroupQp(5, K).character(2, [z, z+1])240sage: chi2 = SmoothCharacterGroupQp(5, K).character(2, [z^4, 3])241sage: chi1 * chi2 # indirect doctest242Character of Q_5*, of level 1, mapping 2 |--> z^5, 5 |--> 3*z + 3243sage: chi2 * chi1 # indirect doctest244Character of Q_5*, of level 1, mapping 2 |--> z^5, 5 |--> 3*z + 3245sage: chi1 * SmoothCharacterGroupQp(5, QQ).character(2, [-1, 7]) # indirect doctest246Character of Q_5*, of level 2, mapping 2 |--> -z, 5 |--> 7*z + 7247"""248if other.level() > self.level():249return other * self250return self.parent().character(self.level(), [self(x) * other(x) for x in self.parent().unit_gens(self.level())])251252def __invert__(self):253r"""254Multiplicative inverse of self.255256EXAMPLES::257258sage: from sage.modular.local_comp.smoothchar import SmoothCharacterGroupUnramifiedQuadratic259sage: K.<z> = CyclotomicField(12)260sage: chi = SmoothCharacterGroupUnramifiedQuadratic(2, K).character(4, [z**4, z**3, z**9, -1, 7]); chi261Character 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 |--> 7262sage: chi**(-1) # indirect doctest263Character 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/7264sage: SmoothCharacterGroupUnramifiedQuadratic(2, QQ).character(0, [7]) / chi # indirect doctest265Character 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 |--> 1266"""267return self.parent().character(self.level(), [~self(x) for x in self.parent().unit_gens(self.level())])268269def restrict_to_Qp(self):270r"""271Return the restriction of this character to `\QQ_p^\times`, embedded as272a subfield of `F^\times`.273274EXAMPLE::275276sage: from sage.modular.local_comp.smoothchar import SmoothCharacterGroupRamifiedQuadratic277sage: SmoothCharacterGroupRamifiedQuadratic(3, 0, QQ).character(0, [2]).restrict_to_Qp()278Character of Q_3*, of level 0, mapping 3 |--> 4279"""280G = SmoothCharacterGroupQp(self.parent().prime(), self.base_ring())281ugs = G.unit_gens(self.level())282return G.character(self.level(), [self(x) for x in ugs])283284def galois_conjugate(self):285r"""286Return the composite of this character with the order `2` automorphism of287`K / \QQ_p` (assuming `K` is quadratic).288289Note that this is the Galois operation on the *domain*, not on the290*codomain*.291292EXAMPLE::293294sage: from sage.modular.local_comp.smoothchar import SmoothCharacterGroupUnramifiedQuadratic295sage: K.<w> = CyclotomicField(3)296sage: G = SmoothCharacterGroupUnramifiedQuadratic(2, K)297sage: chi = G.character(2, [w, -1,-1, 3*w])298sage: chi2 = chi.galois_conjugate(); chi2299Character 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*w300301sage: chi.restrict_to_Qp() == chi2.restrict_to_Qp()302True303sage: chi * chi2 == chi.parent().compose_with_norm(chi.restrict_to_Qp())304True305"""306K,s = self.parent().number_field().objgen()307if K.absolute_degree() != 2:308raise ValueError( "Character must be defined on a quadratic extension" )309sigs = K.embeddings(K)310sig = [x for x in sigs if x(s) != s][0]311return self.parent().character(self.level(), [self(sig(x)) for x in self.parent().unit_gens(self.level())])312313314class SmoothCharacterGroupGeneric(ParentWithBase):315r"""316The group of smooth (i.e. locally constant) characters of a `p`-adic field,317with values in some ring `R`. This is an abstract base class and should not318be instantiated directly.319"""320321Element = SmoothCharacterGeneric322323def __init__(self, p, base_ring):324r"""325TESTS::326327sage: from sage.modular.local_comp.smoothchar import SmoothCharacterGroupGeneric328sage: G = SmoothCharacterGroupGeneric(3, QQ)329sage: SmoothCharacterGroupGeneric(3, "hello")330Traceback (most recent call last):331...332TypeError: base ring (=hello) must be a ring333"""334if not is_Ring(base_ring):335raise TypeError( "base ring (=%s) must be a ring" % base_ring )336ParentWithBase.__init__(self, base=base_ring, category=Groups())337if not (p in ZZ and ZZ(p).is_prime()):338raise ValueError( "p (=%s) must be a prime integer" % p )339self._p = ZZ.coerce(p)340341def _element_constructor_(self, x):342r"""343Construct an element of this group from ``x`` (possibly noncanonically).344This only works if ``x`` is a character of a field containing the field of345self, whose values lie in a field that can be converted into self.346347EXAMPLES::348349sage: from sage.modular.local_comp.smoothchar import SmoothCharacterGroupQp350sage: K.<i> = QuadraticField(-1)351sage: G = SmoothCharacterGroupQp(3, QQ)352sage: GK = SmoothCharacterGroupQp(3, K)353sage: chi = GK(G.character(0, [4])); chi # indirect doctest354Character of Q_3*, of level 0, mapping 3 |--> 4355sage: chi.parent() is GK356True357sage: G(GK.character(0, [7])) # indirect doctest358Character of Q_3*, of level 0, mapping 3 |--> 7359sage: G(GK.character(0, [i])) # indirect doctest360Traceback (most recent call last):361...362TypeError: Unable to coerce i to a rational363"""364if x == 1:365return self.character(0, [1])366if hasattr(x, 'parent') \367and isinstance(x.parent(), SmoothCharacterGroupGeneric) \368and x.parent().number_field().has_coerce_map_from(self.number_field()):369return self.character(x.level(), [x(v) for v in self.unit_gens(x.level())])370else:371raise TypeError372373def __cmp__(self, other):374r"""375TESTS::376377sage: from sage.modular.local_comp.smoothchar import SmoothCharacterGroupQp378sage: G = SmoothCharacterGroupQp(3, QQ)379sage: G == SmoothCharacterGroupQp(3, QQ[I])380False381sage: G == 7382False383sage: G == SmoothCharacterGroupQp(7, QQ)384False385sage: G == SmoothCharacterGroupQp(3, QQ)386True387"""388return cmp(type(self), type(other)) \389or cmp(self.prime(), other.prime()) \390or cmp(self.number_field(), other.number_field()) \391or cmp(self.base_ring(), other.base_ring())392393def _coerce_map_from_(self, other):394r"""395Return True if self has a canonical coerce map from other.396397EXAMPLES::398399sage: from sage.modular.local_comp.smoothchar import SmoothCharacterGroupQp400sage: K.<i> = QuadraticField(-1)401sage: G = SmoothCharacterGroupQp(3, QQ)402sage: GK = SmoothCharacterGroupQp(3, K)403sage: G.has_coerce_map_from(GK)404False405sage: GK.has_coerce_map_from(G)406True407sage: GK.coerce(G.character(0, [4]))408Character of Q_3*, of level 0, mapping 3 |--> 4409sage: G.coerce(GK.character(0, [4]))410Traceback (most recent call last):411...412TypeError: 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 Field413sage: G.character(0, [4]) in GK # indirect doctest414True415416The coercion framework handles base extension, so we test that too::417418sage: K.<i> = QuadraticField(-1)419sage: from sage.modular.local_comp.smoothchar import SmoothCharacterGroupUnramifiedQuadratic420sage: G = SmoothCharacterGroupUnramifiedQuadratic(3, QQ)421sage: G.character(0, [1]).base_extend(K)422Character of unramified extension Q_3(s)* (s^2 + 2*s + 2 = 0), of level 0, mapping 3 |--> 1423424"""425if isinstance(other, SmoothCharacterGroupGeneric) \426and other.number_field() == self.number_field() \427and self.base_ring().has_coerce_map_from(other.base_ring()):428return True429else:430return False431432def prime(self):433r"""434The residue characteristic of the underlying field.435436EXAMPLE::437438sage: from sage.modular.local_comp.smoothchar import SmoothCharacterGroupGeneric439sage: SmoothCharacterGroupGeneric(3, QQ).prime()4403441"""442return self._p443444@abstract_method445def change_ring(self, ring):446r"""447Return the character group of the same field, but with values in a448different coefficient ring. To be implemented by all derived classes449(since the generic base class can't know the parameters).450451EXAMPLE::452453sage: from sage.modular.local_comp.smoothchar import SmoothCharacterGroupGeneric454sage: SmoothCharacterGroupGeneric(3, QQ).change_ring(ZZ)455Traceback (most recent call last):456...457NotImplementedError: <abstract method change_ring at ...>458"""459pass460461def base_extend(self, ring):462r"""463Return the character group of the same field, but with values in a new464coefficient ring into which the old coefficient ring coerces. An error465will be raised if there is no coercion map from the old coefficient466ring to the new one.467468EXAMPLE::469470sage: from sage.modular.local_comp.smoothchar import SmoothCharacterGroupQp471sage: G = SmoothCharacterGroupQp(3, QQ)472sage: G.base_extend(QQbar)473Group of smooth characters of Q_3* with values in Algebraic Field474sage: G.base_extend(Zmod(3))475Traceback (most recent call last):476...477TypeError: no canonical coercion from Rational Field to Ring of integers modulo 3478479"""480if not ring.has_coerce_map_from(self.base_ring()) :481ring.coerce(self.base_ring().an_element())482# this is here to flush out errors483484return self.change_ring(ring)485486@abstract_method487def _field_name(self):488r"""489A string representing the name of the p-adic field of which this is the490character group. To be overridden by derived subclasses.491492EXAMPLE::493494sage: from sage.modular.local_comp.smoothchar import SmoothCharacterGroupGeneric495sage: SmoothCharacterGroupGeneric(3, QQ)._field_name()496Traceback (most recent call last):497...498NotImplementedError: <abstract method _field_name at ...>499"""500pass501502def _repr_(self):503r"""504String representation of self.505506EXAMPLE::507508sage: from sage.modular.local_comp.smoothchar import SmoothCharacterGroupQp509sage: SmoothCharacterGroupQp(7, QQ)._repr_()510'Group of smooth characters of Q_7* with values in Rational Field'511"""512return "Group of smooth characters of %s with values in %s" % (self._field_name(), self.base_ring())513514@abstract_method515def ideal(self, level):516r"""517Return the ``level``-th power of the maximal ideal of the ring of518integers of the p-adic field. Since we approximate by using number519field arithmetic, what is actually returned is an ideal in a number520field.521522EXAMPLE::523524sage: from sage.modular.local_comp.smoothchar import SmoothCharacterGroupGeneric525sage: SmoothCharacterGroupGeneric(3, QQ).ideal(3)526Traceback (most recent call last):527...528NotImplementedError: <abstract method ideal at ...>529"""530pass531532@abstract_method533def unit_gens(self, level):534r"""535A list of generators `x_1, \dots, x_d` of the abelian group `F^\times /536(1 + \mathfrak{p}^c)^\times`, where `c` is the given level, satisfying537no relations other than `x_i^{n_i} = 1` for each `i` (where the538integers `n_i` are returned by :meth:`exponents`). We adopt the539convention that the final generator `x_d` is a uniformiser (and `n_d =5400`).541542EXAMPLE::543544sage: from sage.modular.local_comp.smoothchar import SmoothCharacterGroupGeneric545sage: SmoothCharacterGroupGeneric(3, QQ).unit_gens(3)546Traceback (most recent call last):547...548NotImplementedError: <abstract method unit_gens at ...>549"""550pass551552@abstract_method553def exponents(self, level):554r"""555The orders `n_1, \dots, n_d` of the generators `x_i` of `F^\times / (1556+ \mathfrak{p}^c)^\times` returned by :meth:`unit_gens`.557558EXAMPLE::559560sage: from sage.modular.local_comp.smoothchar import SmoothCharacterGroupGeneric561sage: SmoothCharacterGroupGeneric(3, QQ).exponents(3)562Traceback (most recent call last):563...564NotImplementedError: <abstract method exponents at ...>565"""566pass567568@abstract_method569def subgroup_gens(self, level):570r"""571A set of elements of `(\mathcal{O}_F / \mathfrak{p}^c)^\times`572generating the kernel of the reduction map to `(\mathcal{O}_F /573\mathfrak{p}^{c-1})^\times`.574575EXAMPLE::576577sage: from sage.modular.local_comp.smoothchar import SmoothCharacterGroupGeneric578sage: SmoothCharacterGroupGeneric(3, QQ).subgroup_gens(3)579Traceback (most recent call last):580...581NotImplementedError: <abstract method subgroup_gens at ...>582"""583pass584585@abstract_method586def discrete_log(self, level):587r"""588Given an element `x \in F^\times` (lying in the number field `K` of589which `F` is a completion, see module docstring), express the class of590`x` in terms of the generators of `F^\times / (1 +591\mathfrak{p}^c)^\times` returned by :meth:`unit_gens`.592593This should be overridden by all derived classes. The method should594first attempt to canonically coerce `x` into ``self.number_field()``,595and check that the result is not zero.596597EXAMPLE::598599sage: from sage.modular.local_comp.smoothchar import SmoothCharacterGroupGeneric600sage: SmoothCharacterGroupGeneric(3, QQ).discrete_log(3)601Traceback (most recent call last):602...603NotImplementedError: <abstract method discrete_log at ...>604"""605pass606607def character(self, level, values_on_gens):608r"""609Return the unique character of the given level whose values on the610generators returned by ``self.unit_gens(level)`` are611``values_on_gens``.612613INPUT:614615- ``level`` (integer) an integer `\ge 0`616- ``values_on_gens`` (sequence) a sequence of elements of length equal617to the length of ``self.unit_gens(level)``. The values should be618convertible (that is, possibly noncanonically) into the base ring of self; they619should all be units, and all but the last must be roots of unity (of620the orders given by ``self.exponents(level)``.621622.. note::623624The character returned may have level less than ``level`` in general.625626EXAMPLES::627628sage: from sage.modular.local_comp.smoothchar import SmoothCharacterGroupQp629sage: K.<z> = CyclotomicField(42)630sage: G = SmoothCharacterGroupQp(7, K)631sage: G.character(2, [z^6, 8])632Character of Q_7*, of level 2, mapping 3 |--> z^6, 7 |--> 8633sage: G.character(2, [z^7, 8])634Character of Q_7*, of level 1, mapping 3 |--> z^7, 7 |--> 8635636Non-examples::637638sage: G.character(1, [z, 1])639Traceback (most recent call last):640...641ValueError: value on generator 3 (=z) should be a root of unity of order 6642sage: G.character(1, [1, 0])643Traceback (most recent call last):644...645ValueError: value on uniformiser 7 (=0) should be a unit646647An example with a funky coefficient ring::648649sage: G = SmoothCharacterGroupQp(7, Zmod(9))650sage: G.character(1, [2, 2])651Character of Q_7*, of level 1, mapping 3 |--> 2, 7 |--> 2652sage: G.character(1, [2, 3])653Traceback (most recent call last):654...655ValueError: value on uniformiser 7 (=3) should be a unit656657TESTS::658659sage: G.character(1, [2])660Traceback (most recent call last):661...662AssertionError: 2 images must be given663"""664S = Sequence(values_on_gens, universe=self.base_ring(), immutable=True)665assert len(S) == len(self.unit_gens(level)), "{0} images must be given".format(len(self.unit_gens(level)))666n = self.exponents(level)667for i in xrange(len(S)):668if n[i] != 0 and not S[i]**n[i] == 1:669raise ValueError( "value on generator %s (=%s) should be a root of unity of order %s" % (self.unit_gens(level)[i], S[i], n[i]) )670elif n[i] == 0 and not S[i].is_unit():671raise ValueError( "value on uniformiser %s (=%s) should be a unit" % (self.unit_gens(level)[i], S[i]) )672return self.element_class(self, level, S)673674def _an_element_(self):675r"""676Return an element of this group. Required by the coercion machinery.677678EXAMPLE::679680sage: from sage.modular.local_comp.smoothchar import SmoothCharacterGroupQp681sage: K.<z> = CyclotomicField(42)682sage: G = SmoothCharacterGroupQp(7, K)683sage: G.an_element() # indirect doctest684Character of Q_7*, of level 0, mapping 7 |--> z685"""686return self.character(0, [self.base_ring().an_element()])687688689690def _test_unitgens(self, **options):691r"""692Test that the generators returned by ``unit_gens`` are consistent with693the exponents returned by ``exponents``.694695EXAMPLE::696697sage: from sage.modular.local_comp.smoothchar import SmoothCharacterGroupUnramifiedQuadratic698sage: SmoothCharacterGroupUnramifiedQuadratic(2, Zmod(8))._test_unitgens()699"""700T = self._tester(**options)701for c in xrange(6):702gens = self.unit_gens(c)703exps = self.exponents(c)704T.assert_(exps[-1] == 0)705T.assert_(all([u != 0 for u in exps[:-1]]))706T.assert_(all([u.parent() is self.number_field() for u in gens]))707708I = self.ideal(c)709for i in xrange(len(exps[:-1])):710g = gens[i]711for m in xrange(1, exps[i]):712if (g - 1 in I):713T.fail("For generator g=%s, g^%s = %s = 1 mod I, but order should be %s" % (gens[i], m, g, exps[i]))714g = g * gens[i]715# reduce g mod I716if hasattr(I, "small_residue"):717g = I.small_residue(g)718else: # I is an ideal of ZZ719g = g % (I.gen())720if not (g - 1 in I):721T.fail("For generator g=%s, g^%s = %s, which is not 1 mod I" % (gens[i], exps[i], g))722I = self.prime() if self.number_field() == QQ else self.ideal(1)723T.assert_(gens[-1].valuation(I) == 1)724725# This implicitly tests that the gens really are gens!726_ = self.discrete_log(c, -1)727728def _test_subgroupgens(self, **options):729r"""730Test that the values returned by :meth:`~subgroup_gens` are valid.731732EXAMPLE::733734sage: from sage.modular.local_comp.smoothchar import SmoothCharacterGroupQp735sage: SmoothCharacterGroupQp(2, CC)._test_subgroupgens()736"""737T = self._tester(**options)738for c in xrange(1, 6):739sgs = self.subgroup_gens(c)740I2 = self.ideal(c-1)741T.assert_(all([x-1 in I2 for x in sgs]), "Kernel gens at level %s not in kernel!" % c)742743# now find the exponent of the kernel744745n1 = prod(self.exponents(c)[:-1])746n2 = prod(self.exponents(c-1)[:-1])747n = n1 // n2748# if c > 1, n will be a prime here, so that logs below gets calculated correctly749750logs = []751for idx in xmrange(len(sgs)*[n]):752y = prod( map(operator.pow, sgs, idx) )753L = tuple(self.discrete_log(c, y))754if L not in logs:755logs.append(L)756T.assert_(n2 * len(logs) == n1, "Kernel gens at level %s don't generate everything!" % c)757758def compose_with_norm(self, chi):759r"""760Calculate the character of `K^\times` given by `\chi \circ \mathrm{Norm}_{K/\QQ_p}`.761Here `K` should be a quadratic extension and `\chi` a character of `\QQ_p^\times`.762763EXAMPLE:764765When `K` is the unramified quadratic extension, the level of the new character is the same as the old::766767sage: from sage.modular.local_comp.smoothchar import SmoothCharacterGroupQp, SmoothCharacterGroupRamifiedQuadratic, SmoothCharacterGroupUnramifiedQuadratic768sage: K.<w> = CyclotomicField(6)769sage: G = SmoothCharacterGroupQp(3, K)770sage: chi = G.character(2, [w, 5])771sage: H = SmoothCharacterGroupUnramifiedQuadratic(3, K)772sage: H.compose_with_norm(chi)773Character 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 |--> 25774775In ramified cases, the level of the new character may be larger:776777.. link778779::780781sage: H = SmoothCharacterGroupRamifiedQuadratic(3, 0, K)782sage: H.compose_with_norm(chi)783Character of ramified extension Q_3(s)* (s^2 - 3 = 0), of level 3, mapping 2 |--> w - 1, s + 1 |--> -w, s |--> -5784785On the other hand, since norm is not surjective, the result can even be trivial:786787.. link788789::790791sage: chi = G.character(1, [-1, -1]); chi792Character of Q_3*, of level 1, mapping 2 |--> -1, 3 |--> -1793sage: H.compose_with_norm(chi)794Character of ramified extension Q_3(s)* (s^2 - 3 = 0), of level 0, mapping s |--> 1795"""796if chi.parent().number_field() != QQ: raise ValueError797if self.number_field().absolute_degree() != 2: raise ValueError798n = chi.level()799P = chi.parent().prime() ** n800m = self.number_field()(P).valuation(self.ideal(1))801return self.character(m, [chi(x.norm(QQ)) for x in self.unit_gens(m)])802803class SmoothCharacterGroupQp(SmoothCharacterGroupGeneric):804r"""805The group of smooth characters of `\QQ_p^\times`, with values in some fixed806base ring.807808EXAMPLES::809810sage: from sage.modular.local_comp.smoothchar import SmoothCharacterGroupQp811sage: G = SmoothCharacterGroupQp(7, QQ); G812Group of smooth characters of Q_7* with values in Rational Field813sage: TestSuite(G).run()814sage: G == loads(dumps(G))815True816"""817def unit_gens(self, level):818r"""819Return a set of generators `x_1, \dots, x_d` for `\QQ_p^\times / (1 +820p^c \ZZ_p)^\times`. These must be independent in the sense that there821are no relations between them other than relations of the form822`x_i^{n_i} = 1`. They need not, however, be in Smith normal form.823824EXAMPLE::825826sage: from sage.modular.local_comp.smoothchar import SmoothCharacterGroupQp827sage: SmoothCharacterGroupQp(7, QQ).unit_gens(3)828[3, 7]829sage: SmoothCharacterGroupQp(2, QQ).unit_gens(4)830[15, 5, 2]831"""832if level == 0:833return [QQ(self.prime())]834else:835return [QQ(x) for x in Zmod(self.prime()**level).unit_gens()] + [QQ(self.prime())]836837def exponents(self, level):838r"""839Return the exponents of the generators returned by :meth:`unit_gens`.840841EXAMPLE::842843sage: from sage.modular.local_comp.smoothchar import SmoothCharacterGroupQp844sage: SmoothCharacterGroupQp(7, QQ).exponents(3)845[294, 0]846sage: SmoothCharacterGroupQp(2, QQ).exponents(4)847[2, 4, 0]848"""849if level == 0: return [0]850return [x.multiplicative_order() for x in Zmod(self.prime()**level).unit_gens()] + [0]851852def change_ring(self, ring):853r"""854Return the group of characters of the same field but with values in a855different ring. This need not have anything to do with the original856base ring, and in particular there won't generally be a coercion map857from self to the new group -- use858:meth:`~SmoothCharacterGroupGeneric.base_extend` if you want this.859860EXAMPLE::861862sage: from sage.modular.local_comp.smoothchar import SmoothCharacterGroupQp863sage: SmoothCharacterGroupQp(7, Zmod(3)).change_ring(CC)864Group of smooth characters of Q_7* with values in Complex Field with 53 bits of precision865"""866return SmoothCharacterGroupQp(self.prime(), ring)867868def number_field(self):869r"""870Return the number field used for calculations (a dense subfield of the871local field of which this is the character group). In this case, this872is always the rational field.873874EXAMPLE::875876sage: from sage.modular.local_comp.smoothchar import SmoothCharacterGroupQp877sage: SmoothCharacterGroupQp(7, Zmod(3)).number_field()878Rational Field879"""880return QQ881882def ideal(self, level):883r"""884Return the ``level``-th power of the maximal ideal. Since we885approximate by using rational arithmetic, what is actually returned is886an ideal of `\ZZ`.887888EXAMPLE::889890sage: from sage.modular.local_comp.smoothchar import SmoothCharacterGroupQp891sage: SmoothCharacterGroupQp(7, Zmod(3)).ideal(2)892Principal ideal (49) of Integer Ring893"""894return ZZ.ideal(self.prime() ** level)895896def _field_name(self):897r"""898Return a string representation of the field unit group of which this is899the character group.900901EXAMPLE::902903sage: from sage.modular.local_comp.smoothchar import SmoothCharacterGroupQp904sage: SmoothCharacterGroupQp(7, Zmod(3))._field_name()905'Q_7*'906"""907return "Q_%s*" % self.prime()908909def discrete_log(self, level, x):910r"""911Express the class of `x` in `\QQ_p^\times / (1 + p^c)^\times` in terms912of the generators returned by :meth:`unit_gens`.913914EXAMPLE::915916sage: from sage.modular.local_comp.smoothchar import SmoothCharacterGroupQp917sage: G = SmoothCharacterGroupQp(7, QQ)918sage: G.discrete_log(0, 14)919[1]920sage: G.discrete_log(1, 14)921[2, 1]922sage: G.discrete_log(5, 14)923[9308, 1]924"""925x = self.number_field().coerce(x)926if x == 0: raise ValueError( "cannot evaluate at zero" )927s = x.valuation(self.prime())928return Zmod(self.prime()**level)(x / self.prime()**s).generalised_log() + [s]929930def subgroup_gens(self, level):931r"""932Return a list of generators for the kernel of the map `(\ZZ_p / p^c)^\times933\to (\ZZ_p / p^{c-1})^\times`.934935INPUT:936937- ``c`` (integer) an integer `\ge 1`938939EXAMPLES::940941sage: from sage.modular.local_comp.smoothchar import SmoothCharacterGroupQp942sage: G = SmoothCharacterGroupQp(7, QQ)943sage: G.subgroup_gens(1)944[3]945sage: G.subgroup_gens(2)946[8]947948sage: G = SmoothCharacterGroupQp(2, QQ)949sage: G.subgroup_gens(1)950[]951sage: G.subgroup_gens(2)952[3]953sage: G.subgroup_gens(3)954[5]955"""956if level == 0:957raise ValueError958elif level == 1:959return self.unit_gens(level)[:-1]960else:961return [1 + self.prime()**(level - 1)]962963class SmoothCharacterGroupUnramifiedQuadratic(SmoothCharacterGroupGeneric):964r"""965The group of smooth characters of `\QQ_{p^2}^\times`, where `\QQ_{p^2}` is966the unique unramified quadratic extension of `\QQ_p`. We represent967`\QQ_{p^2}^\times` internally as the completion at the prime above `p` of a968quadratic number field, defined by (the obvious lift to `\ZZ` of) the969Conway polynomial modulo `p` of degree 2.970971EXAMPLE::972973sage: from sage.modular.local_comp.smoothchar import SmoothCharacterGroupUnramifiedQuadratic974sage: G = SmoothCharacterGroupUnramifiedQuadratic(3, QQ); G975Group of smooth characters of unramified extension Q_3(s)* (s^2 + 2*s + 2 = 0) with values in Rational Field976sage: G.unit_gens(3)977[-11*s, 4, 3*s + 1, 3]978sage: TestSuite(G).run()979sage: TestSuite(SmoothCharacterGroupUnramifiedQuadratic(2, QQ)).run()980"""981982def __init__(self, prime, base_ring, names='s'):983r"""984Standard initialisation function.985986EXAMPLE::987988sage: from sage.modular.local_comp.smoothchar import SmoothCharacterGroupUnramifiedQuadratic989sage: G = SmoothCharacterGroupUnramifiedQuadratic(3, QQ, 'foo'); G990Group of smooth characters of unramified extension Q_3(foo)* (foo^2 + 2*foo + 2 = 0) with values in Rational Field991sage: G == loads(dumps(G))992True993"""994SmoothCharacterGroupGeneric.__init__(self, prime, base_ring)995self._name = names996997def change_ring(self, ring):998r"""999Return the character group of the same field, but with values in a1000different coefficient ring. This need not have anything to do with the1001original base ring, and in particular there won't generally be a1002coercion map from self to the new group -- use1003:meth:`~SmoothCharacterGroupGeneric.base_extend` if you want this.10041005EXAMPLE::10061007sage: from sage.modular.local_comp.smoothchar import SmoothCharacterGroupUnramifiedQuadratic1008sage: SmoothCharacterGroupUnramifiedQuadratic(7, Zmod(3), names='foo').change_ring(CC)1009Group of smooth characters of unramified extension Q_7(foo)* (foo^2 + 6*foo + 3 = 0) with values in Complex Field with 53 bits of precision1010"""1011# We want to make sure that both G and the base-extended version have1012# the same values in the cache.1013from copy import copy1014G = SmoothCharacterGroupUnramifiedQuadratic(self.prime(), ring, self._name)1015try:1016G._cache___ideal = copy(self._cache___ideal)1017except AttributeError:1018pass1019return G10201021def _field_name(self):1022r"""1023A string representing the unit group of which this is the character group.10241025EXAMPLE::10261027sage: from sage.modular.local_comp.smoothchar import SmoothCharacterGroupUnramifiedQuadratic1028sage: SmoothCharacterGroupUnramifiedQuadratic(7, Zmod(3), 'a')._field_name()1029'unramified extension Q_7(a)* (a^2 + 6*a + 3 = 0)'1030"""1031return "unramified extension Q_%s(%s)* (%s = 0)" % (self.prime(), self._name, self.number_field().polynomial().change_variable_name(self._name))10321033def number_field(self):1034r"""1035Return a number field of which this is the completion at `p`, defined by a polynomial1036whose discriminant is not divisible by `p`.10371038EXAMPLES::10391040sage: from sage.modular.local_comp.smoothchar import SmoothCharacterGroupUnramifiedQuadratic1041sage: SmoothCharacterGroupUnramifiedQuadratic(7, QQ, 'a').number_field()1042Number Field in a with defining polynomial x^2 + 6*x + 31043sage: SmoothCharacterGroupUnramifiedQuadratic(5, QQ, 'b').number_field()1044Number Field in b with defining polynomial x^2 + 4*x + 21045sage: SmoothCharacterGroupUnramifiedQuadratic(2, QQ, 'c').number_field()1046Number Field in c with defining polynomial x^2 + x + 11047"""1048from sage.rings.all import conway_polynomial, PolynomialRing1049fbar = conway_polynomial(self.prime(), 2)1050f = PolynomialRing(QQ,'x')([a.lift() for a in fbar])1051return NumberField(f, self._name)10521053@cached_method1054def ideal(self, c):1055r"""1056Return the ideal `p^c` of ``self.number_field()``. The result is1057cached, since we use the methods1058:meth:`~sage.rings.number_field.number_field_ideal.NumberFieldFractionalIdeal.idealstar` and1059:meth:`~sage.rings.number_field.number_field_ideal.NumberFieldFractionalIdeal.ideallog` which1060cache a Pari ``bid`` structure.10611062EXAMPLES::10631064sage: from sage.modular.local_comp.smoothchar import SmoothCharacterGroupUnramifiedQuadratic1065sage: G = SmoothCharacterGroupUnramifiedQuadratic(7, QQ, 'a'); I = G.ideal(3); I1066Fractional ideal (343)1067sage: I is G.ideal(3)1068True1069"""1070return self.number_field().ideal(self.prime()**c)10711072@cached_method1073def unit_gens(self, c):1074r"""1075A list of generators `x_1, \dots, x_d` of the abelian group `F^\times /1076(1 + \mathfrak{p}^c)^\times`, where `c` is the given level, satisfying1077no relations other than `x_i^{n_i} = 1` for each `i` (where the1078integers `n_i` are returned by :meth:`exponents`). We adopt the1079convention that the final generator `x_d` is a uniformiser (and `n_d =10800`).10811082ALGORITHM: Use Teichmueller lifts.10831084EXAMPLE::10851086sage: from sage.modular.local_comp.smoothchar import SmoothCharacterGroupUnramifiedQuadratic1087sage: SmoothCharacterGroupUnramifiedQuadratic(7, QQ).unit_gens(0)1088[7]1089sage: SmoothCharacterGroupUnramifiedQuadratic(7, QQ).unit_gens(1)1090[s, 7]1091sage: SmoothCharacterGroupUnramifiedQuadratic(7, QQ).unit_gens(2)1092[22*s, 8, 7*s + 1, 7]1093sage: SmoothCharacterGroupUnramifiedQuadratic(7, QQ).unit_gens(3)1094[169*s + 49, 8, 7*s + 1, 7]10951096In the 2-adic case there can be more than 4 generators::10971098sage: SmoothCharacterGroupUnramifiedQuadratic(2, QQ).unit_gens(0)1099[2]1100sage: SmoothCharacterGroupUnramifiedQuadratic(2, QQ).unit_gens(1)1101[s, 2]1102sage: SmoothCharacterGroupUnramifiedQuadratic(2, QQ).unit_gens(2)1103[s, 2*s + 1, -1, 2]1104sage: SmoothCharacterGroupUnramifiedQuadratic(2, QQ).unit_gens(3)1105[s, 2*s + 1, 4*s + 1, -1, 2]1106"""1107# special cases11081109p = self.prime()1110K = self.number_field()1111a = K.gen()11121113if c == 0:1114return [K(p)]1115elif c == 1:1116return [a, K(p)]1117elif p == 2:1118if c == 2:1119return [a, 1 + 2*a, K(-1), K(2)]1120else:1121return [a, 1 + 2*a, 1 + 4*a, K(-1), K(2)]11221123# general case11241125b = a1126I = self.ideal(c)11271128while b**(p**2 - 1) - 1 not in I:1129b = I.reduce(b**(self.prime()**2))1130return [b, K(1 + p), 1 + a*p, K(p)]11311132def exponents(self, c):1133r"""1134The orders `n_1, \dots, n_d` of the generators `x_i` of `F^\times / (11135+ \mathfrak{p}^c)^\times` returned by :meth:`unit_gens`.11361137EXAMPLE::11381139sage: from sage.modular.local_comp.smoothchar import SmoothCharacterGroupUnramifiedQuadratic1140sage: SmoothCharacterGroupUnramifiedQuadratic(7, QQ).exponents(2)1141[48, 7, 7, 0]1142sage: SmoothCharacterGroupUnramifiedQuadratic(2, QQ).exponents(3)1143[3, 4, 2, 2, 0]1144sage: SmoothCharacterGroupUnramifiedQuadratic(2, QQ).exponents(2)1145[3, 2, 2, 0]1146"""1147p = self.prime()1148if c == 0: return [0]1149elif c == 1: return [p**2 - 1, 0]1150elif p == 2 and c >= 3:1151return [p**2 - 1, p**(c-1), p**(c-2), 2, 0]1152else: return [p**2 - 1, p**(c-1), p**(c-1),0]11531154def subgroup_gens(self, level):1155r"""1156A set of elements of `(\mathcal{O}_F / \mathfrak{p}^c)^\times`1157generating the kernel of the reduction map to `(\mathcal{O}_F /1158\mathfrak{p}^{c-1})^\times`.11591160EXAMPLE::11611162sage: from sage.modular.local_comp.smoothchar import SmoothCharacterGroupUnramifiedQuadratic1163sage: SmoothCharacterGroupUnramifiedQuadratic(7, QQ).subgroup_gens(1)1164[s]1165sage: SmoothCharacterGroupUnramifiedQuadratic(7, QQ).subgroup_gens(2)1166[8, 7*s + 1]1167sage: SmoothCharacterGroupUnramifiedQuadratic(2, QQ).subgroup_gens(2)1168[3, 2*s + 1]1169"""1170if level == 0:1171raise ValueError1172elif level == 1:1173return self.unit_gens(level)[:-1]1174else:1175return [1 + self.prime()**(level - 1), 1 + self.prime()**(level - 1) * self.number_field().gen()]11761177def quotient_gen(self, level):1178r"""1179Find an element generating the quotient11801181.. math::11821183\mathcal{O}_F^\times / \ZZ_p^\times \cdot (1 + p^c \mathcal{O}_F),11841185where `c` is the given level.11861187EXAMPLE::11881189sage: from sage.modular.local_comp.smoothchar import SmoothCharacterGroupUnramifiedQuadratic1190sage: G = SmoothCharacterGroupUnramifiedQuadratic(7,QQ)1191sage: G.quotient_gen(1)1192s1193sage: G.quotient_gen(2)1194-20*s - 211195sage: G.quotient_gen(3)1196-69*s - 7011971198For `p = 2` an error will be raised for level `\ge 3`, as the quotient is not cyclic::11991200sage: G = SmoothCharacterGroupUnramifiedQuadratic(2,QQ)1201sage: G.quotient_gen(1)1202s1203sage: G.quotient_gen(2)1204-s + 21205sage: G.quotient_gen(3)1206Traceback (most recent call last):1207...1208ValueError: Quotient group not cyclic1209"""1210if level == 0:1211raise ValueError( "Quotient group is trivial" )1212elif self.prime() == 2 and level >= 3:1213raise ValueError( "Quotient group not cyclic" )1214elif level == 1:1215return self.unit_gens(level)[0]1216else:1217return self.ideal(level).reduce(self.unit_gens(level)[0] * (1 + self.prime() * self.number_field().gen()))12181219def extend_character(self, level, chi, x, check=True):1220r"""1221Return the unique character of `F^\times` which coincides with `\chi`1222on `\QQ_p^\times` and maps the generator `\alpha` returned by1223:meth:`quotient_gen` to `x`.12241225INPUT:12261227- ``chi``: a smooth character of `\QQ_p`, where `p` is the residue1228characteristic of `F`, with values in the base ring of self (or some1229other ring coercible to it)1230- ``level``: the level of the new character (which should be at least1231the level of ``chi``)1232- ``x``: an element of the base ring of self (or some other ring1233coercible to it).12341235A ``ValueError`` will be raised if `x^t \ne \chi(\alpha^t)`, where `t`1236is the smallest integer such that `\alpha^t` is congruent modulo1237`p^{\rm level}` to an element of `\QQ_p`.12381239EXAMPLES:12401241We extend an unramified character of `\QQ_3^\times` to the unramified1242quadratic extension in various ways.12431244::12451246sage: from sage.modular.local_comp.smoothchar import SmoothCharacterGroupQp, SmoothCharacterGroupUnramifiedQuadratic1247sage: chi = SmoothCharacterGroupQp(5, QQ).character(0, [7]); chi1248Character of Q_5*, of level 0, mapping 5 |--> 71249sage: G = SmoothCharacterGroupUnramifiedQuadratic(5, QQ)1250sage: G.extend_character(1, chi, -1)1251Character of unramified extension Q_5(s)* (s^2 + 4*s + 2 = 0), of level 1, mapping s |--> -1, 5 |--> 71252sage: G.extend_character(2, chi, -1)1253Character of unramified extension Q_5(s)* (s^2 + 4*s + 2 = 0), of level 1, mapping s |--> -1, 5 |--> 71254sage: G.extend_character(3, chi, 1)1255Character of unramified extension Q_5(s)* (s^2 + 4*s + 2 = 0), of level 0, mapping 5 |--> 71256sage: K.<z> = CyclotomicField(6); G.base_extend(K).extend_character(1, chi, z)1257Character of unramified extension Q_5(s)* (s^2 + 4*s + 2 = 0), of level 1, mapping s |--> z, 5 |--> 712581259We extend the nontrivial quadratic character::12601261sage: chi = SmoothCharacterGroupQp(5, QQ).character(1, [-1, 7])1262sage: K.<z> = CyclotomicField(24); G.base_extend(K).extend_character(1, chi, z^6)1263Character of unramified extension Q_5(s)* (s^2 + 4*s + 2 = 0), of level 1, mapping s |--> z^6, 5 |--> 712641265Extensions of higher level::12661267sage: K.<z> = CyclotomicField(20); rho = G.base_extend(K).extend_character(2, chi, z); rho1268Character 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 |--> 71269sage: rho(3)1270-112711272Examples where it doesn't work::12731274sage: G.extend_character(1, chi, 1)1275Traceback (most recent call last):1276...1277ValueError: Value at s must satisfy x^6 = chi(2) = -1, but it does not12781279sage: G = SmoothCharacterGroupQp(2, QQ); H = SmoothCharacterGroupUnramifiedQuadratic(2, QQ)1280sage: chi = G.character(3, [1, -1, 7])1281sage: H.extend_character(2, chi, -1)1282Traceback (most recent call last):1283...1284ValueError: Level of extended character cannot be smaller than level of character of Qp1285"""1286chi = chi.base_extend(self.base_ring())1287if chi.level() > level:1288raise ValueError, "Level of extended character cannot be smaller than level of character of Qp"12891290# check it makes sense1291e = (self.prime() + 1) * (self.prime()**(level - 1))1292v = self.ideal(level).reduce(self.quotient_gen(level) ** e)12931294v = QQ(v)1295if x**e != chi(v):1296raise ValueError( "Value at %s must satisfy x^%s = chi(%s) = %s, but it does not" % (self.quotient_gen(level), e, v, chi(v)) )12971298# now do the calculation1299values_on_standard_gens = []1300other_gens = [self.quotient_gen(level)] + [ZZ(z) for z in Zmod(self.prime()**level).unit_gens()]1301values_on_other_gens = [x] + [chi(u) for u in other_gens[1:]]1302for s in self.unit_gens(level)[:-1]:1303t = self.ideal(level).ideallog(s, other_gens)1304values_on_standard_gens.append( prod([values_on_other_gens[i] ** t[i] for i in xrange(len(t))]) )1305values_on_standard_gens.append(chi(self.prime()))1306chiE = self.character(level, values_on_standard_gens)13071308# check it makes sense (optional but on by default)1309if check:1310assert chiE(self.quotient_gen(level)) == x1311assert chiE.restrict_to_Qp() == chi13121313return chiE13141315def discrete_log(self, level, x):1316r"""1317Express the class of `x` in `F^\times / (1 + \mathfrak{p}^c)^\times` in1318terms of the generators returned by ``self.unit_gens(level)``.13191320EXAMPLE::13211322sage: from sage.modular.local_comp.smoothchar import SmoothCharacterGroupUnramifiedQuadratic1323sage: G = SmoothCharacterGroupUnramifiedQuadratic(2, QQ)1324sage: G.discrete_log(0, 12)1325[2]1326sage: G.discrete_log(1, 12)1327[0, 2]1328sage: v = G.discrete_log(5, 12); v1329[0, 2, 0, 1, 2]1330sage: g = G.unit_gens(5); prod([g[i]**v[i] for i in [0..4]])/12 - 1 in G.ideal(5)1331True1332sage: G.discrete_log(3,G.number_field()([1,1]))1333[2, 0, 0, 1, 0]1334sage: H = SmoothCharacterGroupUnramifiedQuadratic(5, QQ)1335sage: x = H.number_field()([1,1]); x1336s + 11337sage: v = H.discrete_log(5, x); v1338[22, 263, 379, 0]1339sage: h = H.unit_gens(5); prod([h[i]**v[i] for i in [0..3]])/x - 1 in H.ideal(5)1340True1341"""1342x = self.number_field().coerce(x)1343if x == 0: raise ValueError( "cannot evaluate at zero" )1344n1 = x.valuation(self.number_field().ideal(self.prime()))1345x1 = x / self.prime() ** n11346if level == 0:1347return [n1]1348else:1349return self.ideal(level).ideallog(x1, self.unit_gens(level)[:-1]) + [n1]135013511352class SmoothCharacterGroupRamifiedQuadratic(SmoothCharacterGroupGeneric):1353r"""1354The group of smooth characters of `K^\times`, where `K` is a ramified1355quadratic extension of `\QQ_p`, and `p \ne 2`.1356"""1357def __init__(self, prime, flag, base_ring, names='s'):1358r"""1359Standard initialisation function.13601361INPUT:13621363- ``prime`` -- a prime integer1364- ``flag`` -- either 0 or 11365- ``base_ring`` -- a ring1366- ``names`` -- a variable name (default ``s``)13671368If ``flag`` is 0, return the group of characters of the multiplicative1369group of the field `\QQ_p(\sqrt{p})`. If ``flag`` is 1, use the1370extension `\QQ_p(\sqrt{dp})`, where `d` is `-1` (if `p = 3 \pmod 4`) or1371the smallest positive quadratic nonresidue mod `p` otherwise.13721373EXAMPLE::13741375sage: from sage.modular.local_comp.smoothchar import SmoothCharacterGroupRamifiedQuadratic1376sage: G1 = SmoothCharacterGroupRamifiedQuadratic(3, 0, QQ); G11377Group of smooth characters of ramified extension Q_3(s)* (s^2 - 3 = 0) with values in Rational Field1378sage: G2 = SmoothCharacterGroupRamifiedQuadratic(3, 1, QQ); G21379Group of smooth characters of ramified extension Q_3(s)* (s^2 + 3 = 0) with values in Rational Field1380sage: G3 = SmoothCharacterGroupRamifiedQuadratic(5, 1, QQ); G31381Group of smooth characters of ramified extension Q_5(s)* (s^2 - 10 = 0) with values in Rational Field13821383TESTS:13841385.. link13861387::13881389sage: TestSuite(G1).run()1390sage: TestSuite(G2).run()1391sage: TestSuite(G3).run()1392"""1393if prime == 2: raise NotImplementedError( "Wildly ramified extensions not supported" )1394SmoothCharacterGroupGeneric.__init__(self, prime, base_ring)1395self._name = names1396if flag not in [0, 1]:1397raise ValueError( "Flag must be 0 (for Qp(sqrt(p)) ) or 1 (for the other ramified extension)" )1398self._flag = flag1399if flag == 0:1400self._unif_sqr = self.prime()1401else:1402if self.prime() % 4 == 3:1403self._unif_sqr = -self.prime()1404else:1405self._unif_sqr = ZZ(Zmod(self.prime()).quadratic_nonresidue()) * self.prime()14061407def change_ring(self, ring):1408r"""1409Return the character group of the same field, but with values in a1410different coefficient ring. This need not have anything to do with the1411original base ring, and in particular there won't generally be a1412coercion map from self to the new group -- use1413:meth:`~SmoothCharacterGroupGeneric.base_extend` if you want this.14141415EXAMPLE::14161417sage: from sage.modular.local_comp.smoothchar import SmoothCharacterGroupRamifiedQuadratic1418sage: SmoothCharacterGroupRamifiedQuadratic(7, 1, Zmod(3), names='foo').change_ring(CC)1419Group of smooth characters of ramified extension Q_7(foo)* (foo^2 + 7 = 0) with values in Complex Field with 53 bits of precision1420"""1421return SmoothCharacterGroupRamifiedQuadratic(self.prime(), self._flag, ring, self._name)14221423def _field_name(self):1424r"""1425A string representing the unit group of which this is the character group.14261427EXAMPLE::14281429sage: from sage.modular.local_comp.smoothchar import SmoothCharacterGroupRamifiedQuadratic1430sage: SmoothCharacterGroupRamifiedQuadratic(7, 0, Zmod(3), 'a')._field_name()1431'ramified extension Q_7(a)* (a^2 - 7 = 0)'1432"""1433return "ramified extension Q_%s(%s)* (%s = 0)" % (self.prime(), self._name, self.number_field().polynomial().change_variable_name(self._name))14341435def number_field(self):1436r"""1437Return a number field of which this is the completion at `p`.14381439EXAMPLES::14401441sage: from sage.modular.local_comp.smoothchar import SmoothCharacterGroupRamifiedQuadratic1442sage: SmoothCharacterGroupRamifiedQuadratic(7, 0, QQ, 'a').number_field()1443Number Field in a with defining polynomial x^2 - 71444sage: SmoothCharacterGroupRamifiedQuadratic(5, 1, QQ, 'b').number_field()1445Number Field in b with defining polynomial x^2 - 101446sage: SmoothCharacterGroupRamifiedQuadratic(7, 1, Zmod(6), 'c').number_field()1447Number Field in c with defining polynomial x^2 + 71448"""1449from sage.rings.all import PolynomialRing1450R, x = PolynomialRing(QQ, 'x').objgen()1451f = x**2 - self._unif_sqr1452return NumberField(f, self._name)14531454@cached_method1455def ideal(self, c):1456r"""1457Return the ideal `p^c` of ``self.number_field()``. The result is1458cached, since we use the methods1459:meth:`~sage.rings.number_field.number_field_ideal.NumberFieldFractionalIdeal.idealstar` and1460:meth:`~sage.rings.number_field.number_field_ideal.NumberFieldFractionalIdeal.ideallog` which1461cache a Pari ``bid`` structure.14621463EXAMPLES::14641465sage: from sage.modular.local_comp.smoothchar import SmoothCharacterGroupRamifiedQuadratic1466sage: G = SmoothCharacterGroupRamifiedQuadratic(5, 1, QQ, 'a'); I = G.ideal(3); I1467Fractional ideal (25, 5*a)1468sage: I is G.ideal(3)1469True1470"""1471return self.number_field().ideal([self.prime(), self.number_field().gen()])**c14721473def unit_gens(self, c):1474r"""1475A list of generators `x_1, \dots, x_d` of the abelian group `F^\times /1476(1 + \mathfrak{p}^c)^\times`, where `c` is the given level, satisfying1477no relations other than `x_i^{n_i} = 1` for each `i` (where the1478integers `n_i` are returned by :meth:`exponents`). We adopt the1479convention that the final generator `x_d` is a uniformiser.14801481EXAMPLE::14821483sage: from sage.modular.local_comp.smoothchar import SmoothCharacterGroupRamifiedQuadratic1484sage: G = SmoothCharacterGroupRamifiedQuadratic(5, 0, QQ)1485sage: G.unit_gens(0)1486[s]1487sage: G.unit_gens(1)1488[2, s]1489sage: G.unit_gens(8)1490[2, s + 1, s]1491"""1492d = ceil(ZZ(c) / 2)1493p = self.prime()1494K,s = self.number_field().objgen()1495zpgens = [K(ZZ(x)) for x in Zmod(p**d).unit_gens()]1496if c == 0:1497return [s]1498if c == 1:1499return zpgens + [s]1500elif p > 3 or self._unif_sqr == 3 or c <= 3:1501return zpgens + [1 + s, s]1502else:1503# Awkward case: K = Q_3(sqrt(-3)). Here the exponential map doesn't1504# converge on 1 + P, and the quotient (O_K*) / (Zp*) isn't1505# topologically cyclic. I don't know an explicit set of good1506# generators here, so we let Pari do the work and put up with the1507# rather arbitrary (nondeterministic?) results.1508return list(self.ideal(c).idealstar(2).gens_values()) + [s]15091510def exponents(self, c):1511r"""1512Return the orders of the independent generators of the unit group1513returned by :meth:`~unit_gens`.15141515EXAMPLE::15161517sage: from sage.modular.local_comp.smoothchar import SmoothCharacterGroupRamifiedQuadratic1518sage: G = SmoothCharacterGroupRamifiedQuadratic(5, 0, QQ)1519sage: G.exponents(0)1520(0,)1521sage: G.exponents(1)1522(4, 0)1523sage: G.exponents(8)1524(500, 625, 0)1525"""1526c = ZZ(c)1527d = ceil(c / 2)1528p = self.prime()1529if c == 0:1530return tuple([0])1531elif c == 1:1532return tuple([p - 1, 0])1533elif p > 3 or self._unif_sqr == 3 or c <= 3:1534return tuple([p**(d-1)*(p - 1), p**ceil((c - 1)/2), 0])1535else:1536# awkward case, see above1537return self.ideal(c).idealstar(2).gens_orders() + (0,)15381539def subgroup_gens(self, level):1540r"""1541A set of elements of `(\mathcal{O}_F / \mathfrak{p}^c)^\times`1542generating the kernel of the reduction map to `(\mathcal{O}_F /1543\mathfrak{p}^{c-1})^\times`.15441545EXAMPLE::15461547sage: from sage.modular.local_comp.smoothchar import SmoothCharacterGroupRamifiedQuadratic1548sage: G = SmoothCharacterGroupRamifiedQuadratic(3, 1, QQ)1549sage: G.subgroup_gens(2)1550[s + 1]1551"""1552if level == 0:1553raise ValueError1554elif level == 1:1555return self.unit_gens(level)[:-1]1556else:1557return [1 + self.number_field().gen()**(level - 1)]15581559def discrete_log(self, level, x):1560r"""1561Solve the discrete log problem in the unit group.15621563EXAMPLE::15641565sage: from sage.modular.local_comp.smoothchar import SmoothCharacterGroupRamifiedQuadratic1566sage: G = SmoothCharacterGroupRamifiedQuadratic(3, 1, QQ)1567sage: s = G.number_field().gen()1568sage: G.discrete_log(4, 3 + 2*s)1569[5, 2, 1, 1]1570sage: gs = G.unit_gens(4); gs[0]^5 * gs[1]^2 * gs[2] * gs[3] - (3 + 2*s) in G.ideal(4)1571True1572"""1573x = self.number_field().coerce(x)1574if x == 0: raise ValueError, "cannot evaluate at zero"1575n1 = x.valuation(self.ideal(1))1576x1 = x / self.number_field().gen()**n11577if level == 0:1578return [n1]1579else:1580return self.ideal(level).ideallog(x1, self.unit_gens(level)[:-1]) + [n1]158115821583