Hot-keys on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
""" Elements of Arithmetic Subgroups """
################################################################################ # # Copyright (C) 2009, The Sage Group -- http://www.sagemath.org/ # # Distributed under the terms of the GNU General Public License (GPL) # # The full text of the GPL is available at: # # http://www.gnu.org/licenses/ # ################################################################################ from __future__ import absolute_import
from sage.structure.element cimport MultiplicativeGroupElement, MonoidElement, Element from sage.structure.richcmp cimport richcmp from sage.rings.all import ZZ from sage.modular.cusps import Cusp
from sage.matrix.matrix_space import MatrixSpace from sage.matrix.matrix_integer_dense cimport Matrix_integer_dense
M2Z = MatrixSpace(ZZ, 2)
cdef class ArithmeticSubgroupElement(MultiplicativeGroupElement): r""" An element of the group `{\rm SL}_2(\ZZ)`, i.e. a 2x2 integer matrix of determinant 1. """
cdef Matrix_integer_dense __x
def __init__(self, parent, x, check=True): """ Create an element of an arithmetic subgroup.
INPUT:
- ``parent`` -- an arithmetic subgroup
- `x` -- data defining a 2x2 matrix over ZZ which lives in parent
- ``check`` -- if True, check that parent is an arithmetic subgroup, and that `x` defines a matrix of determinant `1`.
We tend not to create elements of arithmetic subgroups that aren't SL2Z, in order to avoid coercion issues (that is, the other arithmetic subgroups are "facade parents").
EXAMPLES::
sage: G = Gamma0(27) sage: sage.modular.arithgroup.arithgroup_element.ArithmeticSubgroupElement(G, [4,1,27,7]) [ 4 1] [27 7] sage: sage.modular.arithgroup.arithgroup_element.ArithmeticSubgroupElement(Integers(3), [4,1,27,7]) Traceback (most recent call last): ... TypeError: parent (= Ring of integers modulo 3) must be an arithmetic subgroup sage: sage.modular.arithgroup.arithgroup_element.ArithmeticSubgroupElement(G, [2,0,0,2]) Traceback (most recent call last): ... TypeError: matrix must have determinant 1 sage: sage.modular.arithgroup.arithgroup_element.ArithmeticSubgroupElement(G, [2,0,0,2], check=False) [2 0] [0 2] sage: x = Gamma0(11)([2,1,11,6]) sage: TestSuite(x).run()
sage: x = Gamma0(5).0 sage: SL2Z(x) [1 1] [0 1] sage: x in SL2Z True """
else: # Getting rid of this would result in a small speed gain for # arithmetic operations, but it would have the disadvantage of # causing strange and opaque errors when inappropriate data types # are used with "check=False".
def __setstate__(self, state): r""" For unpickling objects pickled with the old ArithmeticSubgroupElement class.
EXAMPLES::
sage: si = unpickle_newobj(sage.modular.arithgroup.arithgroup_element.ArithmeticSubgroupElement, ()) sage: x = matrix(ZZ,2,[1,1,0,1]) sage: unpickle_build(si, (Gamma0(13), {'_ArithmeticSubgroupElement__x': x})) """ elif '_CongruenceSubgroupElement__x' in kwdict: self.__x = M2Z(kwdict['_CongruenceSubgroupElement__x']) else: raise ValueError("Don't know how to unpickle %s" % repr(state))
def __iter__(self): """ EXAMPLES::
sage: Gamma0(2).0 [1 1] [0 1] sage: list(Gamma0(2).0) [1, 1, 0, 1]
Warning: this is different from the iteration on the matrix::
sage: list(Gamma0(2).0.matrix()) [(1, 1), (0, 1)] """
def __repr__(self): r""" Return the string representation of ``self``.
EXAMPLES::
sage: Gamma1(5)([6,1,5,1]).__repr__() '[6 1]\n[5 1]' """
def _latex_(self): r""" Return latex representation of ``self``.
EXAMPLES::
sage: Gamma1(5)([6,1,5,1])._latex_() '\\left(\\begin{array}{rr}\n6 & 1 \\\\\n5 & 1\n\\end{array}\\right)' """
cpdef _richcmp_(self, right_r, int op): """ Compare self to right, where right is guaranteed to have the same parent as self.
EXAMPLES::
sage: x = Gamma0(18)([19,1,18,1]) sage: x == 3 False sage: x == x True
sage: x = Gamma0(5)([1,1,0,1]) sage: y = Gamma0(5)([1,4,0,1]) sage: x == 0 False sage: x == y False sage: x != y True
This once caused a segfault (see :trac:`5443`)::
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]]) sage: v == s*u True sage: s*u == v True """
def __nonzero__(self): """ Return True, since the self lives in SL(2,\Z), which does not contain the zero matrix.
EXAMPLES::
sage: x = Gamma0(5)([1,1,0,1]) sage: x.__nonzero__() True """
cpdef _mul_(self, right): """ Return self * right.
EXAMPLES::
sage: x = Gamma0(7)([1,0,7,1]) * Gamma0(7)([3,2,7,5]) ; x # indirect doctest [ 3 2] [28 19] sage: x.parent() Modular Group SL(2,Z)
We check that :trac:`5048` is fixed::
sage: a = Gamma0(10).1 * Gamma0(5).2; a # random sage: a.parent() Modular Group SL(2,Z)
"""
def __invert__(self): """ Return the inverse of self.
EXAMPLES::
sage: Gamma0(11)([1,-1,0,1]).__invert__() [1 1] [0 1] """
def matrix(self): """ Return the matrix corresponding to self.
EXAMPLES::
sage: x = Gamma1(3)([4,5,3,4]) ; x [4 5] [3 4] sage: x.matrix() [4 5] [3 4] sage: type(x.matrix()) <type 'sage.matrix.matrix_integer_dense.Matrix_integer_dense'> """
def determinant(self): """ Return the determinant of self, which is always 1.
EXAMPLES::
sage: Gamma0(691)([1,0,691,1]).determinant() 1 """
def det(self): """ Return the determinant of self, which is always 1.
EXAMPLES::
sage: Gamma1(11)([12,11,-11,-10]).det() 1 """
def a(self): """ Return the upper left entry of self.
EXAMPLES::
sage: Gamma0(13)([7,1,13,2]).a() 7 """
def b(self): """ Return the upper right entry of self.
EXAMPLES::
sage: Gamma0(13)([7,1,13,2]).b() 1 """
def c(self): """ Return the lower left entry of self.
EXAMPLES::
sage: Gamma0(13)([7,1,13,2]).c() 13 """
def d(self): """ Return the lower right entry of self.
EXAMPLES::
sage: Gamma0(13)([7,1,13,2]).d() 2 """
def acton(self, z): """ Return the result of the action of self on z as a fractional linear transformation.
EXAMPLES::
sage: G = Gamma0(15) sage: g = G([1, 2, 15, 31])
An example of g acting on a symbolic variable::
sage: z = var('z') sage: g.acton(z) (z + 2)/(15*z + 31)
An example involving the Gaussian numbers::
sage: K.<i> = NumberField(x^2 + 1) sage: g.acton(i) 1/1186*i + 77/1186
An example with complex numbers::
sage: C.<i> = ComplexField() sage: g.acton(i) 0.0649241146711636 + 0.000843170320404721*I
An example with the cusp infinity::
sage: g.acton(infinity) 1/15
An example which maps a finite cusp to infinity::
sage: g.acton(-31/15) +Infinity
Note that when acting on instances of cusps the return value is still a rational number or infinity (Note the presence of '+', which does not show up for cusp instances)::
sage: g.acton(Cusp(-31/15)) +Infinity
TESTS:
We cover the remaining case, i.e., infinity mapped to infinity::
sage: G([1, 4, 0, 1]).acton(infinity) +Infinity
""" else: else:
def __getitem__(self, q): r""" Fetch entries by direct indexing.
EXAMPLES:: sage: SL2Z([3,2,1,1])[0,0] 3 """
def __hash__(self): r""" Return a hash value.
EXAMPLES::
sage: hash(SL2Z.0) -8192788425652673914 # 64-bit -1995808122 # 32-bit """
def __reduce__(self): r""" Used for pickling.
EXAMPLES::
sage: (SL2Z.1).__reduce__() (Modular Group SL(2,Z), ( [1 1] [0 1] )) """
def multiplicative_order(self): r""" Return the multiplicative order of this element.
EXAMPLES::
sage: SL2Z.one().multiplicative_order() 1 sage: SL2Z([-1,0,0,-1]).multiplicative_order() 2 sage: s,t = SL2Z.gens() sage: ((t^3*s*t^2) * s * ~(t^3*s*t^2)).multiplicative_order() 4 sage: (t^3 * s * t * t^-3).multiplicative_order() 6 sage: (t^3 * s * t * s * t^-2).multiplicative_order() 3 sage: SL2Z([2,1,1,1]).multiplicative_order() +Infinity sage: SL2Z([-2,1,1,-1]).multiplicative_order() +Infinity """
raise RuntimeError |