# HG changeset patch
# User David Loeffler <d.loeffler.01@cantab.net>
# Date 1291928574 0
# Node ID f45efdbe8d70cce32eb1b68adcc4258309a23932
# Parent 7f73030ab02b9425e645b7abd5a711b1ebb5f5b5
#5048: fix coercion issues with elements of congruence subgroups
diff -r 7f73030ab02b -r f45efdbe8d70 sage/modular/arithgroup/arithgroup_element.py
a
|
b
|
|
25 | 25 | |
26 | 26 | class ArithmeticSubgroupElement(MultiplicativeGroupElement): |
27 | 27 | r""" |
28 | | An element of an arithmetic subgroup of `{\rm SL}_2(\ZZ)`. |
| 28 | An element of the group `{\rm SL}_2(\ZZ)`, i.e. a 2x2 integer matrix of |
| 29 | determinant 1. |
29 | 30 | """ |
30 | 31 | |
31 | 32 | def __init__(self, parent, x, check=True): |
… |
… |
|
33 | 34 | Create an element of an arithmetic subgroup. |
34 | 35 | |
35 | 36 | INPUT: |
| 37 | |
36 | 38 | - parent - an arithmetic subgroup |
37 | 39 | |
38 | 40 | - x - data defining a 2x2 matrix over ZZ |
… |
… |
|
42 | 44 | is an arithmetic subgroup, and that |
43 | 45 | x defines a matrix of determinant 1 |
44 | 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 | |
45 | 51 | EXAMPLES:: |
46 | 52 | |
47 | 53 | sage: G = Gamma0(27) |
… |
… |
|
162 | 168 | [ 3 2] |
163 | 169 | [28 19] |
164 | 170 | sage: x.parent() |
165 | | Congruence Subgroup Gamma0(7) |
| 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 | |
166 | 179 | """ |
167 | 180 | return self.parent()(self.__x * right.__x, check=False) |
168 | 181 | |
diff -r 7f73030ab02b -r f45efdbe8d70 sage/modular/arithgroup/arithgroup_generic.py
a
|
b
|
|
47 | 47 | assuming that it has a working element testing routine. |
48 | 48 | """ |
49 | 49 | |
| 50 | def __init__(self): |
| 51 | r""" |
| 52 | Standard init routine. |
| 53 | |
| 54 | EXAMPLE:: |
| 55 | |
| 56 | sage: G = Gamma1(7) |
| 57 | sage: G.category() # indirect doctest |
| 58 | Category of groups |
| 59 | """ |
| 60 | group.Group.__init__(self) |
| 61 | |
50 | 62 | def _repr_(self): |
51 | 63 | r""" |
52 | 64 | Return the string representation of self. |
diff -r 7f73030ab02b -r f45efdbe8d70 sage/modular/arithgroup/arithgroup_perm.py
a
|
b
|
|
185 | 185 | [1 1] |
186 | 186 | [0 1] |
187 | 187 | """ |
188 | | g = SL2Z(g) |
| 188 | g = SL2Z(g, check=check) |
189 | 189 | if (not check) or (self.permutation_action(g)(1) == 1): |
190 | | g._parent = self |
191 | 190 | return g |
192 | 191 | else: |
193 | 192 | raise TypeError, "Not in group" |
diff -r 7f73030ab02b -r f45efdbe8d70 sage/modular/arithgroup/congroup_gamma.py
a
|
b
|
|
129 | 129 | TypeError: matrix must have diagonal entries (=1, 7) congruent to 1 |
130 | 130 | modulo 5, and off-diagonal entries (=1,6) divisible by 5 |
131 | 131 | """ |
132 | | if isinstance(x, ArithmeticSubgroupElement) and x.parent() == self: |
133 | | return x |
134 | | x = ArithmeticSubgroupElement(self, x, check=check) |
| 132 | from all import SL2Z |
| 133 | x = SL2Z(x, check) |
135 | 134 | if not check: |
136 | 135 | return x |
137 | 136 | |
diff -r 7f73030ab02b -r f45efdbe8d70 sage/modular/arithgroup/congroup_gamma0.py
a
|
b
|
|
446 | 446 | ... |
447 | 447 | TypeError: matrix must have lower left entry (=23) divisible by 12 |
448 | 448 | """ |
449 | | if isinstance(x, ArithmeticSubgroupElement) and x.parent() == self: |
450 | | return x |
451 | | x = ArithmeticSubgroupElement(self, x, check=check) |
| 449 | from all import SL2Z |
| 450 | x = SL2Z(x, check) |
452 | 451 | if not check: |
453 | 452 | return x |
454 | 453 | |
diff -r 7f73030ab02b -r f45efdbe8d70 sage/modular/arithgroup/congroup_gamma1.py
a
|
b
|
|
288 | 288 | ... |
289 | 289 | TypeError: matrix must have diagonal entries (=1, 7) congruent to 1 modulo 5, and lower left entry (=6) divisible by 5 |
290 | 290 | """ |
291 | | if isinstance(x, ArithmeticSubgroupElement) and x.parent() == self: |
292 | | return x |
293 | | x = ArithmeticSubgroupElement(self, x, check=check) |
| 291 | from all import SL2Z |
| 292 | x = SL2Z(x, check) |
294 | 293 | if not check: |
295 | 294 | return x |
296 | 295 | |
… |
… |
|
298 | 297 | c = x.c() |
299 | 298 | d = x.d() |
300 | 299 | N = self.level() |
301 | | if (a%N == 1) and (c%N == 0) and (d%N == 1): |
| 300 | if (a%N == 1) and (c%N == 0): |
302 | 301 | return x |
| 302 | # don't need to check d == 1 mod N as this is automatic from det |
303 | 303 | else: |
304 | 304 | raise TypeError, "matrix must have diagonal entries (=%s, %s) congruent to 1 modulo %s, and lower left entry (=%s) divisible by %s" %(a, d, N, c, N) |
305 | 305 | |
diff -r 7f73030ab02b -r f45efdbe8d70 sage/modular/arithgroup/congroup_gammaH.py
a
|
b
|
|
853 | 853 | ... |
854 | 854 | TypeError: matrix must have lower right entry (=3) congruent modulo 10 to some element of H |
855 | 855 | """ |
856 | | if isinstance(x, ArithmeticSubgroupElement) and x.parent() == self: |
857 | | return x |
858 | | x = ArithmeticSubgroupElement(self, x, check=check) |
| 856 | from all import SL2Z |
| 857 | x = SL2Z(x, check) |
859 | 858 | if not check: |
860 | 859 | return x |
861 | 860 | |
diff -r 7f73030ab02b -r f45efdbe8d70 sage/modular/arithgroup/congroup_generic.py
a
|
b
|
|
64 | 64 | if level <= 0: |
65 | 65 | raise ArithmeticError, "Congruence groups only defined for positive levels." |
66 | 66 | self.__level = level |
| 67 | ArithmeticSubgroup.__init__(self) |
67 | 68 | |
68 | 69 | def _repr_(self): |
69 | 70 | """ |
… |
… |
|
197 | 198 | else: |
198 | 199 | raise NotImplementedError |
199 | 200 | |
200 | | def __call__(self, x, check=True): |
201 | | """ |
202 | | Coerce x into self. |
203 | | |
204 | | NOTE: This function should be overridden by any subclass the |
205 | | user will interact with directly. |
206 | | |
207 | | EXAMPLES:: |
208 | | |
209 | | sage: sage.modular.arithgroup.congroup_generic.CongruenceSubgroup(5).__call__(0) |
210 | | Traceback (most recent call last): |
211 | | ... |
212 | | NotImplementedError |
213 | | """ |
214 | | if isinstance(x, ArithmeticSubgroupElement) and x.parent() == self: |
215 | | return x |
216 | | raise NotImplementedError |
diff -r 7f73030ab02b -r f45efdbe8d70 sage/modular/arithgroup/congroup_sl2z.py
a
|
b
|
|
20 | 20 | ################################################################################ |
21 | 21 | |
22 | 22 | from congroup_gamma0 import Gamma0_class |
| 23 | from arithgroup_element import ArithmeticSubgroupElement |
23 | 24 | from sage.rings.integer_ring import ZZ |
24 | 25 | from sage.modular.cusps import Cusp |
25 | 26 | from sage.rings.arith import gcd |
… |
… |
|
92 | 93 | """ |
93 | 94 | return _SL2Z_ref, () |
94 | 95 | |
| 96 | def __call__(self, x, check=True): |
| 97 | r""" |
| 98 | Create an element of self from x. If check=True (the default), check |
| 99 | that x really defines a 2x2 integer matrix of det 1. |
| 100 | """ |
| 101 | return ArithmeticSubgroupElement(self, x, check=check) |
| 102 | |
95 | 103 | def _repr_(self): |
96 | 104 | """ |
97 | 105 | Return the string representation of self. |
diff -r 7f73030ab02b -r f45efdbe8d70 sage/modular/modform/constructor.py
a
|
b
|
|
84 | 84 | (5, Congruence Subgroup Gamma0(5), 7, Integer Ring) |
85 | 85 | sage: type(v[0]), type(v[1]), type(v[2]), type(v[3]) |
86 | 86 | (<type 'sage.rings.integer.Integer'>, |
87 | | <class 'sage.modular.arithgroup.congroup_gamma0.Gamma0_class'>, |
| 87 | <class 'sage.modular.arithgroup.congroup_gamma0.Gamma0_class_with_category'>, |
88 | 88 | <type 'sage.rings.integer.Integer'>, |
89 | 89 | <type 'sage.rings.integer_ring.IntegerRing_class'>) |
90 | 90 | sage: canonical_parameters( 5, 7, 7, ZZ ) |