Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemath
GitHub Repository: sagemath/sagesmc
Path: blob/master/src/sage/modular/arithgroup/arithgroup_element.pyx
8821 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 cimport MultiplicativeGroupElement, MonoidElement, Element
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
from sage.modular.cusps import Cusp
22
23
M2Z = matrix.MatrixSpace(ZZ,2)
24
25
cdef class ArithmeticSubgroupElement(MultiplicativeGroupElement):
26
r"""
27
An element of the group `{\rm SL}_2(\ZZ)`, i.e. a 2x2 integer matrix of
28
determinant 1.
29
"""
30
31
cdef object __x
32
33
def __init__(self, parent, x, check=True):
34
"""
35
Create an element of an arithmetic subgroup.
36
37
INPUT:
38
39
- ``parent`` -- an arithmetic subgroup
40
41
- `x` -- data defining a 2x2 matrix over ZZ
42
which lives in parent
43
44
- ``check`` -- if True, check that parent is an arithmetic
45
subgroup, and that `x` defines a matrix of
46
determinant `1`.
47
48
We tend not to create elements of arithmetic subgroups that aren't
49
SL2Z, in order to avoid coercion issues (that is, the other arithmetic
50
subgroups are "facade parents").
51
52
EXAMPLES::
53
54
sage: G = Gamma0(27)
55
sage: sage.modular.arithgroup.arithgroup_element.ArithmeticSubgroupElement(G, [4,1,27,7])
56
[ 4 1]
57
[27 7]
58
sage: sage.modular.arithgroup.arithgroup_element.ArithmeticSubgroupElement(Integers(3), [4,1,27,7])
59
Traceback (most recent call last):
60
...
61
TypeError: parent (= Ring of integers modulo 3) must be an arithmetic subgroup
62
sage: sage.modular.arithgroup.arithgroup_element.ArithmeticSubgroupElement(G, [2,0,0,2])
63
Traceback (most recent call last):
64
...
65
TypeError: matrix must have determinant 1
66
sage: sage.modular.arithgroup.arithgroup_element.ArithmeticSubgroupElement(G, [2,0,0,2], check=False)
67
[2 0]
68
[0 2]
69
sage: x = Gamma0(11)([2,1,11,6])
70
sage: TestSuite(x).run()
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
from all import is_ArithmeticSubgroup
81
if not is_ArithmeticSubgroup(parent):
82
raise TypeError, "parent (= %s) must be an arithmetic subgroup"%parent
83
84
x = mi2x2(M2Z, x, copy=True, coerce=True)
85
if x.determinant() != 1:
86
raise TypeError, "matrix must have determinant 1"
87
else:
88
x = mi2x2(M2Z, x, copy=True, coerce=False)
89
# Getting rid of this would result in a small speed gain for
90
# arithmetic operations, but it would have the disadvantage of
91
# causing strange and opaque errors when inappropriate data types
92
# are used with "check=False".
93
94
x.set_immutable()
95
MultiplicativeGroupElement.__init__(self, parent)
96
self.__x = x
97
98
def __setstate__(self, state):
99
r"""
100
For unpickling objects pickled with the old ArithmeticSubgroupElement class.
101
102
EXAMPLE::
103
104
sage: si = unpickle_newobj(sage.modular.arithgroup.arithgroup_element.ArithmeticSubgroupElement, ())
105
sage: x = sage.matrix.matrix_integer_2x2.Matrix_integer_2x2(MatrixSpace(ZZ, 2), [1,1,0,1], copy=True, coerce=True)
106
sage: unpickle_build(si, (Gamma0(13), {'_ArithmeticSubgroupElement__x': x}))
107
"""
108
from all import SL2Z
109
oldparent, kwdict = state
110
self._set_parent(SL2Z)
111
if kwdict.has_key('_ArithmeticSubgroupElement__x'):
112
self.__x = kwdict['_ArithmeticSubgroupElement__x']
113
elif kwdict.has_key('_CongruenceSubgroupElement__x'):
114
self.__x = kwdict['_CongruenceSubgroupElement__x']
115
else:
116
raise ValueError, "Don't know how to unpickle %s" % repr(state)
117
118
def __iter__(self):
119
"""
120
EXAMPLES::
121
122
sage: Gamma0(2).0
123
[1 1]
124
[0 1]
125
sage: list(Gamma0(2).0)
126
[1, 1, 0, 1]
127
"""
128
return iter(self.__x)
129
130
def __repr__(self):
131
"""
132
Return the string representation of self.
133
134
EXAMPLES::
135
136
sage: Gamma1(5)([6,1,5,1]).__repr__()
137
'[6 1]\n[5 1]'
138
"""
139
return "%s"%self.__x
140
141
def _latex_(self):
142
"""
143
Return latex representation of self.
144
145
EXAMPLES::
146
147
sage: Gamma1(5)([6,1,5,1])._latex_()
148
'\\left(\\begin{array}{rr}\n6 & 1 \\\\\n5 & 1\n\\end{array}\\right)'
149
"""
150
return '%s' % self.__x._latex_()
151
152
def __richcmp__(left, right, int op):
153
r"""
154
Rich comparison.
155
156
EXAMPLE::
157
158
sage: SL2Z.0 > None
159
True
160
"""
161
return (<Element>left)._richcmp(right, op)
162
163
cdef int _cmp_c_impl(self, Element right_r) except -2:
164
"""
165
Compare self to right, where right is guaranteed to have the same
166
parent as self.
167
168
EXAMPLES::
169
170
sage: x = Gamma0(18)([19,1,18,1])
171
sage: cmp(x, 3) is not 0
172
True
173
sage: cmp(x, x)
174
0
175
176
sage: x = Gamma0(5)([1,1,0,1])
177
sage: x == 0
178
False
179
180
This once caused a segfault (see trac #5443)::
181
182
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]])
183
sage: v == s*u
184
True
185
sage: s*u == v
186
True
187
"""
188
cdef ArithmeticSubgroupElement right = <ArithmeticSubgroupElement>right_r
189
return cmp(self.__x, right.__x)
190
191
def __nonzero__(self):
192
"""
193
Return True, since the self lives in SL(2,\Z), which does not
194
contain the zero matrix.
195
196
EXAMPLES::
197
198
sage: x = Gamma0(5)([1,1,0,1])
199
sage: x.__nonzero__()
200
True
201
"""
202
return True
203
204
cpdef MonoidElement _mul_(self, MonoidElement right):
205
"""
206
Return self * right.
207
208
EXAMPLES::
209
210
sage: x = Gamma0(7)([1,0,7,1]) * Gamma0(7)([3,2,7,5]) ; x # indirect doctest
211
[ 3 2]
212
[28 19]
213
sage: x.parent()
214
Modular Group SL(2,Z)
215
216
We check that #5048 is fixed::
217
218
sage: a = Gamma0(10).1 * Gamma0(5).2; a # random
219
sage: a.parent()
220
Modular Group SL(2,Z)
221
222
"""
223
return self.__class__(self.parent(), self.__x * (<ArithmeticSubgroupElement> right).__x, check=False)
224
225
def __invert__(self):
226
"""
227
Return the inverse of self.
228
229
EXAMPLES::
230
231
sage: Gamma0(11)([1,-1,0,1]).__invert__()
232
[1 1]
233
[0 1]
234
"""
235
I = mi2x2(M2Z, [self.__x[1,1], -self.__x[0,1], -self.__x[1,0], self.__x[0,0]], copy=True, coerce=True)
236
return self.parent()(I, check=False)
237
238
def matrix(self):
239
"""
240
Return the matrix corresponding to self.
241
242
EXAMPLES::
243
244
sage: x = Gamma1(3)([4,5,3,4]) ; x
245
[4 5]
246
[3 4]
247
sage: x.matrix()
248
[4 5]
249
[3 4]
250
sage: type(x.matrix())
251
<type 'sage.matrix.matrix_integer_2x2.Matrix_integer_2x2'>
252
"""
253
return self.__x
254
255
def determinant(self):
256
"""
257
Return the determinant of self, which is always 1.
258
259
EXAMPLES::
260
261
sage: Gamma0(691)([1,0,691,1]).determinant()
262
1
263
"""
264
return ZZ(1)
265
266
def det(self):
267
"""
268
Return the determinant of self, which is always 1.
269
270
EXAMPLES::
271
272
sage: Gamma1(11)([12,11,-11,-10]).det()
273
1
274
"""
275
return self.determinant()
276
277
def a(self):
278
"""
279
Return the upper left entry of self.
280
281
EXAMPLES::
282
283
sage: Gamma0(13)([7,1,13,2]).a()
284
7
285
"""
286
return self.__x[0,0]
287
288
def b(self):
289
"""
290
Return the upper right entry of self.
291
292
EXAMPLES::
293
294
sage: Gamma0(13)([7,1,13,2]).b()
295
1
296
"""
297
return self.__x[0,1]
298
299
def c(self):
300
"""
301
Return the lower left entry of self.
302
303
EXAMPLES::
304
305
sage: Gamma0(13)([7,1,13,2]).c()
306
13
307
"""
308
return self.__x[1,0]
309
310
def d(self):
311
"""
312
Return the lower right entry of self.
313
314
EXAMPLES::
315
316
sage: Gamma0(13)([7,1,13,2]).d()
317
2
318
"""
319
return self.__x[1,1]
320
321
def acton(self, z):
322
"""
323
Return the result of the action of self on z as a fractional linear
324
transformation.
325
326
EXAMPLES::
327
328
sage: G = Gamma0(15)
329
sage: g = G([1, 2, 15, 31])
330
331
An example of g acting on a symbolic variable::
332
333
sage: z = var('z')
334
sage: g.acton(z)
335
(z + 2)/(15*z + 31)
336
337
An example involving the Gaussian numbers::
338
339
sage: K.<i> = NumberField(x^2 + 1)
340
sage: g.acton(i)
341
1/1186*i + 77/1186
342
343
An example with complex numbers::
344
345
sage: C.<i> = ComplexField()
346
sage: g.acton(i)
347
0.0649241146711636 + 0.000843170320404721*I
348
349
An example with the cusp infinity::
350
351
sage: g.acton(infinity)
352
1/15
353
354
An example which maps a finite cusp to infinity::
355
356
sage: g.acton(-31/15)
357
+Infinity
358
359
Note that when acting on instances of cusps the return value
360
is still a rational number or infinity (Note the presence of
361
'+', which does not show up for cusp instances)::
362
363
sage: g.acton(Cusp(-31/15))
364
+Infinity
365
366
TESTS:
367
368
We cover the remaining case, i.e., infinity mapped to infinity::
369
370
sage: G([1, 4, 0, 1]).acton(infinity)
371
+Infinity
372
373
"""
374
from sage.rings.infinity import is_Infinite, infinity
375
if is_Infinite(z):
376
if self.__x[1,0] != 0:
377
return self.__x[0,0]/self.__x[1,0]
378
else:
379
return infinity
380
if hasattr(z, 'denominator') and hasattr(z, 'numerator'):
381
p, q = z.numerator(), z.denominator()
382
P = self.__x[0,0]*p+self.__x[0,1]*q
383
Q = self.__x[1,0]*p+self.__x[1,1]*q
384
if Q == 0 and P != 0:
385
return infinity
386
else:
387
return P/Q
388
return (self.__x[0,0]*z + self.__x[0,1])/(self.__x[1,0]*z + self.__x[1,1])
389
390
def __getitem__(self, q):
391
r"""
392
Fetch entries by direct indexing.
393
394
EXAMPLE::
395
sage: SL2Z([3,2,1,1])[0,0]
396
3
397
"""
398
return self.__x[q]
399
400
def __hash__(self):
401
r"""
402
Return a hash value.
403
404
EXAMPLE::
405
406
sage: hash(SL2Z.0)
407
-4
408
"""
409
return hash(self.__x)
410
411
def __reduce__(self):
412
r"""
413
Used for pickling.
414
415
EXAMPLE::
416
417
sage: (SL2Z.1).__reduce__()
418
(Modular Group SL(2,Z), ([1 1]
419
[0 1],))
420
"""
421
from all import SL2Z
422
return SL2Z, (self.__x,)
423
424