Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemath
GitHub Repository: sagemath/sagesmc
Path: blob/master/src/sage/modular/dirichlet.py
8817 views
1
# -*- coding: utf-8 -*-
2
r"""
3
Dirichlet characters
4
5
A ``DirichletCharacter`` is the extension of a
6
homomorphism
7
8
.. math::
9
10
(\ZZ/N\ZZ)^* \to R^*,
11
12
13
for some ring `R`, to the map
14
`\ZZ/N\ZZ \to R` obtained by sending those
15
`x\in\ZZ/N\ZZ` with `\gcd(N,x)>1` to
16
`0`.
17
18
EXAMPLES::
19
20
sage: G = DirichletGroup(35)
21
sage: x = G.gens()
22
sage: e = x[0]*x[1]^2; e
23
Dirichlet character modulo 35 of conductor 35 mapping 22 |--> zeta12^3, 31 |--> zeta12^2 - 1
24
sage: e.order()
25
12
26
27
This illustrates a canonical coercion.
28
29
::
30
31
sage: e = DirichletGroup(5, QQ).0
32
sage: f = DirichletGroup(5,CyclotomicField(4)).0
33
sage: e*f
34
Dirichlet character modulo 5 of conductor 5 mapping 2 |--> -zeta4
35
36
AUTHORS:
37
38
- William Stein (2005-09-02): Fixed bug in comparison of Dirichlet
39
characters. It was checking that their values were the same, but
40
not checking that they had the same level!
41
42
- William Stein (2006-01-07): added more examples
43
44
- William Stein (2006-05-21): added examples of everything; fix a
45
*lot* of tiny bugs and design problem that became clear when
46
creating examples.
47
48
- Craig Citro (2008-02-16): speed up __call__ method for
49
Dirichlet characters, miscellaneous fixes
50
"""
51
52
########################################################################
53
# Copyright (C) 2004,2005,2006 William Stein <[email protected]>
54
#
55
# Distributed under the terms of the GNU General Public License (GPL)
56
#
57
# The full text of the GPL is available at:
58
#
59
# http://www.gnu.org/licenses/
60
########################################################################
61
62
import weakref
63
64
import sage.categories.all as cat
65
import sage.misc.misc as misc
66
import sage.misc.prandom as random
67
import sage.modules.free_module as free_module
68
import sage.modules.free_module_element as free_module_element
69
import sage.rings.all as rings
70
import sage.rings.arith as arith
71
import sage.rings.number_field.number_field as number_field
72
import sage.structure.parent_gens as parent_gens
73
74
from sage.rings.rational_field import is_RationalField
75
from sage.rings.ring import is_Ring
76
77
from sage.misc.cachefunc import cached_method
78
from sage.rings.arith import binomial, bernoulli
79
from sage.structure.element import MultiplicativeGroupElement
80
from sage.structure.sequence import Sequence
81
82
def trivial_character(N, base_ring=rings.RationalField()):
83
r"""
84
Return the trivial character of the given modulus, with values in the given
85
base ring.
86
87
EXAMPLE::
88
89
sage: t = trivial_character(7)
90
sage: [t(x) for x in [0..20]]
91
[0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1]
92
sage: t(1).parent()
93
Rational Field
94
sage: trivial_character(7, Integers(3))(1).parent()
95
Ring of integers modulo 3
96
"""
97
return DirichletGroup(N, base_ring)(1)
98
99
TrivialCharacter = trivial_character
100
101
def kronecker_character(d):
102
"""
103
Returns the quadratic Dirichlet character (d/.) of minimal
104
conductor.
105
106
EXAMPLES::
107
108
sage: kronecker_character(97*389*997^2)
109
Dirichlet character modulo 37733 of conductor 37733 mapping 1557 |--> -1, 37346 |--> -1
110
111
::
112
113
sage: a = kronecker_character(1)
114
sage: b = DirichletGroup(2401,QQ)(a) # NOTE -- over QQ!
115
sage: b.modulus()
116
2401
117
118
AUTHORS:
119
120
- Jon Hanke (2006-08-06)
121
"""
122
d = rings.Integer(d)
123
if d == 0:
124
raise ValueError, "d must be nonzero"
125
126
D = arith.fundamental_discriminant(d)
127
G = DirichletGroup(abs(D), rings.RationalField())
128
return G([arith.kronecker(D,u) for u in G.unit_gens()])
129
130
131
def kronecker_character_upside_down(d):
132
"""
133
Returns the quadratic Dirichlet character (./d) of conductor d, for
134
d0.
135
136
EXAMPLES::
137
138
sage: kronecker_character_upside_down(97*389*997^2)
139
Dirichlet character modulo 37506941597 of conductor 37733 mapping 13533432536 |--> -1, 22369178537 |--> -1, 14266017175 |--> 1
140
141
AUTHORS:
142
143
- Jon Hanke (2006-08-06)
144
"""
145
d = rings.Integer(d)
146
if d <= 0:
147
raise ValueError, "d must be positive"
148
149
G = DirichletGroup(d, rings.RationalField())
150
return G([arith.kronecker(u.lift(),d) for u in G.unit_gens()])
151
152
153
def is_DirichletCharacter(x):
154
r"""
155
Return True if x is of type DirichletCharacter.
156
157
EXAMPLES::
158
159
sage: from sage.modular.dirichlet import is_DirichletCharacter
160
sage: is_DirichletCharacter(trivial_character(3))
161
True
162
sage: is_DirichletCharacter([1])
163
False
164
"""
165
return isinstance(x, DirichletCharacter)
166
167
class DirichletCharacter(MultiplicativeGroupElement):
168
"""
169
A Dirichlet character
170
"""
171
def __init__(self, parent, x, check=True):
172
r"""
173
Create with ``DirichletCharacter(parent, values_on_gens)``
174
175
INPUT:
176
177
178
- ``parent`` - DirichletGroup, a group of Dirichlet
179
characters
180
181
- ``x``
182
183
- tuple (or list) of ring elements, the values of the
184
Dirichlet character on the chosen generators of
185
`(\ZZ/N\ZZ)^*`.
186
187
- Vector over Z/eZ, where e is the order of the root of
188
unity.
189
190
191
OUTPUT:
192
193
194
- ``DirichletCharacter`` - a Dirichlet character
195
196
197
EXAMPLES::
198
199
sage: G, e = DirichletGroup(13).objgen()
200
sage: G
201
Group of Dirichlet characters of modulus 13 over Cyclotomic Field of order 12 and degree 4
202
sage: e
203
Dirichlet character modulo 13 of conductor 13 mapping 2 |--> zeta12
204
sage: loads(e.dumps()) == e
205
True
206
207
::
208
209
sage: G, x = DirichletGroup(35).objgens()
210
sage: e = x[0]*x[1]; e
211
Dirichlet character modulo 35 of conductor 35 mapping 22 |--> zeta12^3, 31 |--> zeta12^2
212
sage: e.order()
213
12
214
sage: loads(e.dumps()) == e
215
True
216
"""
217
MultiplicativeGroupElement.__init__(self, parent)
218
self.__modulus = parent.modulus()
219
if check:
220
if len(x) != len(parent.unit_gens()):
221
raise ValueError, \
222
"wrong number of values(=%s) on unit gens (want %s)"%( \
223
x,len(parent.unit_gens()))
224
if free_module_element.is_FreeModuleElement(x):
225
self.__element = parent._module(x)
226
else:
227
R = parent.base_ring()
228
self.__values_on_gens = tuple([R(z) for z in x])
229
else:
230
if free_module_element.is_FreeModuleElement(x):
231
self.__element = x
232
else:
233
self.__values_on_gens = x
234
235
236
@cached_method
237
def __eval_at_minus_one(self):
238
r"""
239
Efficiently evaluate the character at -1 using knowledge of its
240
order. This is potentially much more efficient than computing the
241
value of -1 directly using dlog and a large power of the image root
242
of unity.
243
244
We use the following. Proposition: Suppose eps is a character mod
245
`p^n`, where `p` is a prime. Then
246
`\varepsilon(-1) = -1` if and only if `p = 2` and
247
the factor of eps at 4 is nontrivial or `p > 2` and 2 does
248
not divide `\phi(p^n)/\mbox{\rm ord}(\varepsilon)`.
249
250
EXAMPLES::
251
252
sage: chi = DirichletGroup(20).0; chi._DirichletCharacter__eval_at_minus_one()
253
-1
254
"""
255
D = self.decomposition()
256
val = self.base_ring()(1)
257
for e in D:
258
if e.modulus() % 2 == 0:
259
if e.modulus() % 4 == 0:
260
val *= e.values_on_gens()[0] # first gen is -1 for 2-power modulus
261
elif (arith.euler_phi(e.parent().modulus()) / e.order()) % 2 != 0:
262
val *= -1
263
return val
264
265
def __call__(self, m):
266
"""
267
Return the value of this character at the integer `m`.
268
269
.. warning::
270
271
A table of values of the character is made the first time
272
you call this. This table is currently constructed in a
273
somewhat stupid way, though it is still pretty fast.
274
275
EXAMPLES::
276
277
sage: G = DirichletGroup(60)
278
sage: e = prod(G.gens(), G(1))
279
sage: e
280
Dirichlet character modulo 60 of conductor 60 mapping 31 |--> -1, 41 |--> -1, 37 |--> zeta4
281
sage: e(2)
282
0
283
sage: e(7)
284
-zeta4
285
sage: Integers(60).unit_gens()
286
(31, 41, 37)
287
sage: e(31)
288
-1
289
sage: e(41)
290
-1
291
sage: e(37)
292
zeta4
293
sage: e(31*37)
294
-zeta4
295
sage: parent(e(31*37))
296
Cyclotomic Field of order 4 and degree 2
297
"""
298
m = int(m%self.__modulus)
299
try:
300
return self.__values[m]
301
except AttributeError:
302
pass
303
304
val = self.__modulus - 1
305
if m == val:
306
return self.__eval_at_minus_one()
307
else:
308
self.values() # compute all values
309
return self.__values[m]
310
311
def change_ring(self, R):
312
"""
313
Returns the base extension of self to the ring R.
314
315
EXAMPLE::
316
317
sage: e = DirichletGroup(7, QQ).0
318
sage: f = e.change_ring(QuadraticField(3, 'a'))
319
sage: f.parent()
320
Group of Dirichlet characters of modulus 7 over Number Field in a with defining polynomial x^2 - 3
321
322
::
323
324
sage: e = DirichletGroup(13).0
325
sage: e.change_ring(QQ)
326
Traceback (most recent call last):
327
...
328
ValueError: cannot coerce element of order 12 into self
329
"""
330
if self.base_ring() is R:
331
return self
332
G = self.parent().change_ring(R)
333
return G(self)
334
335
def __cmp__(self, other):
336
"""
337
Compare self to other. Note that this only gets called when the parents
338
of self and other are identical, via a canonical coercion map; this
339
means that characters of different moduli compare as unequal, even if
340
they define identical functions on ZZ.
341
342
EXAMPLES::
343
344
sage: e = DirichletGroup(16)([-1, 1])
345
sage: f = e.restrict(8)
346
sage: e == e
347
True
348
sage: f == f
349
True
350
sage: e == f
351
False
352
sage: k = DirichletGroup(7)([-1])
353
sage: k == e
354
False
355
"""
356
return cmp(self.element(), other.element())
357
358
def __hash__(self):
359
"""
360
EXAMPLES::
361
362
sage: e = DirichletGroup(16)([-1, 1])
363
sage: hash(e)
364
1498523633 # 32-bit
365
3713082714464823281 # 64-bit
366
"""
367
return self.element()._hash()
368
369
def __invert__(self):
370
"""
371
Return the multiplicative inverse of self. The notation is self.
372
373
EXAMPLES::
374
375
sage: e = DirichletGroup(13).0
376
sage: f = ~e
377
sage: f*e
378
Dirichlet character modulo 13 of conductor 1 mapping 2 |--> 1
379
"""
380
return DirichletCharacter(self.parent(), -self.element(), check=False)
381
382
def _mul_(self, other):
383
"""
384
Return the product of self and other.
385
386
EXAMPLES::
387
388
sage: G.<a,b> = DirichletGroup(20)
389
sage: a
390
Dirichlet character modulo 20 of conductor 4 mapping 11 |--> -1, 17 |--> 1
391
sage: b
392
Dirichlet character modulo 20 of conductor 5 mapping 11 |--> 1, 17 |--> zeta4
393
sage: a*b # indirect doctest
394
Dirichlet character modulo 20 of conductor 20 mapping 11 |--> -1, 17 |--> zeta4
395
396
Multiplying elements whose parents have different zeta orders works::
397
398
sage: a = DirichletGroup(3, QQ, zeta=1, zeta_order=1)(1)
399
sage: b = DirichletGroup(3, QQ, zeta=-1, zeta_order=2)([-1])
400
sage: a * b # indirect doctest
401
Dirichlet character modulo 3 of conductor 3 mapping 2 |--> -1
402
"""
403
x = self.element() + other.element()
404
return DirichletCharacter(self.parent(), x, check=False)
405
406
#values_on_gens = [self.__values_on_gens[i]*other.__values_on_gens[i]
407
#for i in range(len(self.__values_on_gens))]
408
# return DirichletCharacter(self.parent(), values_on_gens)
409
410
## def x_mul_(self, other):
411
## """
412
## Return the product of self and other.
413
414
## EXAMPLES:
415
## sage: G.<a,b> = DirichletGroup(20)
416
## sage: a
417
## [-1, 1]
418
## sage: b
419
## [1, zeta4]
420
## sage: a*b
421
## [-1, zeta4]
422
## """
423
## values_on_gens = [self.__values_on_gens[i]*other.__values_on_gens[i]
424
## for i in range(len(self.__values_on_gens))]
425
## return DirichletCharacter(self.parent(), values_on_gens)
426
## P = self.parent()
427
## dlog = P._zeta_dlog
428
## pows = P._zeta_powers
429
## n = len(pows)
430
## values_on_gens = [None]*len(self.__values_on_gens)
431
## for i in range(len(self.__values_on_gens)):
432
## k = (dlog[self.__values_on_gens[i]] + dlog[other.__values_on_gens[i]]) % n
433
## values_on_gens[i] = pows[k]
434
## return DirichletCharacter(self.parent(), values_on_gens)
435
436
def __copy__(self):
437
"""
438
Return a (shallow) copy of this Dirichlet character.
439
440
EXAMPLE::
441
442
sage: G.<a> = DirichletGroup(11)
443
sage: b = copy(a)
444
sage: a is b
445
False
446
sage: a.element() is b.element()
447
True
448
"""
449
# This method exists solely because of a bug in the cPickle module --
450
# see modsym/manin_symbols.py.
451
return DirichletCharacter(self.parent(), self.element(), check=False)
452
453
def __pow__(self, n):
454
"""
455
Return self raised to the power of n
456
457
EXAMPLES::
458
459
sage: G.<a,b> = DirichletGroup(20)
460
sage: a^2
461
Dirichlet character modulo 20 of conductor 1 mapping 11 |--> 1, 17 |--> 1
462
sage: b^2
463
Dirichlet character modulo 20 of conductor 5 mapping 11 |--> 1, 17 |--> -1
464
"""
465
return DirichletCharacter(self.parent(), n * self.element(), check=False)
466
467
def _repr_short_(self):
468
r"""
469
A short string representation of self, often used in string representations of modular forms
470
471
EXAMPLES::
472
473
sage: chi = DirichletGroup(24).0
474
sage: chi._repr_short_()
475
'[-1, 1, 1]'
476
477
"""
478
return str(list(self.values_on_gens()))
479
480
def _repr_(self):
481
"""
482
String representation of self.
483
484
EXAMPLES::
485
486
sage: G.<a,b> = DirichletGroup(20)
487
sage: repr(a) # indirect doctest
488
'Dirichlet character modulo 20 of conductor 4 mapping 11 |--> -1, 17 |--> 1'
489
490
"""
491
mapst = ''
492
for i in range(len(self.values_on_gens())):
493
if i != 0:
494
mapst += ', '
495
mapst += str(self.parent().unit_gens()[i]) + ' |--> ' + str(self.values_on_gens()[i])
496
return 'Dirichlet character modulo %s of conductor %s mapping %s'%(self.modulus(), self.conductor(), mapst)
497
498
def _latex_(self):
499
"""
500
LaTeX representation of self.
501
502
EXAMPLES::
503
504
sage: G.<a,b> = DirichletGroup(16)
505
sage: latex(b) # indirect doctest
506
\hbox{Dirichlet character modulo } 16 \hbox{ of conductor } 16 \hbox{ mapping } 15 \mapsto 1,\ 5 \mapsto \zeta_{4}
507
"""
508
from sage.misc.latex import latex
509
mapst = ''
510
for i in range(len(self.values_on_gens())):
511
if i != 0:
512
mapst += r',\ '
513
mapst += self.parent().unit_gens()[i]._latex_() + ' \mapsto ' + self.values_on_gens()[i]._latex_()
514
return r'\hbox{Dirichlet character modulo } %s \hbox{ of conductor } %s \hbox{ mapping } %s' \
515
% (self.modulus(), self.conductor(), mapst)
516
517
def base_ring(self):
518
"""
519
Returns the base ring of this Dirichlet character.
520
521
EXAMPLES::
522
523
sage: G = DirichletGroup(11)
524
sage: G.gen(0).base_ring()
525
Cyclotomic Field of order 10 and degree 4
526
sage: G = DirichletGroup(11, RationalField())
527
sage: G.gen(0).base_ring()
528
Rational Field
529
"""
530
return self.parent().base_ring()
531
532
def bar(self):
533
"""
534
Return the complex conjugate of this Dirichlet character.
535
536
EXAMPLES::
537
538
sage: e = DirichletGroup(5).0
539
sage: e
540
Dirichlet character modulo 5 of conductor 5 mapping 2 |--> zeta4
541
sage: e.bar()
542
Dirichlet character modulo 5 of conductor 5 mapping 2 |--> -zeta4
543
"""
544
return ~self
545
546
def bernoulli(self, k, algorithm='recurrence', cache=True, **opts):
547
r"""
548
Returns the generalized Bernoulli number `B_{k,eps}`.
549
550
INPUT:
551
552
553
- ``k`` - an integer
554
555
- ``algorithm`` - string (default: 'recurrence');
556
either 'recurrence' or 'definition'. The 'recurrence' algorithm
557
expresses generalized Bernoulli numbers in terms of classical
558
Bernoulli numbers using a recurrence formula and is usually
559
optimal. In this case ``**opts`` is passed onto the bernoulli
560
function.
561
562
- ``cache`` - if True, cache answers
563
564
565
Let eps be this character (not necessarily primitive), and let
566
`k \geq 0` be an integer weight. This function computes the
567
(generalized) Bernoulli number `B_{k,eps}`, e.g., as
568
defined on page 44 of Diamond-Im:
569
570
.. math::
571
572
\sum_{a=1}^{N} \varepsilon(a) t*e^{at} / (e^{Nt}-1) = sum_{k=0}^{\infty} B_{k,eps}/{k!} t^k.
573
574
575
where `N` is the modulus of `\varepsilon`.
576
577
The default algorithm is the recurrence on page 656 of Cohen's GTM
578
'Number Theory and Diophantine Equations', section 9.
579
580
EXAMPLES::
581
582
sage: G = DirichletGroup(13)
583
sage: e = G.0
584
sage: e.bernoulli(5)
585
7430/13*zeta12^3 - 34750/13*zeta12^2 - 11380/13*zeta12 + 9110/13
586
sage: eps = DirichletGroup(9).0
587
sage: eps.bernoulli(3)
588
10*zeta6 + 4
589
sage: eps.bernoulli(3, algorithm="definition")
590
10*zeta6 + 4
591
"""
592
if cache:
593
try:
594
self.__bernoulli
595
except AttributeError:
596
self.__bernoulli = {}
597
if self.__bernoulli.has_key(k):
598
return self.__bernoulli[k]
599
N = self.modulus()
600
K = self.base_ring()
601
602
if N != 1 and self(-1) != K((-1)**k):
603
ans = K(0)
604
if cache:
605
self.__bernoulli[k] = ans
606
return ans
607
608
if algorithm == "recurrence":
609
# The following code is pretty fast, at least compared to
610
# the other algorithm below. That said, I'm sure it could
611
# be sped up by a factor of 10 or more in many cases,
612
# especially since we end up computing all the bernoulli
613
# numbers up to k, which should be done with power series
614
# instead of calls to the bernoulli function. Likewise
615
# computing all binomial coefficients can be done much
616
# more efficiently.
617
if self.modulus() == 1:
618
ber = K(bernoulli(k))
619
else:
620
v = self.values()
621
S = lambda n: sum(v[r] * r**n for r in range(1, N))
622
ber = K(sum(binomial(k,j) * bernoulli(j, **opts) *
623
N**(j-1) * S(k-j) for j in range(k+1)))
624
625
elif algorithm == "definition":
626
# This is better since it computes the same thing, but requires
627
# no arith in a poly ring over a number field.
628
prec = k+2
629
R = rings.PowerSeriesRing(rings.QQ, 't')
630
t = R.gen()
631
# g(t) = t/(e^{Nt}-1)
632
g = t/((N*t).exp(prec) - 1)
633
634
# h(n) = g(t)*e^{nt}
635
h = [0] + [g * ((n*t).exp(prec)) for n in range(1,N+1)]
636
ber = sum([self(a)*h[a][k] for a in range(1,N+1)]) * arith.factorial(k)
637
638
else:
639
raise ValueError, "algorithm = '%s' unknown"%algorithm
640
641
if cache:
642
self.__bernoulli[k] = ber
643
return ber
644
645
@cached_method
646
def conductor(self):
647
"""
648
Computes and returns the conductor of this character.
649
650
EXAMPLES::
651
652
sage: G.<a,b> = DirichletGroup(20)
653
sage: a.conductor()
654
4
655
sage: b.conductor()
656
5
657
sage: (a*b).conductor()
658
20
659
660
TESTS::
661
662
sage: G.<a, b> = DirichletGroup(20)
663
sage: type(G(1).conductor())
664
<type 'sage.rings.integer.Integer'>
665
"""
666
if self.modulus() == 1 or self.is_trivial():
667
return rings.Integer(1)
668
F = arith.factor(self.modulus())
669
if len(F) > 1:
670
return misc.mul([d.conductor() for d in self.decomposition()])
671
p = F[0][0]
672
# When p is odd, and x =/= 1, the conductor is the smallest p**r such that
673
# Order(x) divides EulerPhi(p**r) = p**(r-1)*(p-1).
674
# For a given r, whether or not the above divisibility holds
675
# depends only on the factor of p**(r-1) on the right hand side.
676
# Since p-1 is coprime to p, this smallest r such that the
677
# divisibility holds equals Valuation(Order(x),p)+1.
678
cond = p**(arith.valuation(self.order(),p) + 1)
679
if p == 2 and F[0][1] > 2 and self.values_on_gens()[1].multiplicative_order() != 1:
680
cond *= 2;
681
return rings.Integer(cond)
682
683
@cached_method
684
def decomposition(self):
685
"""
686
Return the decomposition of self as a product of Dirichlet
687
characters of prime power modulus, where the prime powers exactly
688
divide the modulus of this character.
689
690
EXAMPLES::
691
692
sage: G.<a,b> = DirichletGroup(20)
693
sage: c = a*b
694
sage: d = c.decomposition(); d
695
[Dirichlet character modulo 4 of conductor 4 mapping 3 |--> -1, Dirichlet character modulo 5 of conductor 5 mapping 2 |--> zeta4]
696
sage: d[0].parent()
697
Group of Dirichlet characters of modulus 4 over Cyclotomic Field of order 4 and degree 2
698
sage: d[1].parent()
699
Group of Dirichlet characters of modulus 5 over Cyclotomic Field of order 4 and degree 2
700
701
We can't multiply directly, since coercion of one element into the
702
other parent fails in both cases::
703
704
sage: d[0]*d[1] == c
705
Traceback (most recent call last):
706
...
707
TypeError: unsupported operand parent(s) for '*': 'Group of Dirichlet characters of modulus 4 over Cyclotomic Field of order 4 and degree 2' and 'Group of Dirichlet characters of modulus 5 over Cyclotomic Field of order 4 and degree 2'
708
709
We can multiply if we're explicit about where we want the
710
multiplication to take place.
711
712
::
713
714
sage: G(d[0])*G(d[1]) == c
715
True
716
717
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`::
718
719
sage: (DirichletGroup(18).0).decomposition()
720
[Dirichlet character modulo 2 of conductor 1 mapping , Dirichlet character modulo 9 of conductor 9 mapping 2 |--> zeta6]
721
sage: (DirichletGroup(36).0).decomposition()
722
[Dirichlet character modulo 4 of conductor 4 mapping 3 |--> -1, Dirichlet character modulo 9 of conductor 1 mapping 2 |--> 1]
723
sage: (DirichletGroup(72).0).decomposition()
724
[Dirichlet character modulo 8 of conductor 4 mapping 7 |--> -1, 5 |--> 1, Dirichlet character modulo 9 of conductor 1 mapping 2 |--> 1]
725
"""
726
D = self.parent().decomposition()
727
vals = [[z] for z in self.values_on_gens()]
728
R = self.base_ring()
729
if self.modulus() % 8 == 0: # 2 factors at 2.
730
vals[0].append(vals[1][0])
731
del vals[1]
732
elif self.modulus() % 4 == 2: # 0 factors at 2.
733
vals = [1] + vals
734
return [D[i](vals[i]) for i in range(len(D))]
735
736
def extend(self, M):
737
"""
738
Returns the extension of this character to a Dirichlet character
739
modulo the multiple M of the modulus.
740
741
EXAMPLES::
742
743
sage: G.<a,b> = DirichletGroup(20)
744
sage: H.<c> = DirichletGroup(4)
745
sage: c.extend(20)
746
Dirichlet character modulo 20 of conductor 4 mapping 11 |--> -1, 17 |--> 1
747
sage: a
748
Dirichlet character modulo 20 of conductor 4 mapping 11 |--> -1, 17 |--> 1
749
sage: c.extend(20) == a
750
True
751
"""
752
if M % self.modulus() != 0:
753
raise ArithmeticError, "M(=%s) must be a multiple of the modulus(=%s)"%(M,self.modulus())
754
H = DirichletGroup(M, self.base_ring())
755
return H(self)
756
757
def galois_orbit(self, sort=True):
758
r"""
759
Return the orbit of this character under the action of the absolute
760
Galois group of the prime subfield of the base ring.
761
762
EXAMPLES::
763
764
sage: G = DirichletGroup(30); e = G.1
765
sage: e.galois_orbit()
766
[Dirichlet character modulo 30 of conductor 5 mapping 11 |--> 1, 7 |--> zeta4, Dirichlet character modulo 30 of conductor 5 mapping 11 |--> 1, 7 |--> -zeta4]
767
768
Another example::
769
770
sage: G = DirichletGroup(13)
771
sage: G.galois_orbits()
772
[
773
[Dirichlet character modulo 13 of conductor 1 mapping 2 |--> 1], ... [Dirichlet character modulo 13 of conductor 13 mapping 2 |--> -1]
774
]
775
sage: e = G.0
776
sage: e
777
Dirichlet character modulo 13 of conductor 13 mapping 2 |--> zeta12
778
sage: e.galois_orbit()
779
[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, Dirichlet character modulo 13 of conductor 13 mapping 2 |--> -zeta12^3 + zeta12]
780
sage: e = G.0^2; e
781
Dirichlet character modulo 13 of conductor 13 mapping 2 |--> zeta12^2
782
sage: e.galois_orbit()
783
[Dirichlet character modulo 13 of conductor 13 mapping 2 |--> zeta12^2, Dirichlet character modulo 13 of conductor 13 mapping 2 |--> -zeta12^2 + 1]
784
785
A non-example::
786
787
sage: chi = DirichletGroup(7, Integers(9), zeta = Integers(9)(2)).0
788
sage: chi.galois_orbit()
789
Traceback (most recent call last):
790
...
791
TypeError: Galois orbits only defined if base ring is an integral domain
792
"""
793
if not self.base_ring().is_integral_domain():
794
raise TypeError, "Galois orbits only defined if base ring is an integral domain"
795
k = self.order()
796
if k <= 2:
797
return [self]
798
P = self.parent()
799
z = self.element()
800
o = int(z.additive_order())
801
Auts = set([m % o for m in P._automorphisms()])
802
v = [DirichletCharacter(P, m * z, check=False) for m in Auts]
803
if sort:
804
v.sort()
805
return v
806
807
808
def gauss_sum(self, a=1):
809
r"""
810
Return a Gauss sum associated to this Dirichlet character.
811
812
The Gauss sum associated to `\chi` is
813
814
.. math::
815
816
g_a(\chi) = \sum_{r \in \ZZ/m\ZZ} \chi(r)\,\zeta^{ar},
817
818
819
where `m` is the modulus of `\chi` and
820
`\zeta` is a primitive `m^{th}` root of unity, i.e.,
821
`\zeta` is ``self.parent().zeta()``.
822
823
FACTS: If the modulus is a prime `p` and the character is
824
nontrivial, then the Gauss sum has absolute value
825
`\sqrt{p}`.
826
827
CACHING: Computed Gauss sums are *not* cached with this character.
828
829
EXAMPLES::
830
831
sage: G = DirichletGroup(3)
832
sage: e = G([-1])
833
sage: e.gauss_sum(1)
834
2*zeta6 - 1
835
sage: e.gauss_sum(2)
836
-2*zeta6 + 1
837
sage: norm(e.gauss_sum())
838
3
839
840
::
841
842
sage: G = DirichletGroup(13)
843
sage: e = G.0
844
sage: e.gauss_sum()
845
-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
846
sage: factor(norm(e.gauss_sum()))
847
13^24
848
"""
849
G = self.parent()
850
K = G.base_ring()
851
if not (rings.is_CyclotomicField(K) or is_RationalField(K)):
852
raise NotImplementedError, "Gauss sums only currently implemented when the base ring is a cyclotomic field or QQ."
853
g = 0
854
m = G.modulus()
855
L = rings.CyclotomicField(arith.lcm(m,G.zeta_order()))
856
zeta = L.gen(0)
857
n = zeta.multiplicative_order()
858
zeta = zeta ** (n // m)
859
if a != 1:
860
zeta = zeta**a
861
z = 1
862
for c in self.values()[1:]:
863
z *= zeta
864
g += L(c)*z
865
return g
866
867
def gauss_sum_numerical(self, prec=53, a=1):
868
r"""
869
Return a Gauss sum associated to this Dirichlet character as an
870
approximate complex number with prec bits of precision.
871
872
INPUT:
873
874
875
- ``prec`` - integer (default: 53), *bits* of precision
876
877
- ``a`` - integer, as for gauss_sum.
878
879
880
The Gauss sum associated to `\chi` is
881
882
.. math::
883
884
g_a(\chi) = \sum_{r \in \ZZ/m\ZZ} \chi(r)\,\zeta^{ar},
885
886
887
where `m` is the modulus of `\chi` and
888
`\zeta` is a primitive `m^{th}` root of unity, i.e.,
889
`\zeta` is ``self.parent().zeta()``.
890
891
EXAMPLES::
892
893
sage: G = DirichletGroup(3)
894
sage: e = G.0
895
sage: abs(e.gauss_sum_numerical())
896
1.7320508075...
897
sage: sqrt(3.0)
898
1.73205080756888
899
sage: e.gauss_sum_numerical(a=2)
900
-...e-15 - 1.7320508075...*I
901
sage: e.gauss_sum_numerical(a=2, prec=100)
902
4.7331654313260708324703713917e-30 - 1.7320508075688772935274463415*I
903
sage: G = DirichletGroup(13)
904
sage: e = G.0
905
sage: e.gauss_sum_numerical()
906
-3.07497205... + 1.8826966926...*I
907
sage: abs(e.gauss_sum_numerical())
908
3.60555127546...
909
sage: sqrt(13.0)
910
3.60555127546399
911
"""
912
G = self.parent()
913
K = G.base_ring()
914
if not (rings.is_CyclotomicField(K) or is_RationalField(K)):
915
raise NotImplementedError, "Gauss sums only currently implemented when the base ring is a cyclotomic field or QQ."
916
phi = K.complex_embedding(prec)
917
CC = phi.codomain()
918
919
g = 0
920
m = G.modulus()
921
zeta = CC.zeta(m)
922
if a != 1:
923
zeta = zeta**a
924
z = 1
925
for c in self.values()[1:]:
926
z *= zeta
927
g += phi(c)*z
928
return g
929
930
def jacobi_sum(self, char, check=True):
931
"""
932
Return the Jacobi sum associated to these Dirichlet characters
933
(i.e., J(self,char)). This is defined as
934
935
.. math::
936
937
J(\chi, \psi) = \sum_{a \in \ZZ / N\ZZ} \chi(a) \psi(1-a)
938
939
where `\chi` and `\psi` are both characters modulo `N`.
940
941
EXAMPLES::
942
943
sage: D = DirichletGroup(13)
944
sage: e = D.0
945
sage: f = D[-2]
946
sage: e.jacobi_sum(f)
947
3*zeta12^2 + 2*zeta12 - 3
948
sage: f.jacobi_sum(e)
949
3*zeta12^2 + 2*zeta12 - 3
950
sage: p = 7
951
sage: DP = DirichletGroup(p)
952
sage: f = DP.0
953
sage: e.jacobi_sum(f)
954
Traceback (most recent call last):
955
...
956
NotImplementedError: Characters must be from the same Dirichlet Group.
957
958
sage: all_jacobi_sums = [(DP[i].values_on_gens(),DP[j].values_on_gens(),DP[i].jacobi_sum(DP[j])) \
959
... for i in range(p-1) for j in range(p-1)[i:]]
960
...
961
sage: for s in all_jacobi_sums:
962
... print s
963
((1,), (1,), 5)
964
((1,), (zeta6,), -1)
965
((1,), (zeta6 - 1,), -1)
966
((1,), (-1,), -1)
967
((1,), (-zeta6,), -1)
968
((1,), (-zeta6 + 1,), -1)
969
((zeta6,), (zeta6,), -zeta6 + 3)
970
((zeta6,), (zeta6 - 1,), 2*zeta6 + 1)
971
((zeta6,), (-1,), -2*zeta6 - 1)
972
((zeta6,), (-zeta6,), zeta6 - 3)
973
((zeta6,), (-zeta6 + 1,), 1)
974
((zeta6 - 1,), (zeta6 - 1,), -3*zeta6 + 2)
975
((zeta6 - 1,), (-1,), 2*zeta6 + 1)
976
((zeta6 - 1,), (-zeta6,), -1)
977
((zeta6 - 1,), (-zeta6 + 1,), -zeta6 - 2)
978
((-1,), (-1,), 1)
979
((-1,), (-zeta6,), -2*zeta6 + 3)
980
((-1,), (-zeta6 + 1,), 2*zeta6 - 3)
981
((-zeta6,), (-zeta6,), 3*zeta6 - 1)
982
((-zeta6,), (-zeta6 + 1,), -2*zeta6 + 3)
983
((-zeta6 + 1,), (-zeta6 + 1,), zeta6 + 2)
984
985
Let's check that trivial sums are being calculated correctly::
986
987
sage: N = 13
988
sage: D = DirichletGroup(N)
989
sage: g = D(1)
990
sage: g.jacobi_sum(g)
991
11
992
sage: sum([g(x)*g(1-x) for x in IntegerModRing(N)])
993
11
994
995
And sums where exactly one character is nontrivial (see trac #6393)::
996
997
sage: G=DirichletGroup(5); X=G.list(); Y=X[0]; Z=X[1]
998
sage: Y.jacobi_sum(Z)
999
-1
1000
sage: Z.jacobi_sum(Y)
1001
-1
1002
1003
Now let's take a look at a non-prime modulus::
1004
1005
sage: N = 9
1006
sage: D = DirichletGroup(N)
1007
sage: g = D(1)
1008
sage: g.jacobi_sum(g)
1009
3
1010
1011
We consider a sum with values in a finite field::
1012
1013
sage: g = DirichletGroup(17, GF(9,'a')).0
1014
sage: g.jacobi_sum(g**2)
1015
2*a
1016
1017
TESTS:
1018
1019
This shows that ticket #6393 has been fixed::
1020
1021
sage: G = DirichletGroup(5); X = G.list(); Y = X[0]; Z = X[1]
1022
sage: # Y is trivial and Z is quartic
1023
sage: sum([Y(x)*Z(1-x) for x in IntegerModRing(5)])
1024
-1
1025
sage: # The value -1 above is the correct value of the Jacobi sum J(Y, Z).
1026
sage: Y.jacobi_sum(Z); Z.jacobi_sum(Y)
1027
-1
1028
-1
1029
"""
1030
if check:
1031
if self.parent() != char.parent():
1032
raise NotImplementedError, "Characters must be from the same Dirichlet Group."
1033
1034
return sum([self(x) * char(1-x) for x in rings.IntegerModRing(self.modulus())])
1035
1036
def kloosterman_sum(self, a=1,b=0):
1037
r"""
1038
Return the "twisted" Kloosterman sum associated to this Dirichlet character.
1039
This includes Gauss sums, classical Kloosterman sums, Salie sums, etc.
1040
1041
The Kloosterman sum associated to `\chi` and the integers a,b is
1042
1043
.. math::
1044
1045
K(a,b,\chi) = \sum_{r \in (\ZZ/m\ZZ)^\times} \chi(r)\,\zeta^{ar+br^{-1}},
1046
1047
where `m` is the modulus of `\chi` and `\zeta` is a primitive
1048
`m` th root of unity. This reduces to to the Gauss sum if `b=0`.
1049
1050
This method performs an exact calculation and returns an element of a
1051
suitable cyclotomic field; see also :meth:`.kloosterman_sum_numerical`,
1052
which gives an inexact answer (but is generally much quicker).
1053
1054
CACHING: Computed Kloosterman sums are *not* cached with this
1055
character.
1056
1057
EXAMPLES::
1058
1059
sage: G = DirichletGroup(3)
1060
sage: e = G([-1])
1061
sage: e.kloosterman_sum(3,5)
1062
-2*zeta6 + 1
1063
sage: G = DirichletGroup(20)
1064
sage: e = G([1 for u in G.unit_gens()])
1065
sage: e.kloosterman_sum(7,17)
1066
-2*zeta20^6 + 2*zeta20^4 + 4
1067
1068
"""
1069
G = self.parent()
1070
K = G.base_ring()
1071
if not (rings.is_CyclotomicField(K) or is_RationalField(K)):
1072
raise NotImplementedError, "Kloosterman sums only currently implemented when the base ring is a cyclotomic field or QQ."
1073
g = 0
1074
m = G.modulus()
1075
L = rings.CyclotomicField(arith.lcm(m,G.zeta_order()))
1076
zeta = L.gen(0)
1077
n = zeta.multiplicative_order()
1078
zeta = zeta ** (n // m)
1079
for c in range(1,m):
1080
if arith.gcd(c,m)==1:
1081
e = rings.Mod(c,m)
1082
z = zeta ** int(a*e + b*(e**(-1)))
1083
g += self.__call__(c)*z
1084
return g
1085
1086
def kloosterman_sum_numerical(self, prec=53, a=1,b=0):
1087
r"""
1088
Return the Kloosterman sum associated to this Dirichlet character as
1089
an approximate complex number with prec bits of precision. See also
1090
:meth:`.kloosterman_sum`, which calculates the sum exactly (which is
1091
generally slower).
1092
1093
INPUT:
1094
1095
- ``prec`` -- integer (default: 53), *bits* of precision
1096
- ``a`` -- integer, as for :meth:`.kloosterman_sum`
1097
- ``b`` -- integer, as for :meth:`.kloosterman_sum`.
1098
1099
EXAMPLES::
1100
1101
sage: G = DirichletGroup(3)
1102
sage: e = G.0
1103
1104
The real component of the numerical value of e is near zero::
1105
1106
sage: v=e.kloosterman_sum_numerical()
1107
sage: v.real() < 1.0e15
1108
True
1109
sage: v.imag()
1110
1.73205080756888
1111
sage: G = DirichletGroup(20)
1112
sage: e = G.1
1113
sage: e.kloosterman_sum_numerical(53,3,11)
1114
3.80422606518061 - 3.80422606518061*I
1115
"""
1116
G = self.parent()
1117
K = G.base_ring()
1118
if not (rings.is_CyclotomicField(K) or is_RationalField(K)):
1119
raise NotImplementedError, "Kloosterman sums only currently implemented when the base ring is a cyclotomic field or QQ."
1120
phi = K.complex_embedding(prec)
1121
CC = phi.codomain()
1122
g = 0
1123
m = G.modulus()
1124
zeta = CC.zeta(m)
1125
1126
for c in range(1,m):
1127
if arith.gcd(c,m)==1:
1128
e = rings.Mod(c,m)
1129
z = zeta ** int(a*e + b*(e**(-1)))
1130
g += phi(self.__call__(c))*z
1131
return g
1132
1133
@cached_method
1134
def is_even(self):
1135
r"""
1136
Return ``True`` if and only if `\varepsilon(-1) = 1`.
1137
1138
EXAMPLES::
1139
1140
sage: G = DirichletGroup(13)
1141
sage: e = G.0
1142
sage: e.is_even()
1143
False
1144
sage: e(-1)
1145
-1
1146
sage: [e.is_even() for e in G]
1147
[True, False, True, False, True, False, True, False, True, False, True, False]
1148
1149
Note that ``is_even`` need not be the negation of
1150
is_odd, e.g., in characteristic 2::
1151
1152
sage: G.<e> = DirichletGroup(13, GF(4,'a'))
1153
sage: e.is_even()
1154
True
1155
sage: e.is_odd()
1156
True
1157
"""
1158
return (self(-1) == self.base_ring()(1))
1159
1160
@cached_method
1161
def is_odd(self):
1162
r"""
1163
Return ``True`` if and only if
1164
`\varepsilon(-1) = -1`.
1165
1166
EXAMPLES::
1167
1168
sage: G = DirichletGroup(13)
1169
sage: e = G.0
1170
sage: e.is_odd()
1171
True
1172
sage: [e.is_odd() for e in G]
1173
[False, True, False, True, False, True, False, True, False, True, False, True]
1174
1175
Note that ``is_even`` need not be the negation of
1176
is_odd, e.g., in characteristic 2::
1177
1178
sage: G.<e> = DirichletGroup(13, GF(4,'a'))
1179
sage: e.is_even()
1180
True
1181
sage: e.is_odd()
1182
True
1183
"""
1184
return (self(-1) == self.base_ring()(-1))
1185
1186
@cached_method
1187
def is_primitive(self):
1188
"""
1189
Return ``True`` if and only if this character is
1190
primitive, i.e., its conductor equals its modulus.
1191
1192
EXAMPLES::
1193
1194
sage: G.<a,b> = DirichletGroup(20)
1195
sage: a.is_primitive()
1196
False
1197
sage: b.is_primitive()
1198
False
1199
sage: (a*b).is_primitive()
1200
True
1201
"""
1202
return (self.conductor() == self.modulus())
1203
1204
@cached_method
1205
def is_trivial(self):
1206
r"""
1207
Returns ``True`` if this is the trivial character,
1208
i.e., has order 1.
1209
1210
EXAMPLES::
1211
1212
sage: G.<a,b> = DirichletGroup(20)
1213
sage: a.is_trivial()
1214
False
1215
sage: (a^2).is_trivial()
1216
True
1217
"""
1218
return (self.element() == 0)
1219
1220
def kernel(self):
1221
r"""
1222
Return the kernel of this character.
1223
1224
OUTPUT: Currently the kernel is returned as a list. This may
1225
change.
1226
1227
EXAMPLES::
1228
1229
sage: G.<a,b> = DirichletGroup(20)
1230
sage: a.kernel()
1231
[1, 9, 13, 17]
1232
sage: b.kernel()
1233
[1, 11]
1234
"""
1235
one = self.base_ring()(1)
1236
return [x for x in range(self.modulus()) if self(x) == one]
1237
1238
def maximize_base_ring(self):
1239
r"""
1240
Let
1241
1242
.. math::
1243
1244
\varepsilon : (\ZZ/N\ZZ)^* \to \QQ(\zeta_n)
1245
1246
1247
be a Dirichlet character. This function returns an equal Dirichlet
1248
character
1249
1250
.. math::
1251
1252
\chi : (\ZZ/N\ZZ)^* \to \QQ(\zeta_m)
1253
1254
1255
where `m` is the least common multiple of `n` and
1256
the exponent of `(\ZZ/N\ZZ)^*`.
1257
1258
EXAMPLES::
1259
1260
sage: G.<a,b> = DirichletGroup(20,QQ)
1261
sage: b.maximize_base_ring()
1262
Dirichlet character modulo 20 of conductor 5 mapping 11 |--> 1, 17 |--> -1
1263
sage: b.maximize_base_ring().base_ring()
1264
Cyclotomic Field of order 4 and degree 2
1265
sage: DirichletGroup(20).base_ring()
1266
Cyclotomic Field of order 4 and degree 2
1267
"""
1268
g = rings.IntegerModRing(self.modulus()).unit_group_exponent()
1269
if g == 1:
1270
g = 2
1271
z = self.base_ring().zeta()
1272
n = z.multiplicative_order()
1273
m = arith.LCM(g,n)
1274
if n == m:
1275
return self
1276
K = rings.CyclotomicField(m)
1277
return self.change_ring(K)
1278
1279
def minimize_base_ring(self):
1280
r"""
1281
Return a Dirichlet character that equals this one, but over as
1282
small a subfield (or subring) of the base ring as possible.
1283
1284
.. note::
1285
1286
This function is currently only implemented when the base
1287
ring is a number field. It's the identity function in
1288
characteristic p.
1289
1290
EXAMPLES::
1291
1292
sage: G = DirichletGroup(13)
1293
sage: e = DirichletGroup(13).0
1294
sage: e.base_ring()
1295
Cyclotomic Field of order 12 and degree 4
1296
sage: e.minimize_base_ring().base_ring()
1297
Cyclotomic Field of order 12 and degree 4
1298
sage: (e^2).minimize_base_ring().base_ring()
1299
Cyclotomic Field of order 6 and degree 2
1300
sage: (e^3).minimize_base_ring().base_ring()
1301
Cyclotomic Field of order 4 and degree 2
1302
sage: (e^12).minimize_base_ring().base_ring()
1303
Rational Field
1304
"""
1305
if isinstance(self.base_ring(),rings.RationalField):
1306
return self
1307
1308
if self.is_trivial() and self.base_ring().characteristic() == 0:
1309
return self.change_ring(rings.QQ)
1310
1311
if isinstance(self.base_ring(),number_field.NumberField_generic):
1312
if self.order() <= 2:
1313
return self.change_ring(rings.RationalField())
1314
if arith.euler_phi(self.order()) == self.base_ring().degree():
1315
return self
1316
K = rings.CyclotomicField(self.order())
1317
return self.change_ring(K)
1318
1319
#raise NotImplementedError, "minimize_base_ring is currently " + \
1320
# "only implemented when the base ring is a number field."
1321
return self
1322
1323
def modulus(self):
1324
"""
1325
The modulus of this character.
1326
1327
EXAMPLES::
1328
1329
sage: e = DirichletGroup(100, QQ).0
1330
sage: e.modulus()
1331
100
1332
sage: e.conductor()
1333
4
1334
"""
1335
return self.__modulus
1336
1337
def level(self):
1338
"""
1339
Synonym for modulus.
1340
1341
EXAMPLE::
1342
1343
sage: e = DirichletGroup(100, QQ).0
1344
sage: e.level()
1345
100
1346
"""
1347
return self.modulus()
1348
1349
@cached_method
1350
def multiplicative_order(self):
1351
"""
1352
The order of this character.
1353
1354
EXAMPLES::
1355
1356
sage: e = DirichletGroup(100).1
1357
sage: e.order() # same as multiplicative_order, since group is multiplicative
1358
20
1359
sage: e.multiplicative_order()
1360
20
1361
sage: e = DirichletGroup(100).0
1362
sage: e.multiplicative_order()
1363
2
1364
"""
1365
return self.element().additive_order()
1366
1367
def primitive_character(self):
1368
"""
1369
Returns the primitive character associated to self.
1370
1371
EXAMPLES::
1372
1373
sage: e = DirichletGroup(100).0; e
1374
Dirichlet character modulo 100 of conductor 4 mapping 51 |--> -1, 77 |--> 1
1375
sage: e.conductor()
1376
4
1377
sage: f = e.primitive_character(); f
1378
Dirichlet character modulo 4 of conductor 4 mapping 3 |--> -1
1379
sage: f.modulus()
1380
4
1381
"""
1382
return self.restrict(self.conductor())
1383
1384
def restrict(self, M):
1385
"""
1386
Returns the restriction of this character to a Dirichlet character
1387
modulo the divisor M of the modulus, which must also be a multiple
1388
of the conductor of this character.
1389
1390
EXAMPLES::
1391
1392
sage: e = DirichletGroup(100).0
1393
sage: e.modulus()
1394
100
1395
sage: e.conductor()
1396
4
1397
sage: e.restrict(20)
1398
Dirichlet character modulo 20 of conductor 4 mapping 11 |--> -1, 17 |--> 1
1399
sage: e.restrict(4)
1400
Dirichlet character modulo 4 of conductor 4 mapping 3 |--> -1
1401
sage: e.restrict(50)
1402
Traceback (most recent call last):
1403
...
1404
ValueError: conductor(=4) must divide M(=50)
1405
"""
1406
M = int(M)
1407
if self.modulus()%M != 0:
1408
raise ValueError, "M(=%s) must divide the modulus(=%s)"%(M,self.modulus())
1409
if M%self.conductor() != 0:
1410
raise ValueError, "conductor(=%s) must divide M(=%s)"%(self.conductor(),M)
1411
H = DirichletGroup(M, self.base_ring())
1412
return H(self)
1413
1414
def values(self):
1415
"""
1416
Returns a list of the values of this character on each integer
1417
between 0 and the modulus.
1418
1419
EXAMPLES::
1420
1421
sage: e = DirichletGroup(20)(1)
1422
sage: e.values()
1423
[0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1]
1424
sage: e = DirichletGroup(20).gen(0)
1425
sage: print e.values()
1426
[0, 1, 0, -1, 0, 0, 0, -1, 0, 1, 0, -1, 0, 1, 0, 0, 0, 1, 0, -1]
1427
sage: e = DirichletGroup(20).gen(1)
1428
sage: e.values()
1429
[0, 1, 0, -zeta4, 0, 0, 0, zeta4, 0, -1, 0, 1, 0, -zeta4, 0, 0, 0, zeta4, 0, -1]
1430
sage: e = DirichletGroup(21).gen(0) ; e.values()
1431
[0, 1, -1, 0, 1, -1, 0, 0, -1, 0, 1, -1, 0, 1, 0, 0, 1, -1, 0, 1, -1]
1432
sage: e = DirichletGroup(21, base_ring=GF(37)).gen(0) ; e.values()
1433
[0, 1, 36, 0, 1, 36, 0, 0, 36, 0, 1, 36, 0, 1, 0, 0, 1, 36, 0, 1, 36]
1434
sage: e = DirichletGroup(21, base_ring=GF(3)).gen(0) ; e.values()
1435
[0, 1, 2, 0, 1, 2, 0, 0, 2, 0, 1, 2, 0, 1, 0, 0, 1, 2, 0, 1, 2]
1436
1437
::
1438
1439
sage: chi = DirichletGroup(100151, CyclotomicField(10)).0
1440
sage: ls = chi.values() ; ls[0:10]
1441
[0,
1442
1,
1443
-zeta10^3,
1444
-zeta10,
1445
-zeta10,
1446
1,
1447
zeta10^3 - zeta10^2 + zeta10 - 1,
1448
zeta10,
1449
zeta10^3 - zeta10^2 + zeta10 - 1,
1450
zeta10^2]
1451
1452
Test that :trac:`14368` is fixed::
1453
1454
sage: DirichletGroup(1).list()[0].values()
1455
[1]
1456
"""
1457
try:
1458
return self.__values
1459
except AttributeError:
1460
pass
1461
# Build cache of all values of the Dirichlet character.
1462
# I'm going to do it this way, since in my app the modulus
1463
# is *always* small and we want to evaluate the character
1464
# a *lot*.
1465
G = self.parent()
1466
R = G.base_ring()
1467
zero = R(0)
1468
one = R(1)
1469
mod = self.__modulus
1470
1471
if self.is_trivial(): # easy special case
1472
x = [ one ] * int(mod)
1473
1474
for p in mod.prime_divisors():
1475
p_mult = p
1476
while p_mult < mod:
1477
x[p_mult] = zero
1478
p_mult += p
1479
if not (mod == 1):
1480
x[0] = zero
1481
self.__values = x
1482
return x
1483
1484
result_list = [zero] * mod
1485
1486
zeta_order = G.zeta_order()
1487
zeta = R.zeta(zeta_order)
1488
A = rings.Integers(zeta_order)
1489
A_zero = A.zero_element()
1490
A_one = A.one_element()
1491
ZZ = rings.ZZ
1492
1493
S = G._integers
1494
1495
R_values = G._zeta_powers
1496
1497
gens = G.unit_gens()
1498
last = [ x.multiplicative_order()-1 for x in G.unit_gens() ]
1499
1500
ngens = len(gens)
1501
exponents = [0] * ngens
1502
n = S(1)
1503
1504
value = A_zero
1505
val_on_gen = [ A(R_values.index(x)) for x in self.values_on_gens() ]
1506
1507
final_index = ngens-1
1508
stop = last[-1]
1509
while exponents[-1] <= stop:
1510
1511
########################
1512
# record character value on n
1513
result_list[n] = R_values[value]
1514
# iterate:
1515
# increase the exponent vector by 1,
1516
# increase n accordingly, and increase value
1517
exponents[0] += 1 # inc exponent
1518
value += val_on_gen[0] # inc value
1519
n *= gens[0]
1520
## n %= mod
1521
i = 0
1522
while i < final_index and exponents[i] > last[i]:
1523
exponents[i] = 0
1524
# now increment position i+1:
1525
exponents[i+1] += 1
1526
value += val_on_gen[i+1]
1527
n *= gens[i+1]
1528
## n %= mod
1529
i += 1
1530
1531
self.__values = result_list
1532
return self.__values
1533
1534
def values_on_gens(self):
1535
"""
1536
Returns a tuple of the values of this character on each of the
1537
minimal generators of `(\ZZ/N\ZZ)^*`, where
1538
`N` is the modulus.
1539
1540
EXAMPLES::
1541
1542
sage: e = DirichletGroup(16)([-1, 1])
1543
sage: e.values_on_gens ()
1544
(-1, 1)
1545
"""
1546
try:
1547
return self.__values_on_gens
1548
except AttributeError:
1549
pows = self.parent()._zeta_powers
1550
v = tuple([pows[i] for i in self.element()])
1551
self.__values_on_gens = v
1552
return v
1553
1554
def element(self):
1555
r"""
1556
Return the underlying `\ZZ/n\ZZ`-module
1557
vector of exponents.
1558
1559
.. warning::
1560
1561
Please do not change the entries of the returned vector;
1562
this vector is mutable *only* because immutable vectors are
1563
implemented yet.
1564
1565
EXAMPLE::
1566
1567
sage: G.<a,b> = DirichletGroup(20)
1568
sage: a.element()
1569
(2, 0)
1570
sage: b.element()
1571
(0, 1)
1572
"""
1573
try:
1574
return self.__element
1575
except AttributeError:
1576
P = self.parent()
1577
M = P._module
1578
dlog = P._zeta_dlog
1579
v = M([dlog[x] for x in self.values_on_gens()])
1580
self.__element = v
1581
return v
1582
1583
1584
_cache = {}
1585
def DirichletGroup(modulus, base_ring=None, zeta=None, zeta_order=None,
1586
names=None, integral=False):
1587
r"""
1588
The group of Dirichlet characters modulo `N` with values in
1589
the subgroup `\langle \zeta_n\rangle` of the
1590
multiplicative group of the ``base_ring``. If the
1591
base_ring is omitted then we use `\QQ(\zeta_n)`,
1592
where `n` is the exponent of
1593
`(\ZZ/N\ZZ)^*`. If `\zeta` is omitted
1594
then we compute and use a maximal-order zeta in base_ring, if
1595
possible.
1596
1597
INPUT:
1598
1599
1600
- ``modulus`` - int
1601
1602
- ``base_ring`` - Ring (optional), where characters
1603
take their values (should be an integral domain).
1604
1605
- ``zeta`` - Element (optional), element of
1606
base_ring; zeta is a root of unity
1607
1608
- ``zeta_order`` - int (optional), the order of zeta
1609
1610
- ``names`` - ignored (needed so G.... =
1611
DirichletGroup(...) notation works)
1612
1613
- ``integral`` - boolean (default:
1614
``False``). If ``True``, return the group
1615
with base_ring the ring of integers in the smallest choice of
1616
CyclotomicField. Ignored if base_ring is not
1617
``None``.
1618
1619
1620
OUTPUT:
1621
1622
1623
- ``DirichletGroup`` - a group of Dirichlet
1624
characters.
1625
1626
1627
EXAMPLES:
1628
1629
The default base ring is a cyclotomic field of order the exponent
1630
of `(\ZZ/N\ZZ)^*`.
1631
1632
::
1633
1634
sage: DirichletGroup(20)
1635
Group of Dirichlet characters of modulus 20 over Cyclotomic Field of order 4 and degree 2
1636
1637
We create the group of Dirichlet character mod 20 with values in
1638
the rational numbers::
1639
1640
sage: G = DirichletGroup(20, QQ); G
1641
Group of Dirichlet characters of modulus 20 over Rational Field
1642
sage: G.order()
1643
4
1644
sage: G.base_ring()
1645
Rational Field
1646
1647
The elements of G print as lists giving the values of the character
1648
on the generators of `(Z/NZ)^*`::
1649
1650
sage: list(G)
1651
[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]
1652
1653
Next we construct the group of Dirichlet character mod 20, but with
1654
values in Q(zeta_n)::
1655
1656
sage: G = DirichletGroup(20)
1657
sage: G.1
1658
Dirichlet character modulo 20 of conductor 5 mapping 11 |--> 1, 17 |--> zeta4
1659
1660
We next compute several invariants of G::
1661
1662
sage: G.gens()
1663
(Dirichlet character modulo 20 of conductor 4 mapping 11 |--> -1, 17 |--> 1, Dirichlet character modulo 20 of conductor 5 mapping 11 |--> 1, 17 |--> zeta4)
1664
sage: G.unit_gens()
1665
(11, 17)
1666
sage: G.zeta()
1667
zeta4
1668
sage: G.zeta_order()
1669
4
1670
1671
In this example we create a Dirichlet character with values in a
1672
number field. We have to give zeta, but not its order.
1673
1674
::
1675
1676
sage: R.<x> = PolynomialRing(QQ)
1677
sage: K.<a> = NumberField(x^4 + 1)
1678
sage: G = DirichletGroup(5, K, a); G
1679
Group of Dirichlet characters of modulus 5 over Number Field in a with defining polynomial x^4 + 1
1680
sage: G.list()
1681
[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]
1682
1683
::
1684
1685
sage: G.<e> = DirichletGroup(13)
1686
sage: loads(G.dumps()) == G
1687
True
1688
1689
::
1690
1691
sage: G = DirichletGroup(19, GF(5))
1692
sage: loads(G.dumps()) == G
1693
True
1694
1695
We compute a Dirichlet group over a large prime field.
1696
1697
::
1698
1699
sage: p = next_prime(10^40)
1700
sage: g = DirichletGroup(19, GF(p)); g
1701
Group of Dirichlet characters of modulus 19 over Finite Field of size 10000000000000000000000000000000000000121
1702
1703
Note that the root of unity has small order, i.e., it is not the
1704
largest order root of unity in the field.
1705
1706
::
1707
1708
sage: g.zeta_order()
1709
2
1710
1711
::
1712
1713
sage: r4 = CyclotomicField(4).ring_of_integers()
1714
sage: G = DirichletGroup(60, r4)
1715
sage: G.gens()
1716
(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)
1717
sage: val = G.gens()[2].values_on_gens()[2] ; val
1718
zeta4
1719
sage: parent(val)
1720
Maximal Order in Cyclotomic Field of order 4 and degree 2
1721
sage: r4.residue_field(r4.ideal(29).factor()[0][0])(val)
1722
17
1723
sage: r4.residue_field(r4.ideal(29).factor()[0][0])(val) * GF(29)(3)
1724
22
1725
sage: r4.residue_field(r4.ideal(29).factor()[0][0])(G.gens()[2].values_on_gens()[2]) * 3
1726
22
1727
sage: parent(r4.residue_field(r4.ideal(29).factor()[0][0])(G.gens()[2].values_on_gens()[2]) * 3)
1728
Residue field of Fractional ideal (-2*zeta4 + 5)
1729
1730
::
1731
1732
sage: DirichletGroup(60, integral=True)
1733
Group of Dirichlet characters of modulus 60 over Maximal Order in Cyclotomic Field of order 4 and degree 2
1734
sage: parent(DirichletGroup(60, integral=True).gens()[2].values_on_gens()[2])
1735
Maximal Order in Cyclotomic Field of order 4 and degree 2
1736
"""
1737
modulus = rings.Integer(modulus)
1738
1739
if base_ring is None:
1740
if not (zeta is None and zeta_order is None):
1741
raise ValueError, "zeta and zeta_order must be None if base_ring not specified."
1742
e = rings.IntegerModRing(modulus).unit_group_exponent()
1743
base_ring = rings.CyclotomicField(e)
1744
if integral:
1745
base_ring = base_ring.ring_of_integers()
1746
1747
if not is_Ring(base_ring):
1748
raise TypeError, "base_ring (=%s) must be a ring"%base_ring
1749
1750
if zeta is None:
1751
e = rings.IntegerModRing(modulus).unit_group_exponent()
1752
try:
1753
zeta = base_ring.zeta(e)
1754
zeta_order = zeta.multiplicative_order()
1755
except (TypeError, ValueError, ArithmeticError):
1756
zeta = base_ring.zeta(base_ring.zeta_order())
1757
n = zeta.multiplicative_order()
1758
zeta_order = arith.GCD(e,n)
1759
zeta = zeta**(n//zeta_order)
1760
1761
elif zeta_order is None:
1762
zeta_order = zeta.multiplicative_order()
1763
1764
key = (base_ring, modulus, zeta, zeta_order)
1765
if _cache.has_key(key):
1766
x = _cache[key]()
1767
if not x is None: return x
1768
1769
R = DirichletGroup_class(modulus, zeta, zeta_order)
1770
_cache[key] = weakref.ref(R)
1771
return R
1772
1773
def is_DirichletGroup(x):
1774
"""
1775
Returns True if x is a Dirichlet group.
1776
1777
EXAMPLES::
1778
1779
sage: from sage.modular.dirichlet import is_DirichletGroup
1780
sage: is_DirichletGroup(DirichletGroup(11))
1781
True
1782
sage: is_DirichletGroup(11)
1783
False
1784
sage: is_DirichletGroup(DirichletGroup(11).0)
1785
False
1786
"""
1787
return isinstance(x, DirichletGroup_class)
1788
1789
class DirichletGroup_class(parent_gens.ParentWithMultiplicativeAbelianGens):
1790
"""
1791
Group of Dirichlet characters modulo `N` over a given base
1792
ring `R`.
1793
"""
1794
def __init__(self, modulus, zeta, zeta_order):
1795
r"""
1796
Create a Dirichlet group. Not to be called directly (use the factory function ``DirichletGroup``.)
1797
1798
EXAMPLES::
1799
1800
sage: G = DirichletGroup(7, base_ring = Integers(9), zeta = Integers(9)(2)) # indirect doctest
1801
sage: G.base() # check that ParentWithBase.__init__ has been called
1802
Ring of integers modulo 9
1803
"""
1804
parent_gens.ParentWithMultiplicativeAbelianGens.__init__(self, zeta.parent())
1805
self._zeta = zeta
1806
self._zeta_order = int(zeta_order)
1807
self._modulus = modulus
1808
self._integers = rings.IntegerModRing(modulus)
1809
a = zeta.parent()(1)
1810
v = {a:0}
1811
w = [a]
1812
for i in range(1, self._zeta_order):
1813
a = a * zeta
1814
v[a] = i
1815
w.append(a)
1816
self._zeta_powers = w # gives quickly the ith power of zeta
1817
self._zeta_dlog = v # dictionary that computes log_{zeta}(power of zeta).
1818
self._module = free_module.FreeModule(rings.IntegerModRing(zeta_order),
1819
len(self._integers.unit_gens()))
1820
1821
def change_ring(self, R, zeta=None, zeta_order=None):
1822
"""
1823
Returns the Dirichlet group over R with the same modulus as self.
1824
1825
EXAMPLES::
1826
1827
sage: G = DirichletGroup(7,QQ); G
1828
Group of Dirichlet characters of modulus 7 over Rational Field
1829
sage: G.change_ring(CyclotomicField(6))
1830
Group of Dirichlet characters of modulus 7 over Cyclotomic Field of order 6 and degree 2
1831
"""
1832
return DirichletGroup(self.modulus(), R,
1833
zeta=zeta,
1834
zeta_order=zeta_order)
1835
1836
def base_extend(self, R):
1837
"""
1838
Returns the Dirichlet group over R obtained by extending scalars, with the same modulus and root of unity as self.
1839
1840
EXAMPLES::
1841
1842
sage: G = DirichletGroup(7,QQ); G
1843
Group of Dirichlet characters of modulus 7 over Rational Field
1844
sage: H = G.base_extend(CyclotomicField(6)); H
1845
Group of Dirichlet characters of modulus 7 over Cyclotomic Field of order 6 and degree 2
1846
sage: H.zeta()
1847
-1
1848
sage: G.base_extend(ZZ)
1849
Traceback (most recent call last):
1850
...
1851
TypeError: No coercion map from 'Rational Field' to 'Integer Ring' is defined.
1852
1853
"""
1854
if not R.has_coerce_map_from(self.base_ring()):
1855
raise TypeError, "No coercion map from '%s' to '%s' is defined." % (self.base_ring(), R)
1856
return DirichletGroup(self.modulus(), R, zeta=R(self.zeta()), zeta_order=self.zeta_order())
1857
1858
def __call__(self, x):
1859
"""
1860
Coerce x into this Dirichlet group.
1861
1862
EXAMPLES::
1863
1864
sage: G = DirichletGroup(13)
1865
sage: K = G.base_ring()
1866
sage: G(1)
1867
Dirichlet character modulo 13 of conductor 1 mapping 2 |--> 1
1868
sage: G([-1])
1869
Dirichlet character modulo 13 of conductor 13 mapping 2 |--> -1
1870
sage: G([K.0])
1871
Dirichlet character modulo 13 of conductor 13 mapping 2 |--> zeta12
1872
sage: G(0)
1873
Traceback (most recent call last):
1874
...
1875
TypeError: No coercion of 0 into Group of Dirichlet characters of modulus 13 over Cyclotomic Field of order 12 and degree 4 defined.
1876
"""
1877
if isinstance(x, (int,rings.Integer)) and x==1:
1878
R = self.base_ring()
1879
x = [R(1) for _ in self.unit_gens()]
1880
if isinstance(x, list): # list of values on each unit generator
1881
return DirichletCharacter(self, x)
1882
elif isinstance(x, DirichletCharacter): # coercion
1883
if x.parent() is self:
1884
return x
1885
elif x.parent() == self:
1886
return DirichletCharacter(self, x.values_on_gens())
1887
return self._coerce_in_dirichlet_character(x)
1888
raise TypeError, "No coercion of %s into %s defined."%(x, self)
1889
1890
def _coerce_in_dirichlet_character(self, x):
1891
r"""
1892
Create an element of this group from a Dirichlet character, whose
1893
conductor must divide the modulus of self.
1894
1895
EXAMPLES::
1896
1897
sage: G = DirichletGroup(6)
1898
sage: G._coerce_in_dirichlet_character(DirichletGroup(3).0)
1899
Dirichlet character modulo 6 of conductor 3 mapping 5 |--> -1
1900
sage: G._coerce_in_dirichlet_character(DirichletGroup(15).0)
1901
Dirichlet character modulo 6 of conductor 3 mapping 5 |--> -1
1902
sage: G._coerce_in_dirichlet_character(DirichletGroup(15).1)
1903
Traceback (most recent call last):
1904
...
1905
TypeError: conductor must divide modulus
1906
sage: H = DirichletGroup(16, QQ); H._coerce_in_dirichlet_character(DirichletGroup(16).1)
1907
Traceback (most recent call last):
1908
...
1909
ValueError: cannot coerce element of order 4 into self
1910
"""
1911
1912
if self.modulus() % x.conductor() != 0:
1913
raise TypeError, "conductor must divide modulus"
1914
elif not x.order().divides(self._zeta_order):
1915
raise ValueError, "cannot coerce element of order %s into self"%x.order()
1916
a = []
1917
R = self.base_ring()
1918
for u in self.unit_gens():
1919
v = u.lift()
1920
# have to do this, since e.g., unit gens mod 11 are not units mod 22.
1921
while arith.GCD(x.modulus(),int(v)) != 1:
1922
v += self.modulus()
1923
a.append(R(x(v)))
1924
return self(a)
1925
1926
def _coerce_impl(self, x):
1927
r"""
1928
Canonical coercion of x into self.
1929
1930
Note that although there is conversion between Dirichlet groups of
1931
different moduli, there is never canonical coercion. The main result of
1932
this is that Dirichlet characters of different moduli never compare as
1933
equal.
1934
1935
TESTS::
1936
1937
sage: trivial_character(6) == trivial_character(3) # indirect doctest
1938
False
1939
sage: trivial_character(3) == trivial_character(9)
1940
False
1941
sage: trivial_character(3) == DirichletGroup(3, QQ).0^2
1942
True
1943
"""
1944
if isinstance(x, DirichletCharacter) and self.modulus() == x.modulus() and \
1945
self.base_ring().has_coerce_map_from(x.base_ring()) and \
1946
self.zeta_order() % x.parent().zeta_order() == 0:
1947
return self._coerce_in_dirichlet_character(x)
1948
raise TypeError
1949
1950
def __cmp__(self, other):
1951
"""
1952
Compare two Dirichlet groups. They are equal if they have the same
1953
modulus, are over the same base ring, and have the same chosen root
1954
of unity. Otherwise we compare first on the modulus, then the base
1955
ring, and finally the root of unity.
1956
1957
EXAMPLES::
1958
1959
sage: DirichletGroup(13) == DirichletGroup(13)
1960
True
1961
sage: DirichletGroup(13) == DirichletGroup(13,QQ)
1962
False
1963
sage: DirichletGroup(11) < DirichletGroup(13,QQ)
1964
True
1965
sage: DirichletGroup(17) > DirichletGroup(13)
1966
True
1967
"""
1968
if not is_DirichletGroup(other):
1969
return -1
1970
c = cmp(self.modulus(), other.modulus())
1971
if c:
1972
return c
1973
c = cmp(self.base_ring(), other.base_ring())
1974
if c:
1975
return c
1976
c = cmp(self._zeta, other._zeta)
1977
if c:
1978
return c
1979
return 0
1980
1981
def __len__(self):
1982
"""
1983
Return the number of elements of this Dirichlet group. This is the
1984
same as self.order().
1985
1986
EXAMPLES::
1987
1988
sage: len(DirichletGroup(20))
1989
8
1990
sage: len(DirichletGroup(20, QQ))
1991
4
1992
sage: len(DirichletGroup(20, GF(5)))
1993
8
1994
sage: len(DirichletGroup(20, GF(2)))
1995
1
1996
sage: len(DirichletGroup(20, GF(3)))
1997
4
1998
"""
1999
return self.order()
2000
2001
def _repr_(self):
2002
"""
2003
Return a print representation of this group, which can be renamed.
2004
2005
EXAMPLES::
2006
2007
sage: G = DirichletGroup(11)
2008
sage: repr(G) # indirect doctest
2009
'Group of Dirichlet characters of modulus 11 over Cyclotomic Field of order 10 and degree 4'
2010
sage: G.rename('Dir(11)')
2011
sage: G
2012
Dir(11)
2013
"""
2014
return "Group of Dirichlet characters of modulus %s over %s"%\
2015
(self.modulus(),self.base_ring())
2016
2017
# Commented out base_ring since this class should inherit base_ring from superclass ParentWithBase.
2018
# -- David Loeffler, 2009-04-09.
2019
#
2020
# def base_ring(self):
2021
# """
2022
# Returns the base ring of self.
2023
#
2024
# EXAMPLES::
2025
#
2026
# sage: DirichletGroup(11).base_ring()
2027
# Cyclotomic Field of order 10 and degree 4
2028
# sage: DirichletGroup(11,QQ).base_ring()
2029
# Rational Field
2030
# sage: DirichletGroup(11,GF(7)).base_ring()
2031
# Finite Field of size 7
2032
# sage: DirichletGroup(20).base_ring()
2033
# Cyclotomic Field of order 4 and degree 2
2034
# """
2035
# return self._zeta.parent()
2036
2037
@cached_method
2038
def decomposition(self):
2039
r"""
2040
Returns the Dirichlet groups of prime power modulus corresponding
2041
to primes dividing modulus.
2042
2043
(Note that if the modulus is 2 mod 4, there will be a "factor" of
2044
`(\ZZ/2\ZZ)^*`, which is the trivial group.)
2045
2046
EXAMPLES::
2047
2048
sage: DirichletGroup(20).decomposition()
2049
[
2050
Group of Dirichlet characters of modulus 4 over Cyclotomic Field of order 4 and degree 2,
2051
Group of Dirichlet characters of modulus 5 over Cyclotomic Field of order 4 and degree 2
2052
]
2053
sage: DirichletGroup(20,GF(5)).decomposition()
2054
[
2055
Group of Dirichlet characters of modulus 4 over Finite Field of size 5,
2056
Group of Dirichlet characters of modulus 5 over Finite Field of size 5
2057
]
2058
"""
2059
R = self.base_ring()
2060
return Sequence([DirichletGroup(p**r,R) for p, r \
2061
in arith.factor(self.modulus())],
2062
cr=True,
2063
universe = cat.Objects())
2064
2065
def exponent(self):
2066
"""
2067
Return the exponent of this group.
2068
2069
EXAMPLES::
2070
2071
sage: DirichletGroup(20).exponent()
2072
4
2073
sage: DirichletGroup(20,GF(3)).exponent()
2074
2
2075
sage: DirichletGroup(20,GF(2)).exponent()
2076
1
2077
sage: DirichletGroup(37).exponent()
2078
36
2079
"""
2080
return self._zeta_order
2081
2082
@cached_method
2083
def _automorphisms(self):
2084
"""
2085
Compute the automorphisms of self. These are always given by raising to
2086
a power, so the return value is a list of integers.
2087
2088
At present this is only implemented if the base ring has characteristic 0 or a prime.
2089
2090
EXAMPLES::
2091
2092
sage: DirichletGroup(17)._automorphisms()
2093
[1, 3, 5, 7, 9, 11, 13, 15]
2094
sage: DirichletGroup(17, GF(11^4, 'a'))._automorphisms()
2095
[1, 11, 121, 1331]
2096
sage: DirichletGroup(17, Integers(6), zeta=Integers(6)(5))._automorphisms()
2097
Traceback (most recent call last):
2098
...
2099
NotImplementedError: Automorphisms for finite non-field base rings not implemented
2100
sage: DirichletGroup(17, Integers(9), zeta=Integers(9)(2))._automorphisms()
2101
Traceback (most recent call last):
2102
...
2103
NotImplementedError: Automorphisms for finite non-field base rings not implemented
2104
"""
2105
n = self.zeta_order()
2106
R = self.base_ring()
2107
p = R.characteristic()
2108
if p == 0:
2109
Auts = [e for e in xrange(1,n) if arith.GCD(e,n) == 1]
2110
else:
2111
if not rings.ZZ(p).is_prime():
2112
raise NotImplementedError, "Automorphisms for finite non-field base rings not implemented"
2113
# The automorphisms in characteristic p are
2114
# k-th powering for
2115
# k = 1, p, p^2, ..., p^(r-1),
2116
# where p^r = 1 (mod n), so r is the mult order of p modulo n.
2117
r = rings.IntegerModRing(n)(p).multiplicative_order()
2118
Auts = [p**m for m in xrange(0,r)]
2119
return Auts
2120
2121
def galois_orbits(self, v=None, reps_only=False, sort=True, check=True):
2122
"""
2123
Return a list of the Galois orbits of Dirichlet characters in self,
2124
or in v if v is not None.
2125
2126
INPUT:
2127
2128
2129
- ``v`` - (optional) list of elements of self
2130
2131
- ``reps_only`` - (optional: default False) if True
2132
only returns representatives for the orbits.
2133
2134
- ``sort`` - (optional: default True) whether to sort
2135
the list of orbits and the orbits themselves (slightly faster if
2136
False).
2137
2138
- ``check`` - (optional, default: True) whether or not
2139
to explicitly coerce each element of v into self.
2140
2141
2142
The Galois group is the absolute Galois group of the prime subfield
2143
of Frac(R). If R is not a domain, an error will be raised.
2144
2145
EXAMPLES::
2146
2147
sage: DirichletGroup(20).galois_orbits()
2148
[
2149
[Dirichlet character modulo 20 of conductor 1 mapping 11 |--> 1, 17 |--> 1], ... [Dirichlet character modulo 20 of conductor 20 mapping 11 |--> -1, 17 |--> -1]
2150
]
2151
sage: DirichletGroup(17, Integers(6), zeta=Integers(6)(5)).galois_orbits()
2152
Traceback (most recent call last):
2153
...
2154
TypeError: Galois orbits only defined if base ring is an integral domain
2155
sage: DirichletGroup(17, Integers(9), zeta=Integers(9)(2)).galois_orbits()
2156
Traceback (most recent call last):
2157
...
2158
TypeError: Galois orbits only defined if base ring is an integral domain
2159
"""
2160
2161
if v is None:
2162
v = self.list()
2163
else:
2164
if check:
2165
v = [self(x) for x in v]
2166
2167
G = []
2168
n = self.zeta_order()
2169
R = self.base_ring()
2170
p = R.characteristic()
2171
seen_so_far = set([])
2172
for x in v:
2173
z = x.element()
2174
e = tuple(z) # change when there are immutable vectors (and below)
2175
if e in seen_so_far:
2176
continue
2177
orbit = x.galois_orbit(sort=sort)
2178
if reps_only:
2179
G.append(x)
2180
else:
2181
G.append(orbit)
2182
for z in orbit:
2183
seen_so_far.add(tuple(z.element()))
2184
G = Sequence(G, cr=True)
2185
if sort:
2186
G.sort()
2187
return G
2188
2189
def gen(self, n=0):
2190
"""
2191
Return the n-th generator of self.
2192
2193
EXAMPLES::
2194
2195
sage: G = DirichletGroup(20)
2196
sage: G.gen(0)
2197
Dirichlet character modulo 20 of conductor 4 mapping 11 |--> -1, 17 |--> 1
2198
sage: G.gen(1)
2199
Dirichlet character modulo 20 of conductor 5 mapping 11 |--> 1, 17 |--> zeta4
2200
sage: G.gen(2)
2201
Traceback (most recent call last):
2202
...
2203
IndexError: n(=2) must be between 0 and 1
2204
2205
::
2206
2207
sage: G.gen(-1)
2208
Traceback (most recent call last):
2209
...
2210
IndexError: n(=-1) must be between 0 and 1
2211
"""
2212
n = int(n)
2213
g = self.gens()
2214
if n<0 or n>=len(g):
2215
raise IndexError, "n(=%s) must be between 0 and %s"%(n,len(g)-1)
2216
return g[n]
2217
2218
def gens(self):
2219
"""
2220
Returns generators of self.
2221
2222
EXAMPLES::
2223
2224
sage: G = DirichletGroup(20)
2225
sage: G.gens()
2226
(Dirichlet character modulo 20 of conductor 4 mapping 11 |--> -1, 17 |--> 1, Dirichlet character modulo 20 of conductor 5 mapping 11 |--> 1, 17 |--> zeta4)
2227
"""
2228
if not (self._gens is None):
2229
return self._gens
2230
self._gens = []
2231
ug = self.unit_gens()
2232
R = self.base_ring()
2233
one = [R(1) for i in range(len(ug))]
2234
zeta = self.zeta()
2235
ord = self.zeta_order()
2236
M = self._module
2237
zero = M(0)
2238
for i in range(len(ug)):
2239
z = zero.__copy__()
2240
z[i] = ord//arith.GCD(ord,ug[i].multiplicative_order())
2241
#vals = list(one)
2242
#vals[i] = zeta**(ord//arith.GCD(ord,ug[i].multiplicative_order()))
2243
#vals[i] = ord//arith.GCD(ord,ug[i].multiplicative_order())
2244
self._gens.append(DirichletCharacter(self, z, check=False))
2245
self._gens = tuple(self._gens)
2246
return self._gens
2247
2248
def integers_mod(self):
2249
r"""
2250
Returns the group of integers `\ZZ/N\ZZ`
2251
where `N` is the modulus of self.
2252
2253
EXAMPLES::
2254
2255
sage: G = DirichletGroup(20)
2256
sage: G.integers_mod()
2257
Ring of integers modulo 20
2258
"""
2259
return self._integers
2260
2261
def modulus(self):
2262
"""
2263
Returns the modulus of self.
2264
2265
EXAMPLES::
2266
2267
sage: G = DirichletGroup(20)
2268
sage: G.modulus()
2269
20
2270
"""
2271
return self._modulus
2272
2273
def ngens(self):
2274
"""
2275
Returns the number of generators of self.
2276
2277
EXAMPLES::
2278
2279
sage: G = DirichletGroup(20)
2280
sage: G.ngens()
2281
2
2282
"""
2283
return len(self.gens())
2284
2285
@cached_method
2286
def order(self):
2287
"""
2288
Return the number of elements of self. This is the same as
2289
len(self).
2290
2291
EXAMPLES::
2292
2293
sage: DirichletGroup(20).order()
2294
8
2295
sage: DirichletGroup(37).order()
2296
36
2297
"""
2298
ord = rings.Integer(1)
2299
for g in self.gens():
2300
ord *= int(g.order())
2301
return ord
2302
2303
def random_element(self):
2304
"""
2305
Return a random element of self.
2306
2307
The element is computed by multiplying a random power of each
2308
generator together, where the power is between 0 and the order of
2309
the generator minus 1, inclusive.
2310
2311
EXAMPLES::
2312
2313
sage: DirichletGroup(37).random_element()
2314
Dirichlet character modulo 37 of conductor 37 mapping 2 |--> zeta36^4
2315
sage: DirichletGroup(20).random_element()
2316
Dirichlet character modulo 20 of conductor 4 mapping 11 |--> -1, 17 |--> 1
2317
sage: DirichletGroup(60).random_element()
2318
Dirichlet character modulo 60 of conductor 3 mapping 31 |--> 1, 41 |--> -1, 37 |--> 1
2319
"""
2320
e = self(1)
2321
for i in range(self.ngens()):
2322
g = self.gen(i)
2323
n = random.randrange(g.order())
2324
e *= g**n
2325
return e
2326
2327
def unit_gens(self):
2328
r"""
2329
Returns the minimal generators for the units of
2330
`(\ZZ/N\ZZ)^*`, where `N` is the
2331
modulus of self.
2332
2333
EXAMPLES::
2334
2335
sage: DirichletGroup(37).unit_gens()
2336
(2,)
2337
sage: DirichletGroup(20).unit_gens()
2338
(11, 17)
2339
sage: DirichletGroup(60).unit_gens()
2340
(31, 41, 37)
2341
sage: DirichletGroup(20,QQ).unit_gens()
2342
(11, 17)
2343
"""
2344
return self._integers.unit_gens()
2345
2346
def zeta(self):
2347
"""
2348
Returns the chosen root zeta of unity in the base ring
2349
`R`.
2350
2351
EXAMPLES::
2352
2353
sage: DirichletGroup(37).zeta()
2354
zeta36
2355
sage: DirichletGroup(20).zeta()
2356
zeta4
2357
sage: DirichletGroup(60).zeta()
2358
zeta4
2359
sage: DirichletGroup(60,QQ).zeta()
2360
-1
2361
sage: DirichletGroup(60, GF(25,'a')).zeta()
2362
2
2363
"""
2364
return self._zeta
2365
2366
def zeta_order(self):
2367
"""
2368
Returns the order of the chosen root zeta of unity in the base ring
2369
`R`.
2370
2371
EXAMPLES::
2372
2373
sage: DirichletGroup(20).zeta_order()
2374
4
2375
sage: DirichletGroup(60).zeta_order()
2376
4
2377
sage: DirichletGroup(60, GF(25,'a')).zeta_order()
2378
4
2379
sage: DirichletGroup(19).zeta_order()
2380
18
2381
"""
2382
return self._zeta_order
2383
2384
2385
2386
2387
2388