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