Path: blob/master/src/sage/modular/arithgroup/congroup_sl2z.py
8820 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: TestSuite(G).run()73sage: SL2Z.0 * SL2Z.174[ 0 -1]75[ 1 1]76sage: SL2Z is loads(dumps(SL2Z))77True78"""79Gamma0_class.__init__(self, 1)8081def __reduce__(self):82"""83Used for pickling self.8485EXAMPLES::8687sage: SL2Z.__reduce__()88(<function _SL2Z_ref at ...>, ())89"""90return _SL2Z_ref, ()9192def _element_constructor_(self, x, check=True):93r"""94Create an element of self from x, which must be something that can be95coerced into a 2x2 integer matrix. If check=True (the default), check96that x really has determinant 1.9798EXAMPLE::99100sage: SL2Z([1,0,0,1]) # indirect doctest101[1 0]102[0 1]103sage: SL2Z([2, 0, 0, 2], check=False) # don't do this!104[2 0]105[0 2]106sage: SL2Z([1, QQ, False], check=False) # don't do this either!107Traceback (most recent call last):108...109TypeError: entries has the wrong length110"""111return ArithmeticSubgroupElement(self, x, check=check)112113def _contains_sl2(self,a,b,c,d):114r"""115Test whether [a,b,c,d] is an element of self, where a,b,c,d are integers with `ad-bc=1`. In other words, always return True.116117EXAMPLE::118119sage: [8,7,9,8] in SL2Z # indirect doctest120True121"""122return True123124def _repr_(self):125"""126Return the string representation of self.127128EXAMPLES::129130sage: SL2Z._repr_()131'Modular Group SL(2,Z)'132"""133return "Modular Group SL(2,Z)"134135def _latex_(self):136r"""137Return the \LaTeX representation of self.138139EXAMPLES::140141sage: SL2Z._latex_()142'\\mbox{\\rm SL}_2(\\Bold{Z})'143sage: latex(SL2Z)144\mbox{\rm SL}_2(\Bold{Z})145"""146return "\\mbox{\\rm SL}_2(%s)"%(ZZ._latex_())147148def is_subgroup(self, right):149"""150Return True if self is a subgroup of right.151152EXAMPLES::153154sage: SL2Z.is_subgroup(SL2Z)155True156sage: SL2Z.is_subgroup(Gamma1(1))157True158sage: SL2Z.is_subgroup(Gamma0(6))159False160"""161return right.level() == 1162163def reduce_cusp(self, c):164r"""165Return the unique reduced cusp equivalent to c under the166action of self. Always returns Infinity, since there is only167one equivalence class of cusps for $SL_2(Z)$.168169EXAMPLES::170171sage: SL2Z.reduce_cusp(Cusps(-1/4))172Infinity173"""174return Cusp(1,0)175176def random_element(self, bound=100, *args, **kwds):177r"""178Return a random element of `{\rm SL}_2(\ZZ)` with entries whose179absolute value is strictly less than bound (default 100).180Additional arguments and keywords are passed to the random_element181method of ZZ.182183(Algorithm: Generate a random pair of integers at most bound. If they184are not coprime, throw them away and start again. If they are, find an185element of `{\rm SL}_2(\ZZ)` whose bottom row is that, and186left-multiply it by `\begin{pmatrix} 1 & w \\ 0 & 1\end{pmatrix}` for187an integer `w` randomly chosen from a small enough range that the188answer still has entries at most bound.)189190It is, unfortunately, not true that all elements of SL2Z with entries <191bound appear with equal probability; those with larger bottom rows are192favoured, because there are fewer valid possibilities for w.193194EXAMPLES::195196sage: SL2Z.random_element()197[60 13]198[83 18]199sage: SL2Z.random_element(5)200[-1 3]201[ 1 -4]202203Passes extra positional or keyword arguments through::204205sage: SL2Z.random_element(5, distribution='1/n')206[ 1 -4]207[ 0 1]208"""209if bound <= 1: raise ValueError("bound must be greater than 1")210c = ZZ.random_element(1-bound, bound, *args, **kwds)211d = ZZ.random_element(1-bound, bound, *args, **kwds)212if gcd(c,d) != 1: # try again213return self.random_element(bound, *args, **kwds)214else:215a,b,c,d = lift_to_sl2z(c,d,0)216whi = bound217wlo = bound218if c > 0:219whi = min(whi, ((bound - a)/ZZ(c)).ceil())220wlo = min(wlo, ((bound + a)/ZZ(c)).ceil())221elif c < 0:222whi = min(whi, ((bound + a)/ZZ(-c)).ceil())223wlo = min(wlo, ((bound - a)/ZZ(-c)).ceil())224225if d > 0:226whi = min(whi, ((bound - b)/ZZ(d)).ceil())227wlo = min(wlo, ((bound + b)/ZZ(d)).ceil())228elif d < 0:229whi = min(whi, ((bound + b)/ZZ(-d)).ceil())230wlo = min(wlo, ((bound - b)/ZZ(-d)).ceil())231232w = ZZ.random_element(1-wlo, whi, *args, **kwds)233a += c*w234b += d*w235return self([a,b,c,d])236237238SL2Z = SL2Z_class()239240def _SL2Z_ref():241"""242Return SL2Z. (Used for pickling SL2Z.)243244EXAMPLES::245246sage: sage.modular.arithgroup.congroup_sl2z._SL2Z_ref()247Modular Group SL(2,Z)248sage: sage.modular.arithgroup.congroup_sl2z._SL2Z_ref() is SL2Z249True250"""251return SL2Z252253254255256