Path: blob/master/sage/modular/arithgroup/congroup_sl2z.py
4084 views
r"""1The modular group `{\rm SL}_2(\ZZ)`23AUTHORS:45- Niles Johnson (2010-08): Trac #3893: ``random_element()`` should pass on ``*args`` and ``**kwds``.67"""89################################################################################10#11# Copyright (C) 2009, The Sage Group -- http://www.sagemath.org/12#13# Distributed under the terms of the GNU General Public License (GPL)14#15# The full text of the GPL is available at:16#17# http://www.gnu.org/licenses/18#19################################################################################2021from congroup_gamma0 import Gamma0_class22from arithgroup_element import ArithmeticSubgroupElement23from sage.rings.integer_ring import ZZ24from sage.modular.cusps import Cusp25from sage.rings.arith import gcd26from sage.modular.modsym.p1list import lift_to_sl2z2728def is_SL2Z(x):29r"""30Return True if x is the modular group `{\rm SL}_2(\ZZ)`.3132EXAMPLES::3334sage: from sage.modular.arithgroup.all import is_SL2Z35sage: is_SL2Z(SL2Z)36True37sage: is_SL2Z(Gamma0(6))38False39"""40return isinstance(x, SL2Z_class)4142class SL2Z_class(Gamma0_class):43r"""44The full modular group `{\rm SL}_2(\ZZ)`, regarded as a congruence45subgroup of itself.46"""4748def __init__(self):49r"""50The modular group ${\rm SL}_2(\Z)$.5152EXAMPLES::5354sage: G = SL2Z; G55Modular Group SL(2,Z)56sage: G.gens()57(58[ 0 -1] [1 1]59[ 1 0], [0 1]60)61sage: G.062[ 0 -1]63[ 1 0]64sage: G.165[1 1]66[0 1]67sage: latex(G)68\mbox{\rm SL}_2(\Bold{Z})69sage: G([1,-1,0,1])70[ 1 -1]71[ 0 1]72sage: loads(G.dumps()) == G73True74sage: SL2Z.0 * SL2Z.175[ 0 -1]76[ 1 1]7778sage: SL2Z == loads(dumps(SL2Z))79True80sage: SL2Z is loads(dumps(SL2Z))81True82"""83Gamma0_class.__init__(self, 1)8485def __reduce__(self):86"""87Used for pickling self.8889EXAMPLES::9091sage: SL2Z.__reduce__()92(<function _SL2Z_ref at ...>, ())93"""94return _SL2Z_ref, ()9596def __call__(self, x, check=True):97r"""98Create an element of self from x. If check=True (the default), check99that x really defines a 2x2 integer matrix of det 1.100101EXAMPLE::102103sage: SL2Z([1,0,0,1])104[1 0]105[0 1]106sage: SL2Z([1, QQ, False], check=False) # don't do this!107[1, Rational Field, False]108"""109return ArithmeticSubgroupElement(self, x, check=check)110111def _repr_(self):112"""113Return the string representation of self.114115EXAMPLES::116117sage: SL2Z._repr_()118'Modular Group SL(2,Z)'119"""120return "Modular Group SL(2,Z)"121122def _latex_(self):123r"""124Return the \LaTeX representation of self.125126EXAMPLES::127128sage: SL2Z._latex_()129'\\mbox{\\rm SL}_2(\\Bold{Z})'130sage: latex(SL2Z)131\mbox{\rm SL}_2(\Bold{Z})132"""133return "\\mbox{\\rm SL}_2(%s)"%(ZZ._latex_())134135def is_subgroup(self, right):136"""137Return True if self is a subgroup of right.138139EXAMPLES::140141sage: SL2Z.is_subgroup(SL2Z)142True143sage: SL2Z.is_subgroup(Gamma1(1))144True145sage: SL2Z.is_subgroup(Gamma0(6))146False147"""148return right.level() == 1149150def reduce_cusp(self, c):151r"""152Return the unique reduced cusp equivalent to c under the153action of self. Always returns Infinity, since there is only154one equivalence class of cusps for $SL_2(Z)$.155156EXAMPLES::157158sage: SL2Z.reduce_cusp(Cusps(-1/4))159Infinity160"""161return Cusp(1,0)162163def random_element(self, bound=100, *args, **kwds):164r"""165Return a random element of `{\rm SL}_2(\ZZ)` with entries whose166absolute value is strictly less than bound (default 100).167Additional arguments and keywords are passed to the random_element168method of ZZ.169170(Algorithm: Generate a random pair of integers at most bound. If they171are not coprime, throw them away and start again. If they are, find an172element of `{\rm SL}_2(\ZZ)` whose bottom row is that, and173left-multiply it by `\begin{pmatrix} 1 & w \\ 0 & 1\end{pmatrix}` for174an integer `w` randomly chosen from a small enough range that the175answer still has entries at most bound.)176177It is, unfortunately, not true that all elements of SL2Z with entries <178bound appear with equal probability; those with larger bottom rows are179favoured, because there are fewer valid possibilities for w.180181EXAMPLES::182183sage: SL2Z.random_element()184[60 13]185[83 18]186sage: SL2Z.random_element(5)187[-1 3]188[ 1 -4]189190Passes extra positional or keyword arguments through::191192sage: SL2Z.random_element(5, distribution='1/n')193[ 1 -1]194[ 0 1]195196"""197if bound <= 1: raise ValueError, "bound must be greater than 1"198c = ZZ.random_element(1-bound, bound, *args, **kwds)199d = ZZ.random_element(1-bound, bound, *args, **kwds)200if gcd(c,d) != 1: # try again201return self.random_element(bound)202else:203a,b,c,d = lift_to_sl2z(c,d,0)204whi = bound205wlo = bound206if c > 0:207whi = min(whi, ((bound - a)/ZZ(c)).ceil())208wlo = min(wlo, ((bound + a)/ZZ(c)).ceil())209elif c < 0:210whi = min(whi, ((bound + a)/ZZ(-c)).ceil())211wlo = min(wlo, ((bound - a)/ZZ(-c)).ceil())212213if d > 0:214whi = min(whi, ((bound - b)/ZZ(d)).ceil())215wlo = min(wlo, ((bound + b)/ZZ(d)).ceil())216elif d < 0:217whi = min(whi, ((bound + b)/ZZ(-d)).ceil())218wlo = min(wlo, ((bound - b)/ZZ(-d)).ceil())219220w = ZZ.random_element(1-wlo, whi)221a += c*w222b += d*w223return self([a,b,c,d])224225226SL2Z = SL2Z_class()227228def _SL2Z_ref():229"""230Return SL2Z. (Used for pickling SL2Z.)231232EXAMPLES::233234sage: sage.modular.arithgroup.congroup_sl2z._SL2Z_ref()235Modular Group SL(2,Z)236sage: sage.modular.arithgroup.congroup_sl2z._SL2Z_ref() is SL2Z237True238"""239return SL2Z240241242243244