Dirichlet characters#
A DirichletCharacter
is the extension of a homomorphism
for some ring \(R\), to the map \(\ZZ/N\ZZ \to R\) obtained by sending those \(x\in\ZZ/N\ZZ\) with \(\gcd(N,x)>1\) to \(0\).
EXAMPLES:
sage: G = DirichletGroup(35)
sage: x = G.gens()
sage: e = x[0]*x[1]^2; e
Dirichlet character modulo 35 of conductor 35
mapping 22 |--> zeta12^3, 31 |--> zeta12^2 - 1
sage: e.order()
12
>>> from sage.all import *
>>> G = DirichletGroup(Integer(35))
>>> x = G.gens()
>>> e = x[Integer(0)]*x[Integer(1)]**Integer(2); e
Dirichlet character modulo 35 of conductor 35
mapping 22 |--> zeta12^3, 31 |--> zeta12^2 - 1
>>> e.order()
12
This illustrates a canonical coercion:
sage: e = DirichletGroup(5, QQ).0
sage: f = DirichletGroup(5, CyclotomicField(4)).0
sage: e*f
Dirichlet character modulo 5 of conductor 5 mapping 2 |--> -zeta4
>>> from sage.all import *
>>> e = DirichletGroup(Integer(5), QQ).gen(0)
>>> f = DirichletGroup(Integer(5), CyclotomicField(Integer(4))).gen(0)
>>> e*f
Dirichlet character modulo 5 of conductor 5 mapping 2 |--> -zeta4
AUTHORS:
William Stein (2005-09-02): Fixed bug in comparison of Dirichlet characters. It was checking that their values were the same, but not checking that they had the same level!
William Stein (2006-01-07): added more examples
William Stein (2006-05-21): added examples of everything; fix a lot of tiny bugs and design problem that became clear when creating examples.
Craig Citro (2008-02-16): speed up __call__ method for Dirichlet characters, miscellaneous fixes
Julian Rueth (2014-03-06): use UniqueFactory to cache DirichletGroups
- class sage.modular.dirichlet.DirichletCharacter(parent, x, check=True)[source]#
Bases:
MultiplicativeGroupElement
A Dirichlet character.
- bar()[source]#
Return the complex conjugate of this Dirichlet character.
EXAMPLES:
sage: e = DirichletGroup(5).0 sage: e Dirichlet character modulo 5 of conductor 5 mapping 2 |--> zeta4 sage: e.bar() Dirichlet character modulo 5 of conductor 5 mapping 2 |--> -zeta4
>>> from sage.all import * >>> e = DirichletGroup(Integer(5)).gen(0) >>> e Dirichlet character modulo 5 of conductor 5 mapping 2 |--> zeta4 >>> e.bar() Dirichlet character modulo 5 of conductor 5 mapping 2 |--> -zeta4
- base_ring()[source]#
Return the base ring of this Dirichlet character.
EXAMPLES:
sage: G = DirichletGroup(11) sage: G.gen(0).base_ring() Cyclotomic Field of order 10 and degree 4 sage: G = DirichletGroup(11, RationalField()) sage: G.gen(0).base_ring() Rational Field
>>> from sage.all import * >>> G = DirichletGroup(Integer(11)) >>> G.gen(Integer(0)).base_ring() Cyclotomic Field of order 10 and degree 4 >>> G = DirichletGroup(Integer(11), RationalField()) >>> G.gen(Integer(0)).base_ring() Rational Field
- bernoulli(k, algorithm='recurrence', cache=True, **opts)[source]#
Return the generalized Bernoulli number \(B_{k,eps}\).
INPUT:
k
– a non-negative integeralgorithm
– either'recurrence'
(default) or'definition'
cache
– if True, cache answers**opts
– optional arguments; not used directly, but passed to thebernoulli()
function if this is called
OUTPUT:
Let \(\varepsilon\) be a (not necessarily primitive) character of modulus \(N\). This function returns the generalized Bernoulli number \(B_{k,\varepsilon}\), as defined by the following identity of power series (see for example [DI1995], Section 2.2):
\[\sum_{a=1}^N \frac{\varepsilon(a) t e^{at}}{e^{Nt}-1} = \sum_{k=0}^{\infty} \frac{B_{k,\varepsilon}}{k!} t^k.\]ALGORITHM:
The
'recurrence'
algorithm computes generalized Bernoulli numbers via classical Bernoulli numbers using the formula in [Coh2007], Proposition 9.4.5; this is usually optimal. Thedefinition
algorithm uses the definition directly.Warning
In the case of the trivial Dirichlet character modulo 1, this function returns \(B_{1,\varepsilon} = 1/2\), in accordance with the above definition, but in contrast to the value \(B_1 = -1/2\) for the classical Bernoulli number. Some authors use an alternative definition giving \(B_{1,\varepsilon} = -1/2\); see the discussion in [Coh2007], Section 9.4.1.
EXAMPLES:
sage: G = DirichletGroup(13) sage: e = G.0 sage: e.bernoulli(5) 7430/13*zeta12^3 - 34750/13*zeta12^2 - 11380/13*zeta12 + 9110/13 sage: eps = DirichletGroup(9).0 sage: eps.bernoulli(3) 10*zeta6 + 4 sage: eps.bernoulli(3, algorithm="definition") 10*zeta6 + 4
>>> from sage.all import * >>> G = DirichletGroup(Integer(13)) >>> e = G.gen(0) >>> e.bernoulli(Integer(5)) 7430/13*zeta12^3 - 34750/13*zeta12^2 - 11380/13*zeta12 + 9110/13 >>> eps = DirichletGroup(Integer(9)).gen(0) >>> eps.bernoulli(Integer(3)) 10*zeta6 + 4 >>> eps.bernoulli(Integer(3), algorithm="definition") 10*zeta6 + 4
- change_ring(R)[source]#
Return the base extension of
self
toR
.INPUT:
R
– either a ring admitting a conversion map from the base ring ofself
, or a ring homomorphism with the base ring ofself
as its domain
EXAMPLES:
sage: e = DirichletGroup(7, QQ).0 sage: f = e.change_ring(QuadraticField(3, 'a')) sage: f.parent() Group of Dirichlet characters modulo 7 with values in Number Field in a with defining polynomial x^2 - 3 with a = 1.732050807568878?
>>> from sage.all import * >>> e = DirichletGroup(Integer(7), QQ).gen(0) >>> f = e.change_ring(QuadraticField(Integer(3), 'a')) >>> f.parent() Group of Dirichlet characters modulo 7 with values in Number Field in a with defining polynomial x^2 - 3 with a = 1.732050807568878?
sage: e = DirichletGroup(13).0 sage: e.change_ring(QQ) Traceback (most recent call last): ... TypeError: Unable to coerce zeta12 to a rational
>>> from sage.all import * >>> e = DirichletGroup(Integer(13)).gen(0) >>> e.change_ring(QQ) Traceback (most recent call last): ... TypeError: Unable to coerce zeta12 to a rational
We test the case where \(R\) is a map (Issue #18072):
sage: K.<i> = QuadraticField(-1) sage: chi = DirichletGroup(5, K)[1] sage: chi(2) i sage: f = K.complex_embeddings()[0] sage: psi = chi.change_ring(f) sage: psi(2) -1.83697019872103e-16 - 1.00000000000000*I
>>> from sage.all import * >>> K = QuadraticField(-Integer(1), names=('i',)); (i,) = K._first_ngens(1) >>> chi = DirichletGroup(Integer(5), K)[Integer(1)] >>> chi(Integer(2)) i >>> f = K.complex_embeddings()[Integer(0)] >>> psi = chi.change_ring(f) >>> psi(Integer(2)) -1.83697019872103e-16 - 1.00000000000000*I
- conductor()[source]#
Compute and return the conductor of this character.
EXAMPLES:
sage: G.<a,b> = DirichletGroup(20) sage: a.conductor() 4 sage: b.conductor() 5 sage: (a*b).conductor() 20
>>> from sage.all import * >>> G = DirichletGroup(Integer(20), names=('a', 'b',)); (a, b,) = G._first_ngens(2) >>> a.conductor() 4 >>> b.conductor() 5 >>> (a*b).conductor() 20
- conrey_number()[source]#
Return the Conrey number for this character.
This is a positive integer coprime to \(q\) that identifies a Dirichlet character of modulus \(q\).
See https://www.lmfdb.org/knowledge/show/character.dirichlet.conrey
EXAMPLES:
sage: # needs sage.rings.number_field sage: chi4 = DirichletGroup(4).gen() sage: chi4.conrey_number() 3 sage: chi = DirichletGroup(24)([1,-1,-1]); chi Dirichlet character modulo 24 of conductor 24 mapping 7 |--> 1, 13 |--> -1, 17 |--> -1 sage: chi.conrey_number() 5 sage: chi = DirichletGroup(60)([1,-1,I]) sage: chi.conrey_number() 17 sage: chi = DirichletGroup(420)([1,-1,-I,1]) sage: chi.conrey_number() 113
>>> from sage.all import * >>> # needs sage.rings.number_field >>> chi4 = DirichletGroup(Integer(4)).gen() >>> chi4.conrey_number() 3 >>> chi = DirichletGroup(Integer(24))([Integer(1),-Integer(1),-Integer(1)]); chi Dirichlet character modulo 24 of conductor 24 mapping 7 |--> 1, 13 |--> -1, 17 |--> -1 >>> chi.conrey_number() 5 >>> chi = DirichletGroup(Integer(60))([Integer(1),-Integer(1),I]) >>> chi.conrey_number() 17 >>> chi = DirichletGroup(Integer(420))([Integer(1),-Integer(1),-I,Integer(1)]) >>> chi.conrey_number() 113
- decomposition()[source]#
Return the decomposition of
self
as a product of Dirichlet characters of prime power modulus, where the prime powers exactly divide the modulus of this character.EXAMPLES:
sage: G.<a,b> = DirichletGroup(20) sage: c = a*b sage: d = c.decomposition(); d [Dirichlet character modulo 4 of conductor 4 mapping 3 |--> -1, Dirichlet character modulo 5 of conductor 5 mapping 2 |--> zeta4] sage: d[0].parent() Group of Dirichlet characters modulo 4 with values in Cyclotomic Field of order 4 and degree 2 sage: d[1].parent() Group of Dirichlet characters modulo 5 with values in Cyclotomic Field of order 4 and degree 2
>>> from sage.all import * >>> G = DirichletGroup(Integer(20), names=('a', 'b',)); (a, b,) = G._first_ngens(2) >>> c = a*b >>> d = c.decomposition(); d [Dirichlet character modulo 4 of conductor 4 mapping 3 |--> -1, Dirichlet character modulo 5 of conductor 5 mapping 2 |--> zeta4] >>> d[Integer(0)].parent() Group of Dirichlet characters modulo 4 with values in Cyclotomic Field of order 4 and degree 2 >>> d[Integer(1)].parent() Group of Dirichlet characters modulo 5 with values in Cyclotomic Field of order 4 and degree 2
We cannot multiply directly, since coercion of one element into the other parent fails in both cases:
sage: d[0]*d[1] == c Traceback (most recent call last): ... TypeError: unsupported operand parent(s) for *: 'Group of Dirichlet characters modulo 4 with values in Cyclotomic Field of order 4 and degree 2' and 'Group of Dirichlet characters modulo 5 with values in Cyclotomic Field of order 4 and degree 2'
>>> from sage.all import * >>> d[Integer(0)]*d[Integer(1)] == c Traceback (most recent call last): ... TypeError: unsupported operand parent(s) for *: 'Group of Dirichlet characters modulo 4 with values in Cyclotomic Field of order 4 and degree 2' and 'Group of Dirichlet characters modulo 5 with values in Cyclotomic Field of order 4 and degree 2'
We can multiply if we are explicit about where we want the multiplication to take place.
sage: G(d[0])*G(d[1]) == c True
>>> from sage.all import * >>> G(d[Integer(0)])*G(d[Integer(1)]) == c True
Conductors that are divisible by various powers of 2 present some problems as the multiplicative group modulo \(2^k\) is trivial for \(k = 1\) and non-cyclic for \(k \ge 3\):
sage: (DirichletGroup(18).0).decomposition() [Dirichlet character modulo 2 of conductor 1, Dirichlet character modulo 9 of conductor 9 mapping 2 |--> zeta6] sage: (DirichletGroup(36).0).decomposition() [Dirichlet character modulo 4 of conductor 4 mapping 3 |--> -1, Dirichlet character modulo 9 of conductor 1 mapping 2 |--> 1] sage: (DirichletGroup(72).0).decomposition() [Dirichlet character modulo 8 of conductor 4 mapping 7 |--> -1, 5 |--> 1, Dirichlet character modulo 9 of conductor 1 mapping 2 |--> 1]
>>> from sage.all import * >>> (DirichletGroup(Integer(18)).gen(0)).decomposition() [Dirichlet character modulo 2 of conductor 1, Dirichlet character modulo 9 of conductor 9 mapping 2 |--> zeta6] >>> (DirichletGroup(Integer(36)).gen(0)).decomposition() [Dirichlet character modulo 4 of conductor 4 mapping 3 |--> -1, Dirichlet character modulo 9 of conductor 1 mapping 2 |--> 1] >>> (DirichletGroup(Integer(72)).gen(0)).decomposition() [Dirichlet character modulo 8 of conductor 4 mapping 7 |--> -1, 5 |--> 1, Dirichlet character modulo 9 of conductor 1 mapping 2 |--> 1]
- element()[source]#
Return the underlying \(\ZZ/n\ZZ\)-module vector of exponents.
EXAMPLES:
sage: G.<a,b> = DirichletGroup(20) sage: a.element() (2, 0) sage: b.element() (0, 1)
>>> from sage.all import * >>> G = DirichletGroup(Integer(20), names=('a', 'b',)); (a, b,) = G._first_ngens(2) >>> a.element() (2, 0) >>> b.element() (0, 1)
Note
The constructor of
DirichletCharacter
sets the cache ofelement()
or ofvalues_on_gens()
. The cache of one of these methods needs to be set for the other method to work properly, these caches have to be stored when pickling an instance ofDirichletCharacter
.
- extend(M)[source]#
Return the extension of this character to a Dirichlet character modulo the multiple
M
of the modulus.EXAMPLES:
sage: G.<a,b> = DirichletGroup(20) sage: H.<c> = DirichletGroup(4) sage: c.extend(20) Dirichlet character modulo 20 of conductor 4 mapping 11 |--> -1, 17 |--> 1 sage: a Dirichlet character modulo 20 of conductor 4 mapping 11 |--> -1, 17 |--> 1 sage: c.extend(20) == a True
>>> from sage.all import * >>> G = DirichletGroup(Integer(20), names=('a', 'b',)); (a, b,) = G._first_ngens(2) >>> H = DirichletGroup(Integer(4), names=('c',)); (c,) = H._first_ngens(1) >>> c.extend(Integer(20)) Dirichlet character modulo 20 of conductor 4 mapping 11 |--> -1, 17 |--> 1 >>> a Dirichlet character modulo 20 of conductor 4 mapping 11 |--> -1, 17 |--> 1 >>> c.extend(Integer(20)) == a True
- fixed_field()[source]#
Given a Dirichlet character, this will return the abelian extension fixed by the kernel of the corresponding Galois character.
OUTPUT:
a number field
EXAMPLES:
sage: G = DirichletGroup(37) sage: chi = G.0 sage: psi = chi^18 sage: psi.fixed_field() Number Field in a with defining polynomial x^2 + x - 9 sage: G = DirichletGroup(7) sage: chi = G.0^2 sage: chi Dirichlet character modulo 7 of conductor 7 mapping 3 |--> zeta6 - 1 sage: chi.fixed_field() Number Field in a with defining polynomial x^3 + x^2 - 2*x - 1 sage: G = DirichletGroup(31) sage: chi = G.0 sage: chi^6 Dirichlet character modulo 31 of conductor 31 mapping 3 |--> zeta30^6 sage: psi = chi^6 sage: psi.fixed_field() Number Field in a with defining polynomial x^5 + x^4 - 12*x^3 - 21*x^2 + x + 5
>>> from sage.all import * >>> G = DirichletGroup(Integer(37)) >>> chi = G.gen(0) >>> psi = chi**Integer(18) >>> psi.fixed_field() Number Field in a with defining polynomial x^2 + x - 9 >>> G = DirichletGroup(Integer(7)) >>> chi = G.gen(0)**Integer(2) >>> chi Dirichlet character modulo 7 of conductor 7 mapping 3 |--> zeta6 - 1 >>> chi.fixed_field() Number Field in a with defining polynomial x^3 + x^2 - 2*x - 1 >>> G = DirichletGroup(Integer(31)) >>> chi = G.gen(0) >>> chi**Integer(6) Dirichlet character modulo 31 of conductor 31 mapping 3 |--> zeta30^6 >>> psi = chi**Integer(6) >>> psi.fixed_field() Number Field in a with defining polynomial x^5 + x^4 - 12*x^3 - 21*x^2 + x + 5
- fixed_field_polynomial(algorithm='pari')[source]#
Given a Dirichlet character, this will return a polynomial generating the abelian extension fixed by the kernel of the corresponding Galois character.
ALGORITHM: (Sage)
A formula by Gauss for the products of periods; see Disquisitiones §343. See the source code for more.
OUTPUT:
a polynomial with integer coefficients
EXAMPLES:
sage: G = DirichletGroup(37) sage: chi = G.0 sage: psi = chi^18 sage: psi.fixed_field_polynomial() x^2 + x - 9 sage: G = DirichletGroup(7) sage: chi = G.0^2 sage: chi Dirichlet character modulo 7 of conductor 7 mapping 3 |--> zeta6 - 1 sage: chi.fixed_field_polynomial() x^3 + x^2 - 2*x - 1 sage: G = DirichletGroup(31) sage: chi = G.0 sage: chi^6 Dirichlet character modulo 31 of conductor 31 mapping 3 |--> zeta30^6 sage: psi = chi^6 sage: psi.fixed_field_polynomial() x^5 + x^4 - 12*x^3 - 21*x^2 + x + 5 sage: G = DirichletGroup(7) sage: chi = G.0 sage: chi.fixed_field_polynomial() x^6 + x^5 + x^4 + x^3 + x^2 + x + 1 sage: G = DirichletGroup(1001) sage: chi = G.0 sage: psi = chi^3 sage: psi.order() 2 sage: psi.fixed_field_polynomial(algorithm="pari") x^2 + x + 2
>>> from sage.all import * >>> G = DirichletGroup(Integer(37)) >>> chi = G.gen(0) >>> psi = chi**Integer(18) >>> psi.fixed_field_polynomial() x^2 + x - 9 >>> G = DirichletGroup(Integer(7)) >>> chi = G.gen(0)**Integer(2) >>> chi Dirichlet character modulo 7 of conductor 7 mapping 3 |--> zeta6 - 1 >>> chi.fixed_field_polynomial() x^3 + x^2 - 2*x - 1 >>> G = DirichletGroup(Integer(31)) >>> chi = G.gen(0) >>> chi**Integer(6) Dirichlet character modulo 31 of conductor 31 mapping 3 |--> zeta30^6 >>> psi = chi**Integer(6) >>> psi.fixed_field_polynomial() x^5 + x^4 - 12*x^3 - 21*x^2 + x + 5 >>> G = DirichletGroup(Integer(7)) >>> chi = G.gen(0) >>> chi.fixed_field_polynomial() x^6 + x^5 + x^4 + x^3 + x^2 + x + 1 >>> G = DirichletGroup(Integer(1001)) >>> chi = G.gen(0) >>> psi = chi**Integer(3) >>> psi.order() 2 >>> psi.fixed_field_polynomial(algorithm="pari") x^2 + x + 2
With the Sage implementation:
sage: G = DirichletGroup(37) sage: chi = G.0 sage: psi = chi^18 sage: psi.fixed_field_polynomial(algorithm="sage") x^2 + x - 9 sage: G = DirichletGroup(7) sage: chi = G.0^2 sage: chi Dirichlet character modulo 7 of conductor 7 mapping 3 |--> zeta6 - 1 sage: chi.fixed_field_polynomial(algorithm="sage") x^3 + x^2 - 2*x - 1 sage: G = DirichletGroup(31) sage: chi = G.0 sage: chi^6 Dirichlet character modulo 31 of conductor 31 mapping 3 |--> zeta30^6 sage: psi = chi^6 sage: psi.fixed_field_polynomial(algorithm="sage") x^5 + x^4 - 12*x^3 - 21*x^2 + x + 5 sage: G = DirichletGroup(7) sage: chi = G.0 sage: chi.fixed_field_polynomial(algorithm="sage") x^6 + x^5 + x^4 + x^3 + x^2 + x + 1 sage: G = DirichletGroup(1001) sage: chi = G.0 sage: psi = chi^3 sage: psi.order() 2 sage: psi.fixed_field_polynomial(algorithm="sage") x^2 + x + 2
>>> from sage.all import * >>> G = DirichletGroup(Integer(37)) >>> chi = G.gen(0) >>> psi = chi**Integer(18) >>> psi.fixed_field_polynomial(algorithm="sage") x^2 + x - 9 >>> G = DirichletGroup(Integer(7)) >>> chi = G.gen(0)**Integer(2) >>> chi Dirichlet character modulo 7 of conductor 7 mapping 3 |--> zeta6 - 1 >>> chi.fixed_field_polynomial(algorithm="sage") x^3 + x^2 - 2*x - 1 >>> G = DirichletGroup(Integer(31)) >>> chi = G.gen(0) >>> chi**Integer(6) Dirichlet character modulo 31 of conductor 31 mapping 3 |--> zeta30^6 >>> psi = chi**Integer(6) >>> psi.fixed_field_polynomial(algorithm="sage") x^5 + x^4 - 12*x^3 - 21*x^2 + x + 5 >>> G = DirichletGroup(Integer(7)) >>> chi = G.gen(0) >>> chi.fixed_field_polynomial(algorithm="sage") x^6 + x^5 + x^4 + x^3 + x^2 + x + 1 >>> G = DirichletGroup(Integer(1001)) >>> chi = G.gen(0) >>> psi = chi**Integer(3) >>> psi.order() 2 >>> psi.fixed_field_polynomial(algorithm="sage") x^2 + x + 2
The algorithm must be one of \(sage\) or \(pari\):
sage: G = DirichletGroup(1001) sage: chi = G.0 sage: psi = chi^3 sage: psi.order() 2 sage: psi.fixed_field_polynomial(algorithm="banana") Traceback (most recent call last): ... NotImplementedError: algorithm must be one of 'pari' or 'sage'
>>> from sage.all import * >>> G = DirichletGroup(Integer(1001)) >>> chi = G.gen(0) >>> psi = chi**Integer(3) >>> psi.order() 2 >>> psi.fixed_field_polynomial(algorithm="banana") Traceback (most recent call last): ... NotImplementedError: algorithm must be one of 'pari' or 'sage'
- galois_orbit(sort=True)[source]#
Return the orbit of this character under the action of the absolute Galois group of the prime subfield of the base ring.
EXAMPLES:
sage: G = DirichletGroup(30); e = G.1 sage: e.galois_orbit() [Dirichlet character modulo 30 of conductor 5 mapping 11 |--> 1, 7 |--> -zeta4, Dirichlet character modulo 30 of conductor 5 mapping 11 |--> 1, 7 |--> zeta4]
>>> from sage.all import * >>> G = DirichletGroup(Integer(30)); e = G.gen(1) >>> e.galois_orbit() [Dirichlet character modulo 30 of conductor 5 mapping 11 |--> 1, 7 |--> -zeta4, Dirichlet character modulo 30 of conductor 5 mapping 11 |--> 1, 7 |--> zeta4]
Another example:
sage: G = DirichletGroup(13) sage: G.galois_orbits() [ [Dirichlet character modulo 13 of conductor 1 mapping 2 |--> 1], ..., [Dirichlet character modulo 13 of conductor 13 mapping 2 |--> -1] ] sage: e = G.0 sage: e Dirichlet character modulo 13 of conductor 13 mapping 2 |--> zeta12 sage: e.galois_orbit() [Dirichlet character modulo 13 of conductor 13 mapping 2 |--> zeta12, Dirichlet character modulo 13 of conductor 13 mapping 2 |--> -zeta12^3 + zeta12, Dirichlet character modulo 13 of conductor 13 mapping 2 |--> zeta12^3 - zeta12, Dirichlet character modulo 13 of conductor 13 mapping 2 |--> -zeta12] sage: e = G.0^2; e Dirichlet character modulo 13 of conductor 13 mapping 2 |--> zeta12^2 sage: e.galois_orbit() [Dirichlet character modulo 13 of conductor 13 mapping 2 |--> zeta12^2, Dirichlet character modulo 13 of conductor 13 mapping 2 |--> -zeta12^2 + 1]
>>> from sage.all import * >>> G = DirichletGroup(Integer(13)) >>> G.galois_orbits() [ [Dirichlet character modulo 13 of conductor 1 mapping 2 |--> 1], ..., [Dirichlet character modulo 13 of conductor 13 mapping 2 |--> -1] ] >>> e = G.gen(0) >>> e Dirichlet character modulo 13 of conductor 13 mapping 2 |--> zeta12 >>> e.galois_orbit() [Dirichlet character modulo 13 of conductor 13 mapping 2 |--> zeta12, Dirichlet character modulo 13 of conductor 13 mapping 2 |--> -zeta12^3 + zeta12, Dirichlet character modulo 13 of conductor 13 mapping 2 |--> zeta12^3 - zeta12, Dirichlet character modulo 13 of conductor 13 mapping 2 |--> -zeta12] >>> e = G.gen(0)**Integer(2); e Dirichlet character modulo 13 of conductor 13 mapping 2 |--> zeta12^2 >>> e.galois_orbit() [Dirichlet character modulo 13 of conductor 13 mapping 2 |--> zeta12^2, Dirichlet character modulo 13 of conductor 13 mapping 2 |--> -zeta12^2 + 1]
A non-example:
sage: chi = DirichletGroup(7, Integers(9), zeta = Integers(9)(2)).0 sage: chi.galois_orbit() Traceback (most recent call last): ... TypeError: Galois orbits only defined if base ring is an integral domain
>>> from sage.all import * >>> chi = DirichletGroup(Integer(7), Integers(Integer(9)), zeta = Integers(Integer(9))(Integer(2))).gen(0) >>> chi.galois_orbit() Traceback (most recent call last): ... TypeError: Galois orbits only defined if base ring is an integral domain
- gauss_sum(a=1)[source]#
Return a Gauss sum associated to this Dirichlet character.
The Gauss sum associated to \(\chi\) is
\[g_a(\chi) = \sum_{r \in \ZZ/m\ZZ} \chi(r)\,\zeta^{ar},\]where \(m\) is the modulus of \(\chi\) and \(\zeta\) is a primitive \(m^{th}\) root of unity.
FACTS: If the modulus is a prime \(p\) and the character is nontrivial, then the Gauss sum has absolute value \(\sqrt{p}\).
CACHING: Computed Gauss sums are not cached with this character.
EXAMPLES:
sage: G = DirichletGroup(3) sage: e = G([-1]) sage: e.gauss_sum(1) 2*zeta6 - 1 sage: e.gauss_sum(2) -2*zeta6 + 1 sage: norm(e.gauss_sum()) 3
>>> from sage.all import * >>> G = DirichletGroup(Integer(3)) >>> e = G([-Integer(1)]) >>> e.gauss_sum(Integer(1)) 2*zeta6 - 1 >>> e.gauss_sum(Integer(2)) -2*zeta6 + 1 >>> norm(e.gauss_sum()) 3
sage: G = DirichletGroup(13) sage: e = G.0 sage: e.gauss_sum() -zeta156^46 + zeta156^45 + zeta156^42 + zeta156^41 + 2*zeta156^40 + zeta156^37 - zeta156^36 - zeta156^34 - zeta156^33 - zeta156^31 + 2*zeta156^30 + zeta156^28 - zeta156^24 - zeta156^22 + zeta156^21 + zeta156^20 - zeta156^19 + zeta156^18 - zeta156^16 - zeta156^15 - 2*zeta156^14 - zeta156^10 + zeta156^8 + zeta156^7 + zeta156^6 + zeta156^5 - zeta156^4 - zeta156^2 - 1 sage: factor(norm(e.gauss_sum())) 13^24
>>> from sage.all import * >>> G = DirichletGroup(Integer(13)) >>> e = G.gen(0) >>> e.gauss_sum() -zeta156^46 + zeta156^45 + zeta156^42 + zeta156^41 + 2*zeta156^40 + zeta156^37 - zeta156^36 - zeta156^34 - zeta156^33 - zeta156^31 + 2*zeta156^30 + zeta156^28 - zeta156^24 - zeta156^22 + zeta156^21 + zeta156^20 - zeta156^19 + zeta156^18 - zeta156^16 - zeta156^15 - 2*zeta156^14 - zeta156^10 + zeta156^8 + zeta156^7 + zeta156^6 + zeta156^5 - zeta156^4 - zeta156^2 - 1 >>> factor(norm(e.gauss_sum())) 13^24
See also
sage.arith.misc.gauss_sum()
for general finite fieldssage.rings.padics.misc.gauss_sum()
for a \(p\)-adic version
- gauss_sum_numerical(prec=53, a=1)[source]#
Return a Gauss sum associated to this Dirichlet character as an approximate complex number with
prec
bits of precision.INPUT:
prec
– integer (default: 53), bits of precisiona
– integer, as forgauss_sum()
.
The Gauss sum associated to \(\chi\) is
\[g_a(\chi) = \sum_{r \in \ZZ/m\ZZ} \chi(r)\,\zeta^{ar},\]where \(m\) is the modulus of \(\chi\) and \(\zeta\) is a primitive \(m^{th}\) root of unity.
EXAMPLES:
sage: G = DirichletGroup(3) sage: e = G.0 sage: abs(e.gauss_sum_numerical()) 1.7320508075... sage: sqrt(3.0) 1.73205080756888 sage: e.gauss_sum_numerical(a=2) -...e-15 - 1.7320508075...*I sage: e.gauss_sum_numerical(a=2, prec=100) 4.7331654313260708324703713917e-30 - 1.7320508075688772935274463415*I sage: G = DirichletGroup(13) sage: H = DirichletGroup(13, CC) sage: e = G.0 sage: f = H.0 sage: e.gauss_sum_numerical() -3.07497205... + 1.8826966926...*I sage: f.gauss_sum_numerical() -3.07497205... + 1.8826966926...*I sage: abs(e.gauss_sum_numerical()) 3.60555127546... sage: abs(f.gauss_sum_numerical()) 3.60555127546... sage: sqrt(13.0) 3.60555127546399
>>> from sage.all import * >>> G = DirichletGroup(Integer(3)) >>> e = G.gen(0) >>> abs(e.gauss_sum_numerical()) 1.7320508075... >>> sqrt(RealNumber('3.0')) 1.73205080756888 >>> e.gauss_sum_numerical(a=Integer(2)) -...e-15 - 1.7320508075...*I >>> e.gauss_sum_numerical(a=Integer(2), prec=Integer(100)) 4.7331654313260708324703713917e-30 - 1.7320508075688772935274463415*I >>> G = DirichletGroup(Integer(13)) >>> H = DirichletGroup(Integer(13), CC) >>> e = G.gen(0) >>> f = H.gen(0) >>> e.gauss_sum_numerical() -3.07497205... + 1.8826966926...*I >>> f.gauss_sum_numerical() -3.07497205... + 1.8826966926...*I >>> abs(e.gauss_sum_numerical()) 3.60555127546... >>> abs(f.gauss_sum_numerical()) 3.60555127546... >>> sqrt(RealNumber('13.0')) 3.60555127546399
- is_even()[source]#
Return
True
if and only if \(\varepsilon(-1) = 1\).EXAMPLES:
sage: G = DirichletGroup(13) sage: e = G.0 sage: e.is_even() False sage: e(-1) -1 sage: [e.is_even() for e in G] [True, False, True, False, True, False, True, False, True, False, True, False] sage: G = DirichletGroup(13, CC) sage: e = G.0 sage: e.is_even() False sage: e(-1) -1.000000... sage: [e.is_even() for e in G] [True, False, True, False, True, False, True, False, True, False, True, False] sage: G = DirichletGroup(100000, CC) sage: G.1.is_even() True
>>> from sage.all import * >>> G = DirichletGroup(Integer(13)) >>> e = G.gen(0) >>> e.is_even() False >>> e(-Integer(1)) -1 >>> [e.is_even() for e in G] [True, False, True, False, True, False, True, False, True, False, True, False] >>> G = DirichletGroup(Integer(13), CC) >>> e = G.gen(0) >>> e.is_even() False >>> e(-Integer(1)) -1.000000... >>> [e.is_even() for e in G] [True, False, True, False, True, False, True, False, True, False, True, False] >>> G = DirichletGroup(Integer(100000), CC) >>> G.gen(1).is_even() True
Note that
is_even
need not be the negation of is_odd, e.g., in characteristic 2:sage: G.<e> = DirichletGroup(13, GF(4,'a')) sage: e.is_even() True sage: e.is_odd() True
>>> from sage.all import * >>> G = DirichletGroup(Integer(13), GF(Integer(4),'a'), names=('e',)); (e,) = G._first_ngens(1) >>> e.is_even() True >>> e.is_odd() True
- is_odd()[source]#
Return
True
if and only if \(\varepsilon(-1) = -1\).EXAMPLES:
sage: G = DirichletGroup(13) sage: e = G.0 sage: e.is_odd() True sage: [e.is_odd() for e in G] [False, True, False, True, False, True, False, True, False, True, False, True] sage: G = DirichletGroup(13) sage: e = G.0 sage: e.is_odd() True sage: [e.is_odd() for e in G] [False, True, False, True, False, True, False, True, False, True, False, True] sage: G = DirichletGroup(100000, CC) sage: G.0.is_odd() True
>>> from sage.all import * >>> G = DirichletGroup(Integer(13)) >>> e = G.gen(0) >>> e.is_odd() True >>> [e.is_odd() for e in G] [False, True, False, True, False, True, False, True, False, True, False, True] >>> G = DirichletGroup(Integer(13)) >>> e = G.gen(0) >>> e.is_odd() True >>> [e.is_odd() for e in G] [False, True, False, True, False, True, False, True, False, True, False, True] >>> G = DirichletGroup(Integer(100000), CC) >>> G.gen(0).is_odd() True
Note that
is_even
need not be the negation of is_odd, e.g., in characteristic 2:sage: G.<e> = DirichletGroup(13, GF(4,'a')) sage: e.is_even() True sage: e.is_odd() True
>>> from sage.all import * >>> G = DirichletGroup(Integer(13), GF(Integer(4),'a'), names=('e',)); (e,) = G._first_ngens(1) >>> e.is_even() True >>> e.is_odd() True
- is_primitive()[source]#
Return
True
if and only if this character is primitive, i.e., its conductor equals its modulus.EXAMPLES:
sage: G.<a,b> = DirichletGroup(20) sage: a.is_primitive() False sage: b.is_primitive() False sage: (a*b).is_primitive() True sage: G.<a,b> = DirichletGroup(20, CC) sage: a.is_primitive() False sage: b.is_primitive() False sage: (a*b).is_primitive() True
>>> from sage.all import * >>> G = DirichletGroup(Integer(20), names=('a', 'b',)); (a, b,) = G._first_ngens(2) >>> a.is_primitive() False >>> b.is_primitive() False >>> (a*b).is_primitive() True >>> G = DirichletGroup(Integer(20), CC, names=('a', 'b',)); (a, b,) = G._first_ngens(2) >>> a.is_primitive() False >>> b.is_primitive() False >>> (a*b).is_primitive() True
- is_trivial()[source]#
Return
True
if this is the trivial character, i.e., has order 1.EXAMPLES:
sage: G.<a,b> = DirichletGroup(20) sage: a.is_trivial() False sage: (a^2).is_trivial() True
>>> from sage.all import * >>> G = DirichletGroup(Integer(20), names=('a', 'b',)); (a, b,) = G._first_ngens(2) >>> a.is_trivial() False >>> (a**Integer(2)).is_trivial() True
- jacobi_sum(char, check=True)[source]#
Return the Jacobi sum associated to these Dirichlet characters (i.e., J(self,char)).
This is defined as
\[J(\chi, \psi) = \sum_{a \in \ZZ / N\ZZ} \chi(a) \psi(1-a)\]where \(\chi\) and \(\psi\) are both characters modulo \(N\).
EXAMPLES:
sage: D = DirichletGroup(13) sage: e = D.0 sage: f = D[-2] sage: e.jacobi_sum(f) 3*zeta12^2 + 2*zeta12 - 3 sage: f.jacobi_sum(e) 3*zeta12^2 + 2*zeta12 - 3 sage: p = 7 sage: DP = DirichletGroup(p) sage: f = DP.0 sage: e.jacobi_sum(f) Traceback (most recent call last): ... NotImplementedError: Characters must be from the same Dirichlet Group. sage: all_jacobi_sums = [(DP[i].values_on_gens(), ....: DP[j].values_on_gens(), ....: DP[i].jacobi_sum(DP[j])) ....: for i in range(p - 1) for j in range(i, p - 1)] sage: for s in all_jacobi_sums: ....: print(s) ((1,), (1,), 5) ((1,), (zeta6,), -1) ((1,), (zeta6 - 1,), -1) ((1,), (-1,), -1) ((1,), (-zeta6,), -1) ((1,), (-zeta6 + 1,), -1) ((zeta6,), (zeta6,), -zeta6 + 3) ((zeta6,), (zeta6 - 1,), 2*zeta6 + 1) ((zeta6,), (-1,), -2*zeta6 - 1) ((zeta6,), (-zeta6,), zeta6 - 3) ((zeta6,), (-zeta6 + 1,), 1) ((zeta6 - 1,), (zeta6 - 1,), -3*zeta6 + 2) ((zeta6 - 1,), (-1,), 2*zeta6 + 1) ((zeta6 - 1,), (-zeta6,), -1) ((zeta6 - 1,), (-zeta6 + 1,), -zeta6 - 2) ((-1,), (-1,), 1) ((-1,), (-zeta6,), -2*zeta6 + 3) ((-1,), (-zeta6 + 1,), 2*zeta6 - 3) ((-zeta6,), (-zeta6,), 3*zeta6 - 1) ((-zeta6,), (-zeta6 + 1,), -2*zeta6 + 3) ((-zeta6 + 1,), (-zeta6 + 1,), zeta6 + 2)
>>> from sage.all import * >>> D = DirichletGroup(Integer(13)) >>> e = D.gen(0) >>> f = D[-Integer(2)] >>> e.jacobi_sum(f) 3*zeta12^2 + 2*zeta12 - 3 >>> f.jacobi_sum(e) 3*zeta12^2 + 2*zeta12 - 3 >>> p = Integer(7) >>> DP = DirichletGroup(p) >>> f = DP.gen(0) >>> e.jacobi_sum(f) Traceback (most recent call last): ... NotImplementedError: Characters must be from the same Dirichlet Group. >>> all_jacobi_sums = [(DP[i].values_on_gens(), ... DP[j].values_on_gens(), ... DP[i].jacobi_sum(DP[j])) ... for i in range(p - Integer(1)) for j in range(i, p - Integer(1))] >>> for s in all_jacobi_sums: ... print(s) ((1,), (1,), 5) ((1,), (zeta6,), -1) ((1,), (zeta6 - 1,), -1) ((1,), (-1,), -1) ((1,), (-zeta6,), -1) ((1,), (-zeta6 + 1,), -1) ((zeta6,), (zeta6,), -zeta6 + 3) ((zeta6,), (zeta6 - 1,), 2*zeta6 + 1) ((zeta6,), (-1,), -2*zeta6 - 1) ((zeta6,), (-zeta6,), zeta6 - 3) ((zeta6,), (-zeta6 + 1,), 1) ((zeta6 - 1,), (zeta6 - 1,), -3*zeta6 + 2) ((zeta6 - 1,), (-1,), 2*zeta6 + 1) ((zeta6 - 1,), (-zeta6,), -1) ((zeta6 - 1,), (-zeta6 + 1,), -zeta6 - 2) ((-1,), (-1,), 1) ((-1,), (-zeta6,), -2*zeta6 + 3) ((-1,), (-zeta6 + 1,), 2*zeta6 - 3) ((-zeta6,), (-zeta6,), 3*zeta6 - 1) ((-zeta6,), (-zeta6 + 1,), -2*zeta6 + 3) ((-zeta6 + 1,), (-zeta6 + 1,), zeta6 + 2)
Let’s check that trivial sums are being calculated correctly:
sage: N = 13 sage: D = DirichletGroup(N) sage: g = D(1) sage: g.jacobi_sum(g) 11 sage: sum([g(x)*g(1-x) for x in IntegerModRing(N)]) 11
>>> from sage.all import * >>> N = Integer(13) >>> D = DirichletGroup(N) >>> g = D(Integer(1)) >>> g.jacobi_sum(g) 11 >>> sum([g(x)*g(Integer(1)-x) for x in IntegerModRing(N)]) 11
And sums where exactly one character is nontrivial (see Issue #6393):
sage: G = DirichletGroup(5); X = G.list(); Y=X[0]; Z=X[1] sage: Y.jacobi_sum(Z) -1 sage: Z.jacobi_sum(Y) -1
>>> from sage.all import * >>> G = DirichletGroup(Integer(5)); X = G.list(); Y=X[Integer(0)]; Z=X[Integer(1)] >>> Y.jacobi_sum(Z) -1 >>> Z.jacobi_sum(Y) -1
Now let’s take a look at a non-prime modulus:
sage: N = 9 sage: D = DirichletGroup(N) sage: g = D(1) sage: g.jacobi_sum(g) 3
>>> from sage.all import * >>> N = Integer(9) >>> D = DirichletGroup(N) >>> g = D(Integer(1)) >>> g.jacobi_sum(g) 3
We consider a sum with values in a finite field:
sage: g = DirichletGroup(17, GF(9,'a')).0 sage: g.jacobi_sum(g**2) 2*a
>>> from sage.all import * >>> g = DirichletGroup(Integer(17), GF(Integer(9),'a')).gen(0) >>> g.jacobi_sum(g**Integer(2)) 2*a
- kernel()[source]#
Return the kernel of this character.
OUTPUT: Currently the kernel is returned as a list. This may change.
EXAMPLES:
sage: G.<a,b> = DirichletGroup(20) sage: a.kernel() [1, 9, 13, 17] sage: b.kernel() [1, 11]
>>> from sage.all import * >>> G = DirichletGroup(Integer(20), names=('a', 'b',)); (a, b,) = G._first_ngens(2) >>> a.kernel() [1, 9, 13, 17] >>> b.kernel() [1, 11]
- kloosterman_sum(a=1, b=0)[source]#
Return the “twisted” Kloosterman sum associated to this Dirichlet character.
This includes Gauss sums, classical Kloosterman sums, Salié sums, etc.
The Kloosterman sum associated to \(\chi\) and the integers a,b is
\[K(a,b,\chi) = \sum_{r \in (\ZZ/m\ZZ)^\times} \chi(r)\,\zeta^{ar+br^{-1}},\]where \(m\) is the modulus of \(\chi\) and \(\zeta\) is a primitive \(m\) th root of unity. This reduces to the Gauss sum if \(b=0\).
This method performs an exact calculation and returns an element of a suitable cyclotomic field; see also
kloosterman_sum_numerical()
, which gives an inexact answer (but is generally much quicker).CACHING: Computed Kloosterman sums are not cached with this character.
EXAMPLES:
sage: G = DirichletGroup(3) sage: e = G([-1]) sage: e.kloosterman_sum(3,5) -2*zeta6 + 1 sage: G = DirichletGroup(20) sage: e = G([1 for u in G.unit_gens()]) sage: e.kloosterman_sum(7,17) -2*zeta20^6 + 2*zeta20^4 + 4
>>> from sage.all import * >>> G = DirichletGroup(Integer(3)) >>> e = G([-Integer(1)]) >>> e.kloosterman_sum(Integer(3),Integer(5)) -2*zeta6 + 1 >>> G = DirichletGroup(Integer(20)) >>> e = G([Integer(1) for u in G.unit_gens()]) >>> e.kloosterman_sum(Integer(7),Integer(17)) -2*zeta20^6 + 2*zeta20^4 + 4
- kloosterman_sum_numerical(prec=53, a=1, b=0)[source]#
Return the Kloosterman sum associated to this Dirichlet character as an approximate complex number with
prec
bits of precision.See also
kloosterman_sum()
, which calculates the sum exactly (which is generally slower).INPUT:
prec
– integer (default: 53), bits of precisiona
– integer, as forkloosterman_sum()
b
– integer, as forkloosterman_sum()
.
EXAMPLES:
sage: G = DirichletGroup(3) sage: e = G.0
>>> from sage.all import * >>> G = DirichletGroup(Integer(3)) >>> e = G.gen(0)
The real component of the numerical value of e is near zero:
sage: v = e.kloosterman_sum_numerical() sage: v.real() < 1.0e15 True sage: v.imag() 1.73205080756888 sage: G = DirichletGroup(20) sage: e = G.1 sage: e.kloosterman_sum_numerical(53,3,11) 3.80422606518061 - 3.80422606518061*I
>>> from sage.all import * >>> v = e.kloosterman_sum_numerical() >>> v.real() < RealNumber('1.0e15') True >>> v.imag() 1.73205080756888 >>> G = DirichletGroup(Integer(20)) >>> e = G.gen(1) >>> e.kloosterman_sum_numerical(Integer(53),Integer(3),Integer(11)) 3.80422606518061 - 3.80422606518061*I
- level()[source]#
Synonym for modulus.
EXAMPLES:
sage: e = DirichletGroup(100, QQ).0 sage: e.level() 100
>>> from sage.all import * >>> e = DirichletGroup(Integer(100), QQ).gen(0) >>> e.level() 100
- lfunction(prec=53, algorithm='pari')[source]#
Return the L-function of
self
.The result is a wrapper around a PARI L-function or around the
lcalc
program.INPUT:
prec
– precision (default 53)algorithm
– ‘pari’ (default) or ‘lcalc’
EXAMPLES:
sage: G.<a,b> = DirichletGroup(20) sage: L = a.lfunction(); L PARI L-function associated to Dirichlet character modulo 20 of conductor 4 mapping 11 |--> -1, 17 |--> 1 sage: L(4) 0.988944551741105
>>> from sage.all import * >>> G = DirichletGroup(Integer(20), names=('a', 'b',)); (a, b,) = G._first_ngens(2) >>> L = a.lfunction(); L PARI L-function associated to Dirichlet character modulo 20 of conductor 4 mapping 11 |--> -1, 17 |--> 1 >>> L(Integer(4)) 0.988944551741105
With the algorithm “lcalc”:
sage: a = a.primitive_character() sage: L = a.lfunction(algorithm='lcalc'); L L-function with complex Dirichlet coefficients sage: L.value(4) # abs tol 1e-8 0.988944551741105 + 0.0*I
>>> from sage.all import * >>> a = a.primitive_character() >>> L = a.lfunction(algorithm='lcalc'); L L-function with complex Dirichlet coefficients >>> L.value(Integer(4)) # abs tol 1e-8 0.988944551741105 + 0.0*I
- lmfdb_page()[source]#
Open the LMFDB web page of the character in a browser.
EXAMPLES:
sage: # needs sage.rings.number_field sage: E = DirichletGroup(4).gen() sage: E.lmfdb_page() # optional -- webbrowser
>>> from sage.all import * >>> # needs sage.rings.number_field >>> E = DirichletGroup(Integer(4)).gen() >>> E.lmfdb_page() # optional -- webbrowser
- maximize_base_ring()[source]#
Let
\[\varepsilon : (\ZZ/N\ZZ)^* \to \QQ(\zeta_n)\]be a Dirichlet character. This function returns an equal Dirichlet character
\[\chi : (\ZZ/N\ZZ)^* \to \QQ(\zeta_m)\]where \(m\) is the least common multiple of \(n\) and the exponent of \((\ZZ/N\ZZ)^*\).
EXAMPLES:
sage: G.<a,b> = DirichletGroup(20,QQ) sage: b.maximize_base_ring() Dirichlet character modulo 20 of conductor 5 mapping 11 |--> 1, 17 |--> -1 sage: b.maximize_base_ring().base_ring() Cyclotomic Field of order 4 and degree 2 sage: DirichletGroup(20).base_ring() Cyclotomic Field of order 4 and degree 2
>>> from sage.all import * >>> G = DirichletGroup(Integer(20),QQ, names=('a', 'b',)); (a, b,) = G._first_ngens(2) >>> b.maximize_base_ring() Dirichlet character modulo 20 of conductor 5 mapping 11 |--> 1, 17 |--> -1 >>> b.maximize_base_ring().base_ring() Cyclotomic Field of order 4 and degree 2 >>> DirichletGroup(Integer(20)).base_ring() Cyclotomic Field of order 4 and degree 2
- minimize_base_ring()[source]#
Return a Dirichlet character that equals this one, but over as small a subfield (or subring) of the base ring as possible.
Note
This function is currently only implemented when the base ring is a number field. It is the identity function in characteristic p.
EXAMPLES:
sage: G = DirichletGroup(13) sage: e = DirichletGroup(13).0 sage: e.base_ring() Cyclotomic Field of order 12 and degree 4 sage: e.minimize_base_ring().base_ring() Cyclotomic Field of order 12 and degree 4 sage: (e^2).minimize_base_ring().base_ring() Cyclotomic Field of order 6 and degree 2 sage: (e^3).minimize_base_ring().base_ring() Cyclotomic Field of order 4 and degree 2 sage: (e^12).minimize_base_ring().base_ring() Rational Field
>>> from sage.all import * >>> G = DirichletGroup(Integer(13)) >>> e = DirichletGroup(Integer(13)).gen(0) >>> e.base_ring() Cyclotomic Field of order 12 and degree 4 >>> e.minimize_base_ring().base_ring() Cyclotomic Field of order 12 and degree 4 >>> (e**Integer(2)).minimize_base_ring().base_ring() Cyclotomic Field of order 6 and degree 2 >>> (e**Integer(3)).minimize_base_ring().base_ring() Cyclotomic Field of order 4 and degree 2 >>> (e**Integer(12)).minimize_base_ring().base_ring() Rational Field
- modulus()[source]#
Return the modulus of this character.
EXAMPLES:
sage: e = DirichletGroup(100, QQ).0 sage: e.modulus() 100 sage: e.conductor() 4
>>> from sage.all import * >>> e = DirichletGroup(Integer(100), QQ).gen(0) >>> e.modulus() 100 >>> e.conductor() 4
- multiplicative_order()[source]#
Return the order of this character.
EXAMPLES:
sage: e = DirichletGroup(100).1 sage: e.order() # same as multiplicative_order, since group is multiplicative 20 sage: e.multiplicative_order() 20 sage: e = DirichletGroup(100).0 sage: e.multiplicative_order() 2
>>> from sage.all import * >>> e = DirichletGroup(Integer(100)).gen(1) >>> e.order() # same as multiplicative_order, since group is multiplicative 20 >>> e.multiplicative_order() 20 >>> e = DirichletGroup(Integer(100)).gen(0) >>> e.multiplicative_order() 2
- primitive_character()[source]#
Return the primitive character associated to
self
.EXAMPLES:
sage: e = DirichletGroup(100).0; e Dirichlet character modulo 100 of conductor 4 mapping 51 |--> -1, 77 |--> 1 sage: e.conductor() 4 sage: f = e.primitive_character(); f Dirichlet character modulo 4 of conductor 4 mapping 3 |--> -1 sage: f.modulus() 4
>>> from sage.all import * >>> e = DirichletGroup(Integer(100)).gen(0); e Dirichlet character modulo 100 of conductor 4 mapping 51 |--> -1, 77 |--> 1 >>> e.conductor() 4 >>> f = e.primitive_character(); f Dirichlet character modulo 4 of conductor 4 mapping 3 |--> -1 >>> f.modulus() 4
- restrict(M)[source]#
Return the restriction of this character to a Dirichlet character modulo the divisor
M
of the modulus, which must also be a multiple of the conductor of this character.EXAMPLES:
sage: e = DirichletGroup(100).0 sage: e.modulus() 100 sage: e.conductor() 4 sage: e.restrict(20) Dirichlet character modulo 20 of conductor 4 mapping 11 |--> -1, 17 |--> 1 sage: e.restrict(4) Dirichlet character modulo 4 of conductor 4 mapping 3 |--> -1 sage: e.restrict(50) Traceback (most recent call last): ... ValueError: conductor(=4) must divide M(=50)
>>> from sage.all import * >>> e = DirichletGroup(Integer(100)).gen(0) >>> e.modulus() 100 >>> e.conductor() 4 >>> e.restrict(Integer(20)) Dirichlet character modulo 20 of conductor 4 mapping 11 |--> -1, 17 |--> 1 >>> e.restrict(Integer(4)) Dirichlet character modulo 4 of conductor 4 mapping 3 |--> -1 >>> e.restrict(Integer(50)) Traceback (most recent call last): ... ValueError: conductor(=4) must divide M(=50)
- values()[source]#
Return a list of the values of this character on each integer between 0 and the modulus.
EXAMPLES:
sage: e = DirichletGroup(20)(1) sage: e.values() [0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1] sage: e = DirichletGroup(20).gen(0) sage: e.values() [0, 1, 0, -1, 0, 0, 0, -1, 0, 1, 0, -1, 0, 1, 0, 0, 0, 1, 0, -1] sage: e = DirichletGroup(20).gen(1) sage: e.values() [0, 1, 0, -zeta4, 0, 0, 0, zeta4, 0, -1, 0, 1, 0, -zeta4, 0, 0, 0, zeta4, 0, -1] sage: e = DirichletGroup(21).gen(0) ; e.values() [0, 1, -1, 0, 1, -1, 0, 0, -1, 0, 1, -1, 0, 1, 0, 0, 1, -1, 0, 1, -1] sage: e = DirichletGroup(21, base_ring=GF(37)).gen(0) ; e.values() [0, 1, 36, 0, 1, 36, 0, 0, 36, 0, 1, 36, 0, 1, 0, 0, 1, 36, 0, 1, 36] sage: e = DirichletGroup(21, base_ring=GF(3)).gen(0) ; e.values() [0, 1, 2, 0, 1, 2, 0, 0, 2, 0, 1, 2, 0, 1, 0, 0, 1, 2, 0, 1, 2]
>>> from sage.all import * >>> e = DirichletGroup(Integer(20))(Integer(1)) >>> e.values() [0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1] >>> e = DirichletGroup(Integer(20)).gen(Integer(0)) >>> e.values() [0, 1, 0, -1, 0, 0, 0, -1, 0, 1, 0, -1, 0, 1, 0, 0, 0, 1, 0, -1] >>> e = DirichletGroup(Integer(20)).gen(Integer(1)) >>> e.values() [0, 1, 0, -zeta4, 0, 0, 0, zeta4, 0, -1, 0, 1, 0, -zeta4, 0, 0, 0, zeta4, 0, -1] >>> e = DirichletGroup(Integer(21)).gen(Integer(0)) ; e.values() [0, 1, -1, 0, 1, -1, 0, 0, -1, 0, 1, -1, 0, 1, 0, 0, 1, -1, 0, 1, -1] >>> e = DirichletGroup(Integer(21), base_ring=GF(Integer(37))).gen(Integer(0)) ; e.values() [0, 1, 36, 0, 1, 36, 0, 0, 36, 0, 1, 36, 0, 1, 0, 0, 1, 36, 0, 1, 36] >>> e = DirichletGroup(Integer(21), base_ring=GF(Integer(3))).gen(Integer(0)) ; e.values() [0, 1, 2, 0, 1, 2, 0, 0, 2, 0, 1, 2, 0, 1, 0, 0, 1, 2, 0, 1, 2]
sage: chi = DirichletGroup(100151, CyclotomicField(10)).0 sage: ls = chi.values() ; ls[0:10] [0, 1, -zeta10^3, -zeta10, -zeta10, 1, zeta10^3 - zeta10^2 + zeta10 - 1, zeta10, zeta10^3 - zeta10^2 + zeta10 - 1, zeta10^2]
>>> from sage.all import * >>> chi = DirichletGroup(Integer(100151), CyclotomicField(Integer(10))).gen(0) >>> ls = chi.values() ; ls[Integer(0):Integer(10)] [0, 1, -zeta10^3, -zeta10, -zeta10, 1, zeta10^3 - zeta10^2 + zeta10 - 1, zeta10, zeta10^3 - zeta10^2 + zeta10 - 1, zeta10^2]
- values_on_gens()[source]#
Return a tuple of the values of
self
on the standard generators of \((\ZZ/N\ZZ)^*\), where \(N\) is the modulus.EXAMPLES:
sage: # needs sage.rings.number_field sage: e = DirichletGroup(16)([-1, 1]) sage: e.values_on_gens () (-1, 1)
>>> from sage.all import * >>> # needs sage.rings.number_field >>> e = DirichletGroup(Integer(16))([-Integer(1), Integer(1)]) >>> e.values_on_gens () (-1, 1)
Note
The constructor of
DirichletCharacter
sets the cache ofelement()
or ofvalues_on_gens()
. The cache of one of these methods needs to be set for the other method to work properly, these caches have to be stored when pickling an instance ofDirichletCharacter
.
- class sage.modular.dirichlet.DirichletGroupFactory[source]#
Bases:
UniqueFactory
Construct a group of Dirichlet characters modulo \(N\).
INPUT:
N
– positive integerbase_ring
– commutative ring; the value ring for the characters in this group (default: the cyclotomic field \(\QQ(\zeta_n)\), where \(n\) is the exponent of \((\ZZ/N\ZZ)^*\))zeta
– (optional) root of unity inbase_ring
zeta_order
– (optional) positive integer; this must be the order ofzeta
if both are specifiednames
– ignored (needed soG.<...> = DirichletGroup(...)
notation works)integral
– boolean (default:False
); whether to replace the default cyclotomic field by its rings of integers as the base ring. This is ignored ifbase_ring
is notNone
.
OUTPUT:
The group of Dirichlet characters modulo \(N\) with values in a subgroup \(V\) of the multiplicative group \(R^*\) of
base_ring
. This is the group of homomorphisms \((\ZZ/N\ZZ)^* \to V\) with pointwise multiplication. The group \(V\) is determined as follows:If both
zeta
andzeta_order
are omitted, then \(V\) is taken to be \(R^*\), or equivalently its \(n\)-torsion subgroup, where \(n\) is the exponent of \((\ZZ/N\ZZ)^*\). Many operations, such as finding a set of generators for the group, are only implemented if \(V\) is cyclic and a generator for \(V\) can be found.If
zeta
is specified, then \(V\) is taken to be the cyclic subgroup of \(R^*\) generated byzeta
. Ifzeta_order
is also given, it must be the multiplicative order ofzeta
; this is useful if the base ring is not exact or if the order ofzeta
is very large.If
zeta
is not specified butzeta_order
is, then \(V\) is taken to be the group of roots of unity of order dividingzeta_order
in \(R\). In this case, \(R\) must be a domain (so \(V\) is cyclic), and \(V\) must have orderzeta_order
. Furthermore, a generatorzeta
of \(V\) is computed, and an error is raised if suchzeta
cannot be found.
EXAMPLES:
The default base ring is a cyclotomic field of order the exponent of \((\ZZ/N\ZZ)^*\):
sage: DirichletGroup(20) Group of Dirichlet characters modulo 20 with values in Cyclotomic Field of order 4 and degree 2
>>> from sage.all import * >>> DirichletGroup(Integer(20)) Group of Dirichlet characters modulo 20 with values in Cyclotomic Field of order 4 and degree 2
We create the group of Dirichlet character mod 20 with values in the rational numbers:
sage: G = DirichletGroup(20, QQ); G Group of Dirichlet characters modulo 20 with values in Rational Field sage: G.order() 4 sage: G.base_ring() Rational Field
>>> from sage.all import * >>> G = DirichletGroup(Integer(20), QQ); G Group of Dirichlet characters modulo 20 with values in Rational Field >>> G.order() 4 >>> G.base_ring() Rational Field
The elements of G print as lists giving the values of the character on the generators of \((Z/NZ)^*\):
sage: list(G) [Dirichlet character modulo 20 of conductor 1 mapping 11 |--> 1, 17 |--> 1, Dirichlet character modulo 20 of conductor 4 mapping 11 |--> -1, 17 |--> 1, Dirichlet character modulo 20 of conductor 5 mapping 11 |--> 1, 17 |--> -1, Dirichlet character modulo 20 of conductor 20 mapping 11 |--> -1, 17 |--> -1]
>>> from sage.all import * >>> list(G) [Dirichlet character modulo 20 of conductor 1 mapping 11 |--> 1, 17 |--> 1, Dirichlet character modulo 20 of conductor 4 mapping 11 |--> -1, 17 |--> 1, Dirichlet character modulo 20 of conductor 5 mapping 11 |--> 1, 17 |--> -1, Dirichlet character modulo 20 of conductor 20 mapping 11 |--> -1, 17 |--> -1]
Next we construct the group of Dirichlet character mod 20, but with values in \(\QQ(\zeta_n)\):
sage: G = DirichletGroup(20) sage: G.1 Dirichlet character modulo 20 of conductor 5 mapping 11 |--> 1, 17 |--> zeta4
>>> from sage.all import * >>> G = DirichletGroup(Integer(20)) >>> G.gen(1) Dirichlet character modulo 20 of conductor 5 mapping 11 |--> 1, 17 |--> zeta4
We next compute several invariants of
G
:sage: G.gens() (Dirichlet character modulo 20 of conductor 4 mapping 11 |--> -1, 17 |--> 1, Dirichlet character modulo 20 of conductor 5 mapping 11 |--> 1, 17 |--> zeta4) sage: G.unit_gens() (11, 17) sage: G.zeta() zeta4 sage: G.zeta_order() 4
>>> from sage.all import * >>> G.gens() (Dirichlet character modulo 20 of conductor 4 mapping 11 |--> -1, 17 |--> 1, Dirichlet character modulo 20 of conductor 5 mapping 11 |--> 1, 17 |--> zeta4) >>> G.unit_gens() (11, 17) >>> G.zeta() zeta4 >>> G.zeta_order() 4
In this example we create a Dirichlet group with values in a number field:
sage: R.<x> = PolynomialRing(QQ) sage: K.<a> = NumberField(x^4 + 1) sage: DirichletGroup(5, K) Group of Dirichlet characters modulo 5 with values in Number Field in a with defining polynomial x^4 + 1
>>> from sage.all import * >>> R = PolynomialRing(QQ, names=('x',)); (x,) = R._first_ngens(1) >>> K = NumberField(x**Integer(4) + Integer(1), names=('a',)); (a,) = K._first_ngens(1) >>> DirichletGroup(Integer(5), K) Group of Dirichlet characters modulo 5 with values in Number Field in a with defining polynomial x^4 + 1
An example where we give
zeta
, but not its order:sage: G = DirichletGroup(5, K, a); G Group of Dirichlet characters modulo 5 with values in the group of order 8 generated by a in Number Field in a with defining polynomial x^4 + 1 sage: G.list() [Dirichlet character modulo 5 of conductor 1 mapping 2 |--> 1, Dirichlet character modulo 5 of conductor 5 mapping 2 |--> a^2, Dirichlet character modulo 5 of conductor 5 mapping 2 |--> -1, Dirichlet character modulo 5 of conductor 5 mapping 2 |--> -a^2]
>>> from sage.all import * >>> G = DirichletGroup(Integer(5), K, a); G Group of Dirichlet characters modulo 5 with values in the group of order 8 generated by a in Number Field in a with defining polynomial x^4 + 1 >>> G.list() [Dirichlet character modulo 5 of conductor 1 mapping 2 |--> 1, Dirichlet character modulo 5 of conductor 5 mapping 2 |--> a^2, Dirichlet character modulo 5 of conductor 5 mapping 2 |--> -1, Dirichlet character modulo 5 of conductor 5 mapping 2 |--> -a^2]
We can also restrict the order of the characters, either with or without specifying a root of unity:
sage: DirichletGroup(5, K, zeta=-1, zeta_order=2) Group of Dirichlet characters modulo 5 with values in the group of order 2 generated by -1 in Number Field in a with defining polynomial x^4 + 1 sage: DirichletGroup(5, K, zeta_order=2) Group of Dirichlet characters modulo 5 with values in the group of order 2 generated by -1 in Number Field in a with defining polynomial x^4 + 1
>>> from sage.all import * >>> DirichletGroup(Integer(5), K, zeta=-Integer(1), zeta_order=Integer(2)) Group of Dirichlet characters modulo 5 with values in the group of order 2 generated by -1 in Number Field in a with defining polynomial x^4 + 1 >>> DirichletGroup(Integer(5), K, zeta_order=Integer(2)) Group of Dirichlet characters modulo 5 with values in the group of order 2 generated by -1 in Number Field in a with defining polynomial x^4 + 1
sage: G.<e> = DirichletGroup(13) sage: loads(G.dumps()) == G True
>>> from sage.all import * >>> G = DirichletGroup(Integer(13), names=('e',)); (e,) = G._first_ngens(1) >>> loads(G.dumps()) == G True
sage: G = DirichletGroup(19, GF(5)) sage: loads(G.dumps()) == G True
>>> from sage.all import * >>> G = DirichletGroup(Integer(19), GF(Integer(5))) >>> loads(G.dumps()) == G True
We compute a Dirichlet group over a large prime field:
sage: p = next_prime(10^40) sage: g = DirichletGroup(19, GF(p)); g Group of Dirichlet characters modulo 19 with values in Finite Field of size 10000000000000000000000000000000000000121
>>> from sage.all import * >>> p = next_prime(Integer(10)**Integer(40)) >>> g = DirichletGroup(Integer(19), GF(p)); g Group of Dirichlet characters modulo 19 with values in Finite Field of size 10000000000000000000000000000000000000121
Note that the root of unity has small order, i.e., it is not the largest order root of unity in the field:
sage: g.zeta_order() 2
>>> from sage.all import * >>> g.zeta_order() 2
sage: r4 = CyclotomicField(4).ring_of_integers() sage: G = DirichletGroup(60, r4) sage: G.gens() (Dirichlet character modulo 60 of conductor 4 mapping 31 |--> -1, 41 |--> 1, 37 |--> 1, Dirichlet character modulo 60 of conductor 3 mapping 31 |--> 1, 41 |--> -1, 37 |--> 1, Dirichlet character modulo 60 of conductor 5 mapping 31 |--> 1, 41 |--> 1, 37 |--> zeta4) sage: val = G.gens()[2].values_on_gens()[2] ; val zeta4 sage: parent(val) Gaussian Integers generated by zeta4 in Cyclotomic Field of order 4 and degree 2 sage: r4_29_0 = r4.residue_field(r4.ideal(29).factor()[0][0]); r4_29_0(val) doctest:warning ... DeprecationWarning: ... 17 sage: r4_29_0(val) * GF(29)(3) 22 sage: r4_29_0(G.gens()[2].values_on_gens()[2]) * 3 22 sage: parent(r4_29_0(G.gens()[2].values_on_gens()[2]) * 3) Residue field of Fractional ideal (-2*zeta4 + 5)
>>> from sage.all import * >>> r4 = CyclotomicField(Integer(4)).ring_of_integers() >>> G = DirichletGroup(Integer(60), r4) >>> G.gens() (Dirichlet character modulo 60 of conductor 4 mapping 31 |--> -1, 41 |--> 1, 37 |--> 1, Dirichlet character modulo 60 of conductor 3 mapping 31 |--> 1, 41 |--> -1, 37 |--> 1, Dirichlet character modulo 60 of conductor 5 mapping 31 |--> 1, 41 |--> 1, 37 |--> zeta4) >>> val = G.gens()[Integer(2)].values_on_gens()[Integer(2)] ; val zeta4 >>> parent(val) Gaussian Integers generated by zeta4 in Cyclotomic Field of order 4 and degree 2 >>> r4_29_0 = r4.residue_field(r4.ideal(Integer(29)).factor()[Integer(0)][Integer(0)]); r4_29_0(val) doctest:warning ... DeprecationWarning: ... 17 >>> r4_29_0(val) * GF(Integer(29))(Integer(3)) 22 >>> r4_29_0(G.gens()[Integer(2)].values_on_gens()[Integer(2)]) * Integer(3) 22 >>> parent(r4_29_0(G.gens()[Integer(2)].values_on_gens()[Integer(2)]) * Integer(3)) Residue field of Fractional ideal (-2*zeta4 + 5)
sage: DirichletGroup(60, integral=True) Group of Dirichlet characters modulo 60 with values in Gaussian Integers generated by zeta4 in Cyclotomic Field of order 4 and degree 2 sage: parent(DirichletGroup(60, integral=True).gens()[2].values_on_gens()[2]) Gaussian Integers generated by zeta4 in Cyclotomic Field of order 4 and degree 2
>>> from sage.all import * >>> DirichletGroup(Integer(60), integral=True) Group of Dirichlet characters modulo 60 with values in Gaussian Integers generated by zeta4 in Cyclotomic Field of order 4 and degree 2 >>> parent(DirichletGroup(Integer(60), integral=True).gens()[Integer(2)].values_on_gens()[Integer(2)]) Gaussian Integers generated by zeta4 in Cyclotomic Field of order 4 and degree 2
If the order of
zeta
cannot be determined automatically, we can specify it usingzeta_order
:sage: DirichletGroup(7, CC, zeta=exp(2*pi*I/6)) # needs sage.symbolic Traceback (most recent call last): ... NotImplementedError: order of element not known sage: DirichletGroup(7, CC, zeta=exp(2*pi*I/6), zeta_order=6) # needs sage.symbolic Group of Dirichlet characters modulo 7 with values in the group of order 6 generated by 0.500000000000000 + 0.866025403784439*I in Complex Field with 53 bits of precision
>>> from sage.all import * >>> DirichletGroup(Integer(7), CC, zeta=exp(Integer(2)*pi*I/Integer(6))) # needs sage.symbolic Traceback (most recent call last): ... NotImplementedError: order of element not known >>> DirichletGroup(Integer(7), CC, zeta=exp(Integer(2)*pi*I/Integer(6)), zeta_order=Integer(6)) # needs sage.symbolic Group of Dirichlet characters modulo 7 with values in the group of order 6 generated by 0.500000000000000 + 0.866025403784439*I in Complex Field with 53 bits of precision
If the base ring is not a domain (in which case the group of roots of unity is not necessarily cyclic), some operations still work, such as creation of elements:
sage: G = DirichletGroup(5, Zmod(15)); G Group of Dirichlet characters modulo 5 with values in Ring of integers modulo 15 sage: chi = G([13]); chi Dirichlet character modulo 5 of conductor 5 mapping 2 |--> 13 sage: chi^2 Dirichlet character modulo 5 of conductor 5 mapping 2 |--> 4 sage: chi.multiplicative_order() 4
>>> from sage.all import * >>> G = DirichletGroup(Integer(5), Zmod(Integer(15))); G Group of Dirichlet characters modulo 5 with values in Ring of integers modulo 15 >>> chi = G([Integer(13)]); chi Dirichlet character modulo 5 of conductor 5 mapping 2 |--> 13 >>> chi**Integer(2) Dirichlet character modulo 5 of conductor 5 mapping 2 |--> 4 >>> chi.multiplicative_order() 4
Other operations only work if
zeta
is specified:sage: G.gens() Traceback (most recent call last): ... NotImplementedError: factorization of polynomials over rings with composite characteristic is not implemented sage: G = DirichletGroup(5, Zmod(15), zeta=2); G Group of Dirichlet characters modulo 5 with values in the group of order 4 generated by 2 in Ring of integers modulo 15 sage: G.gens() (Dirichlet character modulo 5 of conductor 5 mapping 2 |--> 2,)
>>> from sage.all import * >>> G.gens() Traceback (most recent call last): ... NotImplementedError: factorization of polynomials over rings with composite characteristic is not implemented >>> G = DirichletGroup(Integer(5), Zmod(Integer(15)), zeta=Integer(2)); G Group of Dirichlet characters modulo 5 with values in the group of order 4 generated by 2 in Ring of integers modulo 15 >>> G.gens() (Dirichlet character modulo 5 of conductor 5 mapping 2 |--> 2,)
- class sage.modular.dirichlet.DirichletGroup_class(base_ring, modulus, zeta, zeta_order)[source]#
Bases:
WithEqualityById
,Parent
Group of Dirichlet characters modulo \(N\) with values in a ring \(R\).
- Element[source]#
alias of
DirichletCharacter
- base_extend(R)[source]#
Return the base extension of
self
toR
.INPUT:
R
– either a ring admitting a coercion map from the base ring ofself
, or a ring homomorphism with the base ring ofself
as its domain
EXAMPLES:
sage: G = DirichletGroup(7,QQ); G Group of Dirichlet characters modulo 7 with values in Rational Field sage: H = G.base_extend(CyclotomicField(6)); H Group of Dirichlet characters modulo 7 with values in Cyclotomic Field of order 6 and degree 2
>>> from sage.all import * >>> G = DirichletGroup(Integer(7),QQ); G Group of Dirichlet characters modulo 7 with values in Rational Field >>> H = G.base_extend(CyclotomicField(Integer(6))); H Group of Dirichlet characters modulo 7 with values in Cyclotomic Field of order 6 and degree 2
Note that the root of unity can change:
sage: H.zeta() zeta6
>>> from sage.all import * >>> H.zeta() zeta6
This method (in contrast to
change_ring()
) requires a coercion map to exist:sage: G.base_extend(ZZ) Traceback (most recent call last): ... TypeError: no coercion map from Rational Field to Integer Ring is defined
>>> from sage.all import * >>> G.base_extend(ZZ) Traceback (most recent call last): ... TypeError: no coercion map from Rational Field to Integer Ring is defined
Base-extended Dirichlet groups do not silently get roots of unity with smaller order than expected (Issue #6018):
sage: G = DirichletGroup(10, QQ).base_extend(CyclotomicField(4)) sage: H = DirichletGroup(10, CyclotomicField(4)) sage: G is H True sage: G3 = DirichletGroup(31, CyclotomicField(3)) sage: G5 = DirichletGroup(31, CyclotomicField(5)) sage: K30 = CyclotomicField(30) sage: G3.gen(0).base_extend(K30) * G5.gen(0).base_extend(K30) Dirichlet character modulo 31 of conductor 31 mapping 3 |--> -zeta30^7 + zeta30^5 + zeta30^4 + zeta30^3 - zeta30 - 1
>>> from sage.all import * >>> G = DirichletGroup(Integer(10), QQ).base_extend(CyclotomicField(Integer(4))) >>> H = DirichletGroup(Integer(10), CyclotomicField(Integer(4))) >>> G is H True >>> G3 = DirichletGroup(Integer(31), CyclotomicField(Integer(3))) >>> G5 = DirichletGroup(Integer(31), CyclotomicField(Integer(5))) >>> K30 = CyclotomicField(Integer(30)) >>> G3.gen(Integer(0)).base_extend(K30) * G5.gen(Integer(0)).base_extend(K30) Dirichlet character modulo 31 of conductor 31 mapping 3 |--> -zeta30^7 + zeta30^5 + zeta30^4 + zeta30^3 - zeta30 - 1
When a root of unity is specified, base extension still works if the new base ring is not an integral domain:
sage: f = DirichletGroup(17, ZZ, zeta=-1).0 sage: g = f.base_extend(Integers(15)) sage: g(3) 14 sage: g.parent().zeta() 14
>>> from sage.all import * >>> f = DirichletGroup(Integer(17), ZZ, zeta=-Integer(1)).gen(0) >>> g = f.base_extend(Integers(Integer(15))) >>> g(Integer(3)) 14 >>> g.parent().zeta() 14
- change_ring(R, zeta=None, zeta_order=None)[source]#
Return the base extension of
self
toR
.INPUT:
R
– either a ring admitting a conversion map from the base ring ofself
, or a ring homomorphism with the base ring ofself
as its domainzeta
– (optional) root of unity inR
zeta_order
– (optional) order ofzeta
EXAMPLES:
sage: G = DirichletGroup(7,QQ); G Group of Dirichlet characters modulo 7 with values in Rational Field sage: G.change_ring(CyclotomicField(6)) # needs sage.rings.number_field Group of Dirichlet characters modulo 7 with values in Cyclotomic Field of order 6 and degree 2
>>> from sage.all import * >>> G = DirichletGroup(Integer(7),QQ); G Group of Dirichlet characters modulo 7 with values in Rational Field >>> G.change_ring(CyclotomicField(Integer(6))) # needs sage.rings.number_field Group of Dirichlet characters modulo 7 with values in Cyclotomic Field of order 6 and degree 2
- decomposition()[source]#
Return the Dirichlet groups of prime power modulus corresponding to primes dividing modulus.
(Note that if the modulus is 2 mod 4, there will be a “factor” of \((\ZZ/2\ZZ)^*\), which is the trivial group.)
EXAMPLES:
sage: DirichletGroup(20).decomposition() [ Group of Dirichlet characters modulo 4 with values in Cyclotomic Field of order 4 and degree 2, Group of Dirichlet characters modulo 5 with values in Cyclotomic Field of order 4 and degree 2 ] sage: DirichletGroup(20,GF(5)).decomposition() [ Group of Dirichlet characters modulo 4 with values in Finite Field of size 5, Group of Dirichlet characters modulo 5 with values in Finite Field of size 5 ]
>>> from sage.all import * >>> DirichletGroup(Integer(20)).decomposition() [ Group of Dirichlet characters modulo 4 with values in Cyclotomic Field of order 4 and degree 2, Group of Dirichlet characters modulo 5 with values in Cyclotomic Field of order 4 and degree 2 ] >>> DirichletGroup(Integer(20),GF(Integer(5))).decomposition() [ Group of Dirichlet characters modulo 4 with values in Finite Field of size 5, Group of Dirichlet characters modulo 5 with values in Finite Field of size 5 ]
- exponent()[source]#
Return the exponent of this group.
EXAMPLES:
sage: DirichletGroup(20).exponent() 4 sage: DirichletGroup(20,GF(3)).exponent() 2 sage: DirichletGroup(20,GF(2)).exponent() 1 sage: DirichletGroup(37).exponent() 36
>>> from sage.all import * >>> DirichletGroup(Integer(20)).exponent() 4 >>> DirichletGroup(Integer(20),GF(Integer(3))).exponent() 2 >>> DirichletGroup(Integer(20),GF(Integer(2))).exponent() 1 >>> DirichletGroup(Integer(37)).exponent() 36
- galois_orbits(v=None, reps_only=False, sort=True, check=True)[source]#
Return a list of the Galois orbits of Dirichlet characters in
self
, or inv
ifv
is notNone
.INPUT:
v
– (optional) list of elements ofself
reps_only
– (optional: defaultFalse
) ifTrue
only returns representatives for the orbits.sort
– (optional: defaultTrue
) whether to sort the list of orbits and the orbits themselves (slightly faster ifFalse
).check
– (default:True
) whether or not to explicitly coerce each element ofv
intoself
.
The Galois group is the absolute Galois group of the prime subfield of Frac(R). If R is not a domain, an error will be raised.
EXAMPLES:
sage: DirichletGroup(20).galois_orbits() [ [Dirichlet character modulo 20 of conductor 20 mapping 11 |--> -1, 17 |--> -1], ..., [Dirichlet character modulo 20 of conductor 1 mapping 11 |--> 1, 17 |--> 1] ] sage: DirichletGroup(17, Integers(6), zeta=Integers(6)(5)).galois_orbits() Traceback (most recent call last): ... TypeError: Galois orbits only defined if base ring is an integral domain sage: DirichletGroup(17, Integers(9), zeta=Integers(9)(2)).galois_orbits() Traceback (most recent call last): ... TypeError: Galois orbits only defined if base ring is an integral domain
>>> from sage.all import * >>> DirichletGroup(Integer(20)).galois_orbits() [ [Dirichlet character modulo 20 of conductor 20 mapping 11 |--> -1, 17 |--> -1], ..., [Dirichlet character modulo 20 of conductor 1 mapping 11 |--> 1, 17 |--> 1] ] >>> DirichletGroup(Integer(17), Integers(Integer(6)), zeta=Integers(Integer(6))(Integer(5))).galois_orbits() Traceback (most recent call last): ... TypeError: Galois orbits only defined if base ring is an integral domain >>> DirichletGroup(Integer(17), Integers(Integer(9)), zeta=Integers(Integer(9))(Integer(2))).galois_orbits() Traceback (most recent call last): ... TypeError: Galois orbits only defined if base ring is an integral domain
- gen(n=0)[source]#
Return the n-th generator of
self
.EXAMPLES:
sage: G = DirichletGroup(20) sage: G.gen(0) Dirichlet character modulo 20 of conductor 4 mapping 11 |--> -1, 17 |--> 1 sage: G.gen(1) Dirichlet character modulo 20 of conductor 5 mapping 11 |--> 1, 17 |--> zeta4 sage: G.gen(2) Traceback (most recent call last): ... IndexError: n(=2) must be between 0 and 1
>>> from sage.all import * >>> G = DirichletGroup(Integer(20)) >>> G.gen(Integer(0)) Dirichlet character modulo 20 of conductor 4 mapping 11 |--> -1, 17 |--> 1 >>> G.gen(Integer(1)) Dirichlet character modulo 20 of conductor 5 mapping 11 |--> 1, 17 |--> zeta4 >>> G.gen(Integer(2)) Traceback (most recent call last): ... IndexError: n(=2) must be between 0 and 1
sage: G.gen(-1) Traceback (most recent call last): ... IndexError: n(=-1) must be between 0 and 1
>>> from sage.all import * >>> G.gen(-Integer(1)) Traceback (most recent call last): ... IndexError: n(=-1) must be between 0 and 1
- gens()[source]#
Return generators of
self
.EXAMPLES:
sage: G = DirichletGroup(20) sage: G.gens() (Dirichlet character modulo 20 of conductor 4 mapping 11 |--> -1, 17 |--> 1, Dirichlet character modulo 20 of conductor 5 mapping 11 |--> 1, 17 |--> zeta4)
>>> from sage.all import * >>> G = DirichletGroup(Integer(20)) >>> G.gens() (Dirichlet character modulo 20 of conductor 4 mapping 11 |--> -1, 17 |--> 1, Dirichlet character modulo 20 of conductor 5 mapping 11 |--> 1, 17 |--> zeta4)
- integers_mod()[source]#
Return the group of integers \(\ZZ/N\ZZ\) where \(N\) is the modulus of
self
.EXAMPLES:
sage: G = DirichletGroup(20) sage: G.integers_mod() Ring of integers modulo 20
>>> from sage.all import * >>> G = DirichletGroup(Integer(20)) >>> G.integers_mod() Ring of integers modulo 20
- list()[source]#
Return a list of the Dirichlet characters in this group.
EXAMPLES:
sage: DirichletGroup(5).list() [Dirichlet character modulo 5 of conductor 1 mapping 2 |--> 1, Dirichlet character modulo 5 of conductor 5 mapping 2 |--> zeta4, Dirichlet character modulo 5 of conductor 5 mapping 2 |--> -1, Dirichlet character modulo 5 of conductor 5 mapping 2 |--> -zeta4]
>>> from sage.all import * >>> DirichletGroup(Integer(5)).list() [Dirichlet character modulo 5 of conductor 1 mapping 2 |--> 1, Dirichlet character modulo 5 of conductor 5 mapping 2 |--> zeta4, Dirichlet character modulo 5 of conductor 5 mapping 2 |--> -1, Dirichlet character modulo 5 of conductor 5 mapping 2 |--> -zeta4]
- modulus()[source]#
Return the modulus of
self
.EXAMPLES:
sage: G = DirichletGroup(20) sage: G.modulus() 20
>>> from sage.all import * >>> G = DirichletGroup(Integer(20)) >>> G.modulus() 20
- ngens()[source]#
Return the number of generators of
self
.EXAMPLES:
sage: G = DirichletGroup(20) sage: G.ngens() 2
>>> from sage.all import * >>> G = DirichletGroup(Integer(20)) >>> G.ngens() 2
- order()[source]#
Return the number of elements of
self
.This is the same as len(self).
EXAMPLES:
sage: DirichletGroup(20).order() 8 sage: DirichletGroup(37).order() 36
>>> from sage.all import * >>> DirichletGroup(Integer(20)).order() 8 >>> DirichletGroup(Integer(37)).order() 36
- random_element()[source]#
Return a random element of
self
.The element is computed by multiplying a random power of each generator together, where the power is between 0 and the order of the generator minus 1, inclusive.
EXAMPLES:
sage: D = DirichletGroup(37) sage: g = D.random_element() sage: g.parent() is D True sage: g**36 Dirichlet character modulo 37 of conductor 1 mapping 2 |--> 1 sage: S = set(D.random_element().conductor() for _ in range(100)) sage: while S != {1, 37}: ....: S.add(D.random_element().conductor()) sage: D = DirichletGroup(20) sage: g = D.random_element() sage: g.parent() is D True sage: g**4 Dirichlet character modulo 20 of conductor 1 mapping 11 |--> 1, 17 |--> 1 sage: S = set(D.random_element().conductor() for _ in range(100)) sage: while S != {1, 4, 5, 20}: ....: S.add(D.random_element().conductor()) sage: D = DirichletGroup(60) sage: g = D.random_element() sage: g.parent() is D True sage: g**4 Dirichlet character modulo 60 of conductor 1 mapping 31 |--> 1, 41 |--> 1, 37 |--> 1 sage: S = set(D.random_element().conductor() for _ in range(100)) sage: while S != {1, 3, 4, 5, 12, 15, 20, 60}: ....: S.add(D.random_element().conductor())
>>> from sage.all import * >>> D = DirichletGroup(Integer(37)) >>> g = D.random_element() >>> g.parent() is D True >>> g**Integer(36) Dirichlet character modulo 37 of conductor 1 mapping 2 |--> 1 >>> S = set(D.random_element().conductor() for _ in range(Integer(100))) >>> while S != {Integer(1), Integer(37)}: ... S.add(D.random_element().conductor()) >>> D = DirichletGroup(Integer(20)) >>> g = D.random_element() >>> g.parent() is D True >>> g**Integer(4) Dirichlet character modulo 20 of conductor 1 mapping 11 |--> 1, 17 |--> 1 >>> S = set(D.random_element().conductor() for _ in range(Integer(100))) >>> while S != {Integer(1), Integer(4), Integer(5), Integer(20)}: ... S.add(D.random_element().conductor()) >>> D = DirichletGroup(Integer(60)) >>> g = D.random_element() >>> g.parent() is D True >>> g**Integer(4) Dirichlet character modulo 60 of conductor 1 mapping 31 |--> 1, 41 |--> 1, 37 |--> 1 >>> S = set(D.random_element().conductor() for _ in range(Integer(100))) >>> while S != {Integer(1), Integer(3), Integer(4), Integer(5), Integer(12), Integer(15), Integer(20), Integer(60)}: ... S.add(D.random_element().conductor())
- unit_gens()[source]#
Return the minimal generators for the units of \((\ZZ/N\ZZ)^*\), where \(N\) is the modulus of
self
.EXAMPLES:
sage: DirichletGroup(37).unit_gens() (2,) sage: DirichletGroup(20).unit_gens() (11, 17) sage: DirichletGroup(60).unit_gens() (31, 41, 37) sage: DirichletGroup(20,QQ).unit_gens() (11, 17)
>>> from sage.all import * >>> DirichletGroup(Integer(37)).unit_gens() (2,) >>> DirichletGroup(Integer(20)).unit_gens() (11, 17) >>> DirichletGroup(Integer(60)).unit_gens() (31, 41, 37) >>> DirichletGroup(Integer(20),QQ).unit_gens() (11, 17)
- zeta()[source]#
Return the chosen root of unity in the base ring.
EXAMPLES:
sage: DirichletGroup(37).zeta() zeta36 sage: DirichletGroup(20).zeta() zeta4 sage: DirichletGroup(60).zeta() zeta4 sage: DirichletGroup(60,QQ).zeta() -1 sage: DirichletGroup(60, GF(25,'a')).zeta() 2
>>> from sage.all import * >>> DirichletGroup(Integer(37)).zeta() zeta36 >>> DirichletGroup(Integer(20)).zeta() zeta4 >>> DirichletGroup(Integer(60)).zeta() zeta4 >>> DirichletGroup(Integer(60),QQ).zeta() -1 >>> DirichletGroup(Integer(60), GF(Integer(25),'a')).zeta() 2
- zeta_order()[source]#
Return the order of the chosen root of unity in the base ring.
EXAMPLES:
sage: DirichletGroup(20).zeta_order() 4 sage: DirichletGroup(60).zeta_order() 4 sage: DirichletGroup(60, GF(25,'a')).zeta_order() 4 sage: DirichletGroup(19).zeta_order() 18
>>> from sage.all import * >>> DirichletGroup(Integer(20)).zeta_order() 4 >>> DirichletGroup(Integer(60)).zeta_order() 4 >>> DirichletGroup(Integer(60), GF(Integer(25),'a')).zeta_order() 4 >>> DirichletGroup(Integer(19)).zeta_order() 18
- sage.modular.dirichlet.TrivialCharacter(N, base_ring=Rational Field)[source]#
Return the trivial character of the given modulus, with values in the given base ring.
EXAMPLES:
sage: t = trivial_character(7) sage: [t(x) for x in [0..20]] [0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1] sage: t(1).parent() Rational Field sage: trivial_character(7, Integers(3))(1).parent() Ring of integers modulo 3
>>> from sage.all import * >>> t = trivial_character(Integer(7)) >>> [t(x) for x in (ellipsis_range(Integer(0),Ellipsis,Integer(20)))] [0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1] >>> t(Integer(1)).parent() Rational Field >>> trivial_character(Integer(7), Integers(Integer(3)))(Integer(1)).parent() Ring of integers modulo 3
- sage.modular.dirichlet.is_DirichletCharacter(x)[source]#
Return
True
ifx
is of typeDirichletCharacter
.EXAMPLES:
sage: from sage.modular.dirichlet import is_DirichletCharacter sage: is_DirichletCharacter(trivial_character(3)) doctest:warning... DeprecationWarning: The function is_DirichletCharacter is deprecated; use 'isinstance(..., DirichletCharacter)' instead. See https://github.com/sagemath/sage/issues/38184 for details. True sage: is_DirichletCharacter([1]) False
>>> from sage.all import * >>> from sage.modular.dirichlet import is_DirichletCharacter >>> is_DirichletCharacter(trivial_character(Integer(3))) doctest:warning... DeprecationWarning: The function is_DirichletCharacter is deprecated; use 'isinstance(..., DirichletCharacter)' instead. See https://github.com/sagemath/sage/issues/38184 for details. True >>> is_DirichletCharacter([Integer(1)]) False
- sage.modular.dirichlet.is_DirichletGroup(x)[source]#
Return
True
ifx
is a Dirichlet group.EXAMPLES:
sage: from sage.modular.dirichlet import is_DirichletGroup sage: is_DirichletGroup(DirichletGroup(11)) doctest:warning... DeprecationWarning: The function is_DirichletGroup is deprecated; use 'isinstance(..., DirichletGroup_class)' instead. See https://github.com/sagemath/sage/issues/38035 for details. True sage: is_DirichletGroup(11) False sage: is_DirichletGroup(DirichletGroup(11).0) False
>>> from sage.all import * >>> from sage.modular.dirichlet import is_DirichletGroup >>> is_DirichletGroup(DirichletGroup(Integer(11))) doctest:warning... DeprecationWarning: The function is_DirichletGroup is deprecated; use 'isinstance(..., DirichletGroup_class)' instead. See https://github.com/sagemath/sage/issues/38035 for details. True >>> is_DirichletGroup(Integer(11)) False >>> is_DirichletGroup(DirichletGroup(Integer(11)).gen(0)) False
- sage.modular.dirichlet.kronecker_character(d)[source]#
Return the quadratic Dirichlet character (d/.) of minimal conductor.
EXAMPLES:
sage: kronecker_character(97*389*997^2) Dirichlet character modulo 37733 of conductor 37733 mapping 1557 |--> -1, 37346 |--> -1
>>> from sage.all import * >>> kronecker_character(Integer(97)*Integer(389)*Integer(997)**Integer(2)) Dirichlet character modulo 37733 of conductor 37733 mapping 1557 |--> -1, 37346 |--> -1
sage: a = kronecker_character(1) sage: b = DirichletGroup(2401,QQ)(a) # NOTE -- over QQ! sage: b.modulus() 2401
>>> from sage.all import * >>> a = kronecker_character(Integer(1)) >>> b = DirichletGroup(Integer(2401),QQ)(a) # NOTE -- over QQ! >>> b.modulus() 2401
AUTHORS:
Jon Hanke (2006-08-06)
- sage.modular.dirichlet.kronecker_character_upside_down(d)[source]#
Return the quadratic Dirichlet character (./d) of conductor d, for d > 0.
EXAMPLES:
sage: kronecker_character_upside_down(97*389*997^2) Dirichlet character modulo 37506941597 of conductor 37733 mapping 13533432536 |--> -1, 22369178537 |--> -1, 14266017175 |--> 1
>>> from sage.all import * >>> kronecker_character_upside_down(Integer(97)*Integer(389)*Integer(997)**Integer(2)) Dirichlet character modulo 37506941597 of conductor 37733 mapping 13533432536 |--> -1, 22369178537 |--> -1, 14266017175 |--> 1
AUTHORS:
Jon Hanke (2006-08-06)
- sage.modular.dirichlet.trivial_character(N, base_ring=Rational Field)[source]#
Return the trivial character of the given modulus, with values in the given base ring.
EXAMPLES:
sage: t = trivial_character(7) sage: [t(x) for x in [0..20]] [0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1] sage: t(1).parent() Rational Field sage: trivial_character(7, Integers(3))(1).parent() Ring of integers modulo 3
>>> from sage.all import * >>> t = trivial_character(Integer(7)) >>> [t(x) for x in (ellipsis_range(Integer(0),Ellipsis,Integer(20)))] [0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1] >>> t(Integer(1)).parent() Rational Field >>> trivial_character(Integer(7), Integers(Integer(3)))(Integer(1)).parent() Ring of integers modulo 3