def central_character(self): r""" Return the central character of this representation. This is the restriction to `\QQ_p^\times` of the unique smooth character `\omega` of `\mathbf{A}^\times / \QQ^\times` such that `\omega(\varpi_\ell) = \ell^j \varepsilon(\ell)` for all primes `\ell \nmid Np`, where `\varpi_\ell` is a uniformiser at `\ell`, `\varepsilon` is the Nebentypus character of the newform `f`, and `j` is the twist factor (see the documentation for :func:`~LocalComponent`). EXAMPLES:: sage: LocalComponent(Newform('27a'), 3).central_character() Character of Q_3*, of level 0, mapping 3 |--> 1 sage: LocalComponent(Newforms(Gamma1(5), 5, names='c')[0], 5).central_character() Character of Q_5*, of level 1, mapping 2 |--> c0 + 1, 5 |--> 125 sage: LocalComponent(Newforms(DirichletGroup(24)([1, -1,-1]), 3, names='a')[0], 2).central_character() Character of Q_2*, of level 3, mapping 7 |--> 1, 5 |--> -1, 2 |--> -2 """ from sage.rings.arith import crt chi = self.newform().character() f = self.prime() ** self.conductor() N = self.newform().level() // f G = DirichletGroup(f, self.coefficient_field()) chip = G([chi(crt(ZZ(x), 1, f, N)) for x in G.unit_gens()]).primitive_character() a = crt(1, self.prime(), f, N) if chip.conductor() == 1: return SmoothCharacterGroupQp(self.prime(), self.coefficient_field()).character(0, [chi(a) * self.prime()**self.twist_factor()]) else: return SmoothCharacterGroupQp(self.prime(), self.coefficient_field()).character(chip.conductor().valuation(self.prime()), list((~chip).values_on_gens()) + [chi(a) * self.prime()**self.twist_factor()])
def lift_to_gamma1(g, m, n): r""" If ``g = [a,b,c,d]`` is a list of integers defining a `2 \times 2` matrix whose determinant is `1 \pmod m`, return a list of integers giving the entries of a matrix which is congruent to `g \pmod m` and to `\begin{pmatrix} 1 & * \\ 0 & 1 \end{pmatrix} \pmod n`. Here `m` and `n` must be coprime. Here `m` and `n` should be coprime positive integers. Either of `m` and `n` can be `1`. If `n = 1`, this still makes perfect sense; this is what is called by the function :func:`~lift_matrix_to_sl2z`. If `m = 1` this is a rather silly question, so we adopt the convention of always returning the identity matrix. The result is always a list of Sage integers (unlike ``lift_to_sl2z``, which tends to return Python ints). EXAMPLE:: sage: from sage.modular.local_comp.liftings import lift_to_gamma1 sage: A = matrix(ZZ, 2, lift_to_gamma1([10, 11, 3, 11], 19, 5)); A [371 68] [ 60 11] sage: A.det() == 1 True sage: A.change_ring(Zmod(19)) [10 11] [ 3 11] sage: A.change_ring(Zmod(5)) [1 3] [0 1] sage: m = list(SL2Z.random_element()) sage: n = lift_to_gamma1(m, 11, 17) sage: assert matrix(Zmod(11), 2, n) == matrix(Zmod(11),2,m) sage: assert matrix(Zmod(17), 2, [n[0], 0, n[2], n[3]]) == 1 sage: type(lift_to_gamma1([10,11,3,11],19,5)[0]) <type 'sage.rings.integer.Integer'> Tests with `m = 1` and with `n = 1`:: sage: lift_to_gamma1([1,1,0,1], 5, 1) [1, 1, 0, 1] sage: lift_to_gamma1([2,3,11,22], 1, 5) [1, 0, 0, 1] """ if m == 1: return [ZZ(1), ZZ(0), ZZ(0), ZZ(1)] a, b, c, d = [ZZ(x) for x in g] if not (a * d - b * c) % m == 1: raise ValueError("Determinant is {0} mod {1}, should be 1".format( (a * d - b * c) % m, m)) c2 = crt(c, 0, m, n) d2 = crt(d, 1, m, n) a3, b3, c3, d3 = [ZZ(_) for _ in lift_to_sl2z(c2, d2, m * n)] r = (a3 * b - b3 * a) % m return [a3 + r * c3, b3 + r * d3, c3, d3]
def lift_to_gamma1(g, m, n): r""" If ``g = [a,b,c,d]`` is a list of integers defining a `2 \times 2` matrix whose determinant is `1 \pmod m`, return a list of integers giving the entries of a matrix which is congruent to `g \pmod m` and to `\begin{pmatrix} 1 & * \\ 0 & 1 \end{pmatrix} \pmod n`. Here `m` and `n` must be coprime. Here `m` and `n` should be coprime positive integers. Either of `m` and `n` can be `1`. If `n = 1`, this still makes perfect sense; this is what is called by the function :func:`~lift_matrix_to_sl2z`. If `m = 1` this is a rather silly question, so we adopt the convention of always returning the identity matrix. The result is always a list of Sage integers (unlike ``lift_to_sl2z``, which tends to return Python ints). EXAMPLE:: sage: from sage.modular.local_comp.liftings import lift_to_gamma1 sage: A = matrix(ZZ, 2, lift_to_gamma1([10, 11, 3, 11], 19, 5)); A [371 68] [ 60 11] sage: A.det() == 1 True sage: A.change_ring(Zmod(19)) [10 11] [ 3 11] sage: A.change_ring(Zmod(5)) [1 3] [0 1] sage: m = list(SL2Z.random_element()) sage: n = lift_to_gamma1(m, 11, 17) sage: assert matrix(Zmod(11), 2, n) == matrix(Zmod(11),2,m) sage: assert matrix(Zmod(17), 2, [n[0], 0, n[2], n[3]]) == 1 sage: type(lift_to_gamma1([10,11,3,11],19,5)[0]) <type 'sage.rings.integer.Integer'> Tests with `m = 1` and with `n = 1`:: sage: lift_to_gamma1([1,1,0,1], 5, 1) [1, 1, 0, 1] sage: lift_to_gamma1([2,3,11,22], 1, 5) [1, 0, 0, 1] """ if m == 1: return [ZZ(1),ZZ(0),ZZ(0),ZZ(1)] a,b,c,d = [ZZ(x) for x in g] if not (a*d - b*c) % m == 1: raise ValueError( "Determinant is {0} mod {1}, should be 1".format((a*d - b*c) % m, m) ) c2 = crt(c, 0, m, n) d2 = crt(d, 1, m, n) a3,b3,c3,d3 = map(ZZ, lift_to_sl2z(c2,d2,m*n)) r = (a3*b - b3*a) % m return [a3 + r*c3, b3 + r*d3, c3, d3]
def lift_ramified(g, p, u, n): r""" Given four integers `a,b,c,d` with `p \mid c` and `ad - bc = 1 \pmod{p^u}`, find `a',b',c',d'` congruent to `a,b,c,d \pmod{p^u}`, with `c' = c \pmod{p^{u+1}}`, such that `a'd' - b'c'` is exactly 1, and `\begin{pmatrix} a & b \\ c & d \end{pmatrix}` is in `\Gamma_1(n)`. Algorithm: Uses :func:`~lift_to_gamma1` to get a lifting modulo `p^u`, and then adds an appropriate multiple of the top row to the bottom row in order to get the bottom-left entry correct modulo `p^{u+1}`. EXAMPLE:: sage: from sage.modular.local_comp.liftings import lift_ramified sage: lift_ramified([2,2,3,2], 3, 1, 1) [5, 8, 3, 5] sage: lift_ramified([8,2,12,2], 3, 2, 23) [323, 110, -133584, -45493] sage: type(lift_ramified([8,2,12,2], 3, 2, 23)[0]) <type 'sage.rings.integer.Integer'> """ a,b,c,d = lift_to_gamma1(g, p**u, n) r = crt( (c - g[2]) / p**u * inverse_mod(a, p), 0, p, n) c = c - p**u * r * a d = d - p**u * r * b # assert (c - g[2]) % p**(u+1) == 0 return [a,b,c,d]
def _iterator_discriminant(self, epsilon, offset): """ Return iterator over all possible discriminants of a Fourier index given a content ``eps`` and a discriminant offset modulo `D`. INPUT: - `\epsilon` -- Integer; Content of an index. - ``offset`` -- Integer; Offset modulo D of the discriminant. OUTPUT: - Iterator over Integers. TESTS:: sage: fac = HermitianModularFormD2Factory(4,-3) sage: list(fac._iterator_discriminant(2, 3)) [0, 12, 24] sage: list(fac._iterator_discriminant(2, 2)) [8, 20] sage: list(fac._iterator_discriminant(1, 2)) [2, 5, 8, 11, 14, 17, 20, 23, 26] """ mD = -self.__D periode = lcm(mD, epsilon**2) offset = crt(offset, 0, mD, epsilon**2) % periode return xrange(offset, self.__precision._enveloping_discriminant_bound(), periode)
def _iterator_discriminant(self, epsilon, offset) : """ Return iterator over all possible discriminants of a Fourier index given a content ``eps`` and a discriminant offset modulo `D`. INPUT: - `\epsilon` -- Integer; Content of an index. - ``offset`` -- Integer; Offset modulo D of the discriminant. OUTPUT: - Iterator over Integers. TESTS:: sage: fac = HermitianModularFormD2Factory(4,-3) sage: list(fac._iterator_discriminant(2, 3)) [0, 12, 24] sage: list(fac._iterator_discriminant(2, 2)) [8, 20] sage: list(fac._iterator_discriminant(1, 2)) [2, 5, 8, 11, 14, 17, 20, 23, 26] """ mD = -self.__D periode = lcm(mD, epsilon**2) offset = crt(offset, 0, mD, epsilon**2) % periode return xrange( offset, self.__precision._enveloping_discriminant_bound(), periode )
def central_character(self): r""" Return the central character of this representation. This is the restriction to `\QQ_p^\times` of the unique smooth character `\omega` of `\mathbf{A}^\times / \QQ^\times` such that `\omega(\varpi_\ell) = \ell^j \varepsilon(\ell)` for all primes `\ell \nmid Np`, where `\varpi_\ell` is a uniformiser at `\ell`, `\varepsilon` is the Nebentypus character of the newform `f`, and `j` is the twist factor (see the documentation for :func:`~LocalComponent`). EXAMPLES:: sage: LocalComponent(Newform('27a'), 3).central_character() Character of Q_3*, of level 0, mapping 3 |--> 1 sage: LocalComponent(Newforms(Gamma1(5), 5, names='c')[0], 5).central_character() Character of Q_5*, of level 1, mapping 2 |--> c0 + 1, 5 |--> 125 sage: LocalComponent(Newforms(DirichletGroup(24)([1, -1,-1]), 3, names='a')[0], 2).central_character() Character of Q_2*, of level 3, mapping 7 |--> 1, 5 |--> -1, 2 |--> -2 """ from sage.rings.arith import crt chi = self.newform().character() f = self.prime()**self.conductor() N = self.newform().level() // f G = DirichletGroup(f, self.coefficient_field()) chip = G([chi(crt(ZZ(x), 1, f, N)) for x in G.unit_gens()]).primitive_character() a = crt(1, self.prime(), f, N) if chip.conductor() == 1: return SmoothCharacterGroupQp( self.prime(), self.coefficient_field()).character( 0, [chi(a) * self.prime()**self.twist_factor()]) else: return SmoothCharacterGroupQp( self.prime(), self.coefficient_field()).character( chip.conductor().valuation(self.prime()), list((~chip).values_on_gens()) + [chi(a) * self.prime()**self.twist_factor()])
def group(self): r""" Return a `\Gamma_H` group which is the level of all of the relevant twists of `f`. EXAMPLE:: sage: from sage.modular.local_comp.type_space import example_type_space sage: example_type_space().group() Congruence Subgroup Gamma_H(98) with H generated by [57] """ p = self.prime() r = self.conductor() d = max(self.character_conductor(), r // 2) n = self.tame_level() chi = self.form().character() tame_H = [i for i in chi.kernel() if (i % p**r) == 1] wild_H = [crt(1 + p**d, 1, p**r, n)] return GammaH(n * p**r, tame_H + wild_H)
def group(self): r""" Return a `\Gamma_H` group which is the level of all of the relevant twists of `f`. EXAMPLE:: sage: from sage.modular.local_comp.type_space import example_type_space sage: example_type_space().group() Congruence Subgroup Gamma_H(98) with H generated by [57] """ p = self.prime() r = self.conductor() d = max(self.character_conductor(), r//2) n = self.tame_level() chi = self.form().character() tame_H = [i for i in chi.kernel() if (i % p**r) == 1] wild_H = [crt(1 + p**d, 1, p**r, n)] return GammaH(n * p**r, tame_H + wild_H)
def rho(self, g): r""" Calculate the action of the group element `g` on the type space. EXAMPLE:: sage: from sage.modular.local_comp.type_space import example_type_space sage: T = example_type_space(2) sage: m = T.rho([2,0,0,1]); m [ 1 -2 1 0] [ 1 -1 0 1] [ 1 0 -1 1] [ 0 1 -2 1] sage: v = T.eigensymbol_subspace().basis()[0] sage: m * v == v True We test that it is a left action:: sage: T = example_type_space(0) sage: a = [0,5,4,3]; b = [0,2,3,5]; ab = [1,4,2,2] sage: T.rho(ab) == T.rho(a) * T.rho(b) True An odd level example:: sage: from sage.modular.local_comp.type_space import TypeSpace sage: T = TypeSpace(Newform('54a'), 3) sage: a = [0,1,3,0]; b = [2,1,0,1]; ab = [0,1,6,3] sage: T.rho(ab) == T.rho(a) * T.rho(b) True """ if not self.is_minimal(): raise NotImplementedError( "Group action on non-minimal type space not implemented") if self.u() == 0: # silly special case: rep is principal series or special, so SL2 # action on type space is trivial raise ValueError("Representation is not supercuspidal") p = self.prime() f = p**self.u() g = map(ZZ, g) d = (g[0] * g[3] - g[2] * g[1]) # g is in S(K_0) (easy case) if d % f == 1: return self._rho_s(g) # g is in K_0, but not in S(K_0) if d % p != 0: try: a = self._a except AttributeError: self._discover_torus_action() a = self._a i = 0 while (d * a**i) % f != 1: i += 1 if i > f: raise ArithmeticError return self._rho_s([a**i * g[0], g[1], a**i * g[2], g[3] ]) * self._amat**(-i) # funny business if (self.conductor() % 2 == 0): if all([x.valuation(p) > 0 for x in g]): eps = self.form().character()(crt(1, p, f, self.tame_level())) return ~eps * self.rho([x // p for x in g]) else: raise ArithmeticError("g(={0}) not in K".format(g)) else: m = matrix(ZZ, 2, g) s = m.det().valuation(p) mm = (matrix(QQ, 2, [0, -1, p, 0])**(-s) * m).change_ring(ZZ) return self._unif_ramified()**s * self.rho(mm.list())
def rho(self, g): r""" Calculate the action of the group element `g` on the type space. EXAMPLE:: sage: from sage.modular.local_comp.type_space import example_type_space sage: T = example_type_space(2) sage: m = T.rho([2,0,0,1]); m [ 1 -2 1 0] [ 1 -1 0 1] [ 1 0 -1 1] [ 0 1 -2 1] sage: v = T.eigensymbol_subspace().basis()[0] sage: m * v == v True We test that it is a left action:: sage: T = example_type_space(0) sage: a = [0,5,4,3]; b = [0,2,3,5]; ab = [1,4,2,2] sage: T.rho(ab) == T.rho(a) * T.rho(b) True An odd level example:: sage: from sage.modular.local_comp.type_space import TypeSpace sage: T = TypeSpace(Newform('54a'), 3) sage: a = [0,1,3,0]; b = [2,1,0,1]; ab = [0,1,6,3] sage: T.rho(ab) == T.rho(a) * T.rho(b) True """ if not self.is_minimal(): raise NotImplementedError( "Group action on non-minimal type space not implemented" ) if self.u() == 0: # silly special case: rep is principal series or special, so SL2 # action on type space is trivial raise ValueError( "Representation is not supercuspidal" ) p = self.prime() f = p**self.u() g = map(ZZ, g) d = (g[0]*g[3] - g[2]*g[1]) # g is in S(K_0) (easy case) if d % f == 1: return self._rho_s(g) # g is in K_0, but not in S(K_0) if d % p != 0: try: a = self._a except: self._discover_torus_action() a = self._a i = 0 while (d * a**i) % f != 1: i += 1 if i > f: raise ArithmeticError return self._rho_s([a**i*g[0], g[1], a**i*g[2], g[3]]) * self._amat**(-i) # funny business if (self.conductor() % 2 == 0): if all([x.valuation(p) > 0 for x in g]): eps = self.form().character()(crt(1, p, f, self.tame_level())) return ~eps * self.rho([x // p for x in g]) else: raise ArithmeticError( "g(={0}) not in K".format(g) ) else: m = matrix(ZZ, 2, g) s = m.det().valuation(p) mm = (matrix(QQ, 2, [0, -1, p, 0])**(-s) * m).change_ring(ZZ) return self._unif_ramified()**s * self.rho(mm.list())