Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemath
GitHub Repository: sagemath/sagelib
Path: blob/master/sage/modular/arithgroup/arithgroup_element.py
4054 views
1
"""
2
Elements of Arithmetic Subgroups
3
"""
4
5
################################################################################
6
#
7
# Copyright (C) 2009, The Sage Group -- http://www.sagemath.org/
8
#
9
# Distributed under the terms of the GNU General Public License (GPL)
10
#
11
# The full text of the GPL is available at:
12
#
13
# http://www.gnu.org/licenses/
14
#
15
################################################################################
16
17
from sage.structure.element import MultiplicativeGroupElement
18
from sage.rings.all import ZZ
19
import sage.matrix.all as matrix
20
from sage.matrix.matrix_integer_2x2 import Matrix_integer_2x2 as mi2x2
21
22
from all import is_ArithmeticSubgroup
23
24
M2Z = matrix.MatrixSpace(ZZ,2)
25
26
class ArithmeticSubgroupElement(MultiplicativeGroupElement):
27
r"""
28
An element of the group `{\rm SL}_2(\ZZ)`, i.e. a 2x2 integer matrix of
29
determinant 1.
30
"""
31
32
def __init__(self, parent, x, check=True):
33
"""
34
Create an element of an arithmetic subgroup.
35
36
INPUT:
37
38
- parent - an arithmetic subgroup
39
40
- x - data defining a 2x2 matrix over ZZ
41
which lives in parent
42
43
- check - if True, check that parent
44
is an arithmetic subgroup, and that
45
x defines a matrix of determinant 1
46
47
We tend not to create elements of arithmetic subgroups that aren't
48
SL2Z, in order to avoid coercion issues (that is, the other arithmetic
49
subgroups are "facade parents").
50
51
EXAMPLES::
52
53
sage: G = Gamma0(27)
54
sage: sage.modular.arithgroup.arithgroup_element.ArithmeticSubgroupElement(G, [4,1,27,7])
55
[ 4 1]
56
[27 7]
57
sage: sage.modular.arithgroup.arithgroup_element.ArithmeticSubgroupElement(Integers(3), [4,1,27,7])
58
Traceback (most recent call last):
59
...
60
TypeError: parent (= Ring of integers modulo 3) must be an arithmetic subgroup
61
sage: sage.modular.arithgroup.arithgroup_element.ArithmeticSubgroupElement(G, [2,0,0,2])
62
Traceback (most recent call last):
63
...
64
TypeError: matrix must have determinant 1
65
sage: sage.modular.arithgroup.arithgroup_element.ArithmeticSubgroupElement(G, [2,0,0,2], check=False)
66
[2, 0, 0, 2]
67
68
sage: x = Gamma0(11)([2,1,11,6])
69
sage: x == loads(dumps(x))
70
True
71
72
sage: x = Gamma0(5).0
73
sage: SL2Z(x)
74
[1 1]
75
[0 1]
76
sage: x in SL2Z
77
True
78
"""
79
if check:
80
if not is_ArithmeticSubgroup(parent):
81
raise TypeError, "parent (= %s) must be an arithmetic subgroup"%parent
82
83
x = mi2x2(M2Z, x, copy=True, coerce=True)
84
if x.determinant() != 1:
85
raise TypeError, "matrix must have determinant 1"
86
87
try:
88
x.set_immutable()
89
except AttributeError:
90
pass
91
92
MultiplicativeGroupElement.__init__(self, parent)
93
self.__x = x
94
95
def __iter__(self):
96
"""
97
EXAMPLES::
98
99
sage: Gamma0(2).0
100
[1 1]
101
[0 1]
102
sage: list(Gamma0(2).0)
103
[1, 1, 0, 1]
104
"""
105
return iter(self.__x)
106
107
def __repr__(self):
108
"""
109
Return the string representation of self.
110
111
EXAMPLES::
112
113
sage: Gamma1(5)([6,1,5,1]).__repr__()
114
'[6 1]\n[5 1]'
115
"""
116
return "%s"%self.__x
117
118
def __cmp__(self, right):
119
"""
120
Compare self to right.
121
122
EXAMPLES::
123
124
sage: x = Gamma0(18)([19,1,18,1])
125
sage: x.__cmp__(3) is not 0
126
True
127
sage: x.__cmp__(x)
128
0
129
130
sage: x = Gamma0(5)([1,1,0,1])
131
sage: x == 0
132
False
133
134
This once caused a segfault (see trac #5443)::
135
136
sage: r,s,t,u,v = map(SL2Z, [[1, 1, 0, 1], [-1, 0, 0, -1], [1, -1, 0, 1], [1, -1, 2, -1], [-1, 1, -2, 1]])
137
sage: v == s*u
138
True
139
sage: s*u == v
140
True
141
"""
142
from sage.misc.functional import parent
143
if parent(self) != parent(right):
144
return cmp(type(self), type(right))
145
else:
146
return cmp(self.__x, right.__x)
147
148
def __nonzero__(self):
149
"""
150
Return True, since the self lives in SL(2,\Z), which does not
151
contain the zero matrix.
152
153
EXAMPLES::
154
155
sage: x = Gamma0(5)([1,1,0,1])
156
sage: x.__nonzero__()
157
True
158
"""
159
return True
160
161
def _mul_(self, right):
162
"""
163
Return self * right.
164
165
EXAMPLES::
166
167
sage: x = Gamma0(7)([1,0,7,1]) * Gamma0(7)([3,2,7,5]) ; x # indirect doctest
168
[ 3 2]
169
[28 19]
170
sage: x.parent()
171
Modular Group SL(2,Z)
172
173
We check that #5048 is fixed::
174
175
sage: a = Gamma0(10).1 * Gamma0(5).2; a # random
176
sage: a.parent()
177
Modular Group SL(2,Z)
178
179
"""
180
return self.parent()(self.__x * right.__x, check=False)
181
182
def __invert__(self):
183
"""
184
Return the inverse of self.
185
186
EXAMPLES::
187
188
sage: Gamma0(11)([1,-1,0,1]).__invert__()
189
[1 1]
190
[0 1]
191
"""
192
I = mi2x2(M2Z, [self.__x[1,1], -self.__x[0,1], -self.__x[1,0], self.__x[0,0]], copy=True, coerce=True)
193
return self.parent()(I, check=False)
194
195
def matrix(self):
196
"""
197
Return the matrix corresponding to self.
198
199
EXAMPLES::
200
201
sage: x = Gamma1(3)([4,5,3,4]) ; x
202
[4 5]
203
[3 4]
204
sage: x.matrix()
205
[4 5]
206
[3 4]
207
sage: type(x.matrix())
208
<type 'sage.matrix.matrix_integer_2x2.Matrix_integer_2x2'>
209
"""
210
return self.__x
211
212
def determinant(self):
213
"""
214
Return the determinant of self, which is always 1.
215
216
EXAMPLES::
217
218
sage: Gamma0(691)([1,0,691,1]).determinant()
219
1
220
"""
221
return ZZ(1)
222
223
def det(self):
224
"""
225
Return the determinant of self, which is always 1.
226
227
EXAMPLES::
228
229
sage: Gamma1(11)([12,11,-11,-10]).det()
230
1
231
"""
232
return self.determinant()
233
234
def a(self):
235
"""
236
Return the upper left entry of self.
237
238
EXAMPLES::
239
240
sage: Gamma0(13)([7,1,13,2]).a()
241
7
242
"""
243
return self.__x[0,0]
244
245
def b(self):
246
"""
247
Return the upper right entry of self.
248
249
EXAMPLES::
250
251
sage: Gamma0(13)([7,1,13,2]).b()
252
1
253
"""
254
return self.__x[0,1]
255
256
def c(self):
257
"""
258
Return the lower left entry of self.
259
260
EXAMPLES::
261
262
sage: Gamma0(13)([7,1,13,2]).c()
263
13
264
"""
265
return self.__x[1,0]
266
267
def d(self):
268
"""
269
Return the lower right entry of self.
270
271
EXAMPLES::
272
273
sage: Gamma0(13)([7,1,13,2]).d()
274
2
275
"""
276
return self.__x[1,1]
277
278
def acton(self, z):
279
"""
280
Return the result of the action of self on z as a fractional linear
281
transformation.
282
283
EXAMPLES::
284
285
sage: G = Gamma0(15)
286
sage: g = G([1, 2, 15, 31])
287
288
An example of g acting on a symbolic variable::
289
290
sage: z = var('z')
291
sage: g.acton(z)
292
(z + 2)/(15*z + 31)
293
294
An example involving the Gaussian numbers::
295
296
sage: K.<i> = NumberField(x^2 + 1)
297
sage: g.acton(i)
298
1/1186*i + 77/1186
299
300
An example with complex numbers::
301
302
sage: C.<i> = ComplexField()
303
sage: g.acton(i)
304
0.0649241146711636 + 0.000843170320404721*I
305
"""
306
return (self.__x[0,0]*z + self.__x[0,1])/(self.__x[1,0]*z + self.__x[1,1])
307
308
309
def __getitem__(self, q):
310
r"""
311
Fetch entries by direct indexing.
312
313
EXAMPLE::
314
sage: SL2Z([3,2,1,1])[0,0]
315
3
316
"""
317
return self.__x[q]
318
319