Ticket #2103: 2103-new.patch

File 2103-new.patch, 47.5 kB (added by davidloeffler, 2 months ago)
  • a/sage/modular/abvar/abvar.py

    old new  
    30693069        class that matters: 
    30703070            sage: D = (J0(11)*J1(11)).decomposition(); D 
    30713071            [ 
    3072             Simple abelian subvariety 11a(1,11) of dimension 1 of J0(11) x J1(11), 
    3073             Simple abelian subvariety 11aG1(1,11) of dimension 1 of J0(11) x J1(11) 
     3072            Simple abelian subvariety 11aG1(1,11) of dimension 1 of J0(11) x J1(11), 
     3073            Simple abelian subvariety 11a(1,11) of dimension 1 of J0(11) x J1(11) 
    30743074            ] 
    30753075            sage: D[0]._complement_shares_no_factors_with_same_label() 
    30763076            True 
    30773077            sage: D[0].newform_label() 
    3078             '11a
     3078            '11aG1
    30793079            sage: D[1].newform_label() 
    3080             '11aG1'             
     3080            '11a'             
    30813081        """ 
    30823082        try: 
    30833083            return self.__complement_shares 
  • a/sage/modular/congroup.py

    old new  
    2626import sage.rings.arith as arith 
    2727from sage.rings.integer_mod_ring import IntegerModRing 
    2828from sage.rings.all import QQ, ZZ, divisors 
    29  
    3029from sage.matrix.matrix_space import MatrixSpace 
    3130 
    3231from congroup_element import CongruenceSubgroupElement 
     32import cusps 
     33from sage.sets.set import Set 
    3334 
    3435import sage.modular.modsym.p1list 
    3536 
     
    475476            return x 
    476477        raise NotImplementedError 
    477478 
     479    def reduce_cusp(self, c): 
     480        r""" 
     481        Given a cusp $c \in \mathbb{P}^1(\mathbb{Q})$, return the unique 
     482        reduced cusp equivalent to c under the action of self, where a reduced 
     483        cusp is an element r/s with r,s coprime integers, s as small as 
     484        possible, and r as small as possible for that s. 
     485         
     486        NOTE: This function should be overridden by all subclasses. 
     487 
     488        EXAMPLES: 
     489            sage: sage.modular.congroup.CongruenceSubgroup(5).reduce_cusp(1/4) 
     490            Traceback (most recent call last): 
     491            ... 
     492            NotImplementedError 
     493        """ 
     494        raise NotImplementedError 
     495 
     496    def cusps(self, bdmap=False): 
     497        r""" 
     498        Return a set of inequivalent cusps for self, i.e. a set of 
     499        representatives for the orbits of self on $\mathbb{P}^1(\mathbb{Q})$. 
     500        These should be returned in a reduced form. 
     501 
     502        INPUTS: 
     503            (bool) -- whether to directly calculate the cusps, or to calculate 
     504            them as a by-product of computing the boundary map on the 
     505            associated space of modular symbols. The latter is slower, but is 
     506            older and presumably better-tested code. 
     507 
     508        EXAMPLES: 
     509            sage: Gamma0(36).cusps() 
     510            {1/6, 1/4, 1/3, 1/2, 1/9, 0, 1/18, 5/12, Infinity, 1/12, 2/3, 5/6} 
     511            sage: Gamma0(36).cusps(True) == Gamma0(36).cusps(False) 
     512            True 
     513            sage: GammaH(36, [19,29]).cusps() == Gamma0(36).cusps() 
     514            True 
     515            sage: Gamma0(1).cusps() 
     516            {Infinity} 
     517        """ 
     518        # special case for SL2Z as modular symbols space is zero 
     519        if bdmap == True: 
     520            # special case for SL2Z as modular symbols space is zero 
     521            if self == SL2Z: 
     522                return Set([cusps.Cusp(1,0)]) 
     523            return Set([self.reduce_cusp(c) for c in self.modular_symbols().cusps()]) 
     524        else: 
     525            return self._find_cusps() 
     526 
     527    def _find_cusps(self): 
     528        r""" 
     529        Calculate a list of inequivalent cusps.  
     530 
     531        EXAMPLES: 
     532            sage: sage.modular.congroup.CongruenceSubgroup(5)._find_cusps() 
     533            Traceback (most recent call last): 
     534            ... 
     535            NotImplementedError 
     536 
     537        NOTE: This function should be overridden by all subclasses. 
     538        """ 
     539        raise NotImplementedError 
     540 
    478541def lift_to_sl2z(c, d, N): 
    479542    """ 
    480543    Given a vector (c, d) in $(Z/NZ)^2$, this function computes and 
     
    528591    return [z2, -z1, c, d] 
    529592 
    530593 
    531 def is_Gamma0(x): 
    532     """ 
    533     Return True if x is a congruence subgroup of type Gamma0. 
    534  
    535     EXAMPLES: 
    536         sage: from sage.modular.congroup import is_Gamma0 
    537         sage: is_Gamma0(SL2Z) 
    538         True 
    539         sage: is_Gamma0(Gamma0(13)) 
    540         True 
    541         sage: is_Gamma0(Gamma1(6)) 
    542         False 
    543     """ 
    544     return isinstance(x, Gamma0_class) 
    545  
    546 _gamma0_cache = {} 
    547 def Gamma0(N): 
    548     """ 
    549     Return the congruence subgroup Gamma0(N). 
    550  
    551     EXAMPLES: 
    552         sage: G = Gamma0(51) ; G 
    553         Congruence Subgroup Gamma0(51) 
    554         sage: G == Gamma0(51) 
    555         True 
    556         sage: G is Gamma0(51) 
    557         True 
    558     """ 
    559     try: 
    560         return _gamma0_cache[N] 
    561     except KeyError: 
    562         _gamma0_cache[N] = Gamma0_class(N) 
    563         return _gamma0_cache[N] 
    564  
    565 class Gamma0_class(CongruenceSubgroup): 
    566     def __init__(self, level): 
    567         r""" 
    568         The congruence subgroup $\Gamma_0(N)$. 
    569  
    570         EXAMPLES: 
    571             sage: G = Gamma0(11); G 
    572             Congruence Subgroup Gamma0(11) 
    573             sage: loads(G.dumps()) == G 
    574             True 
    575         """ 
    576         CongruenceSubgroup.__init__(self, level) 
    577  
    578     def _repr_(self): 
    579         """ 
    580         Return the string representation of self. 
    581  
    582         EXAMPLES: 
    583             sage: Gamma0(98)._repr_() 
    584             'Congruence Subgroup Gamma0(98)' 
    585         """ 
    586         return "Congruence Subgroup Gamma0(%s)"%self.level() 
    587  
    588     def __reduce__(self): 
    589         """ 
    590         Used for pickling self. 
    591  
    592         EXAMPLES: 
    593             sage: Gamma0(22).__reduce__() 
    594             (<function Gamma0 at ...>, (22,)) 
    595         """ 
    596         return Gamma0, (self.level(),) 
    597  
    598     def _latex_(self): 
    599         r""" 
    600         Return the \LaTeX representation of self. 
    601          
    602         EXAMPLES: 
    603             sage: Gamma0(20)._latex_() 
    604             '\\Gamma_0(20)' 
    605             sage: latex(Gamma0(20)) 
    606             \Gamma_0(20) 
    607         """ 
    608         return "\\Gamma_0(%s)"%self.level() 
    609  
    610     def _generators_for_H(self): 
    611         """ 
    612         Return generators for the subgroup H of the units mod 
    613         self.level() that defines self. 
    614          
    615         EXAMPLES: 
    616             sage: Gamma0(15)._generators_for_H() 
    617             [11, 7] 
    618         """ 
    619         try: 
    620             return self.__generators_for_H 
    621         except AttributeError: 
    622             self.__generators_for_H = [int(x) for x in IntegerModRing(self.level()).unit_gens()] 
    623             return self.__generators_for_H 
    624  
    625     def _list_of_elements_in_H(self): 
    626         """ 
    627         Returns a sorted list of Python ints that are representatives 
    628         between 0 and N-1 of the elements of H. 
    629  
    630         EXAMPLES: 
    631             sage: G = Gamma0(11) 
    632             sage: G._list_of_elements_in_H() 
    633             [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] 
    634  
    635             sage: G = Gamma0(6) 
    636             sage: G._list_of_elements_in_H() 
    637             [1, 5] 
    638  
    639             sage: G = Gamma0(1) 
    640             sage: G._list_of_elements_in_H() 
    641             [1] 
    642         """ 
    643         N = self.level() 
    644         if N != 1: 
    645             gcd = arith.gcd 
    646             return [ x for x in range(1, N) if gcd(x, N) == 1 ] 
    647         else: 
    648             return [1] 
    649      
    650     def __cmp__(self, right): 
    651         """ 
    652         Compare self to right. 
    653  
    654         EXAMPLES: 
    655             sage: Gamma0(21).__cmp__(Gamma0(21)) 
    656             0 
    657             sage: Gamma0(21) < Gamma0(32) 
    658             True 
    659         """ 
    660         if not is_Gamma0(right): 
    661             if is_CongruenceSubgroup(right): 
    662                 c = cmp(self.level(), right.level()) 
    663                 if c: return c 
    664             return cmp(type(self), type(right)) 
    665         return cmp(self.level(), right.level()) 
    666  
    667     def is_even(self): 
    668         """ 
    669         Return True precisely if this subgroup contains the matrix -1. 
    670  
    671         Since Gamma0(N) always, contains the matrix -1, this always 
    672         returns True. 
    673  
    674         EXAMPLES: 
    675             sage: Gamma0(12).is_even() 
    676             True 
    677             sage: SL2Z.is_even() 
    678             True 
    679         """ 
    680         return True 
    681  
    682     def is_subgroup(self, right): 
    683         """ 
    684         Return True if self is a subgroup of right. 
    685  
    686         EXAMPLES: 
    687             sage: G = Gamma0(20) 
    688             sage: G.is_subgroup(SL2Z) 
    689             True 
    690             sage: G.is_subgroup(Gamma0(4)) 
    691             True 
    692             sage: G.is_subgroup(Gamma0(20)) 
    693             True 
    694             sage: G.is_subgroup(Gamma0(7)) 
    695             False 
    696             sage: Gamma0(2).is_subgroup(Gamma1(2)) 
    697             True 
    698         """ 
    699         if right.level() == 1: 
    700             return True 
    701         if is_Gamma0(right): 
    702             return self.level() % right.level() == 0 
    703         if is_Gamma1(right): 
    704             if right.level() >= 3: 
    705                 return False 
    706             elif right.level() == 2: 
    707                 return self.level() == 2 
    708             # case level 1 dealt with above 
    709         raise NotImplementedError 
    710  
    711     def coset_reps(self): 
    712         r""" 
    713         Return representatives for the right cosets of this congruence 
    714         subgroup in ${\rm SL}_2(\Z)$ as a generator object. 
    715          
    716         Use \code{list(self.coset_reps())} to obtain coset reps as a 
    717         list. 
    718  
    719         EXAMPLES: 
    720             sage: list(Gamma0(5).coset_reps()) 
    721             [[1, 0, 0, 1], 
    722             [0, -1, 1, 0], 
    723             [1, 0, 1, 1], 
    724             [1, 1, 1, 2], 
    725             [1, 2, 1, 3], 
    726             [1, 3, 1, 4]] 
    727             sage: list(Gamma0(4).coset_reps()) 
    728             [[1, 0, 0, 1], 
    729             [0, -1, 1, 0], 
    730             [1, 0, 1, 1], 
    731             [1, 1, 1, 2], 
    732             [1, 2, 1, 3], 
    733             [-1, -1, 2, 1]] 
    734             sage: list(Gamma0(1).coset_reps()) 
    735             [[1, 0, 0, 1]] 
    736         """ 
    737         N = self.level() 
    738         for z in sage.modular.modsym.p1list.P1List(N): 
    739             yield lift_to_sl2z(z[0], z[1], N) 
    740  
    741     def generators(self): 
    742         r""" 
    743         Return generators for this congruence subgroup. 
    744  
    745         The result is cached. 
    746  
    747         EXAMPLE: 
    748             sage: for g in Gamma0(3).generators(): 
    749             ...     print g 
    750             ...     print '---' 
    751             [1 1] 
    752             [0 1] 
    753             --- 
    754             [-1  0] 
    755             [ 0 -1] 
    756             --- 
    757             ... 
    758             --- 
    759             [-2  1] 
    760             [-3  1] 
    761             --- 
    762  
    763         """ 
    764         try: 
    765             return self.__gens 
    766         except AttributeError: 
    767             from sage.modular.modsym.p1list import P1List 
    768             from congroup_pyx import generators_helper 
    769             level = self.level() 
    770             gen_list = generators_helper(P1List(level), level, Mat2Z) 
    771             self.__gens = [self(g, check=False) for g in gen_list] 
    772             return self.__gens 
    773  
    774     def gamma_h_subgroups(self): 
    775         r""" 
    776         Return the subgroups of the form $\Gamma_H(N)$ contained 
    777         in self, where $N$ is the level of self. 
    778  
    779         EXAMPLES: 
    780             sage: G = Gamma0(11) 
    781             sage: G.gamma_h_subgroups() 
    782             [Congruence Subgroup Gamma_H(11) with H generated by [2], Congruence Subgroup Gamma_H(11) with H generated by [4], Congruence Subgroup Gamma_H(11) with H generated by [10], Congruence Subgroup Gamma_H(11) with H generated by []] 
    783             sage: G = Gamma0(12) 
    784             sage: G.gamma_h_subgroups() 
    785             [Congruence Subgroup Gamma_H(12) with H generated by [5, 7], Congruence Subgroup Gamma_H(12) with H generated by [7], Congruence Subgroup Gamma_H(12) with H generated by [5], Congruence Subgroup Gamma_H(12) with H generated by []] 
    786         """ 
    787         N = self.level() 
    788         R = IntegerModRing(N) 
    789         return [GammaH(N, H) for H in R.multiplicative_subgroups()] 
    790  
    791     def __call__(self, x, check=True): 
    792         r""" 
    793         Create an element of this congruence subgroup from x. 
    794  
    795         If the optional flag check is True (default), check whether 
    796         x actually gives an element of self. 
    797  
    798         EXAMPLES: 
    799             sage: G = Gamma0(12) 
    800             sage: G([1, 0, 24, 1]) 
    801             [ 1  0] 
    802             [24  1] 
    803             sage: G(matrix(ZZ, 2, [1, 1, -12, -11])) 
    804             [  1   1] 
    805             [-12 -11] 
    806             sage: G([1, 0, 23, 1]) 
    807             Traceback (most recent call last): 
    808             ... 
    809             TypeError: matrix must have lower left entry (=23) divisible by 12 
    810         """ 
    811         if isinstance(x, CongruenceSubgroupElement) and x.parent() == self: 
    812             return x 
    813         x = CongruenceSubgroupElement(self, x, check=check) 
    814         if not check: 
    815             return x 
    816          
    817         c = x.c() 
    818         N = self.level() 
    819         if c%N == 0: 
    820             return x 
    821         else: 
    822             raise TypeError, "matrix must have lower left entry (=%s) divisible by %s" %(c, N) 
    823  
    824 def is_SL2Z(x): 
    825     """ 
    826     Return True if x is the modular group ${\rm SL}_2(\Z)$. 
    827  
    828     EXAMPLES: 
    829         sage: from sage.modular.congroup import is_SL2Z     
    830         sage: is_SL2Z(SL2Z) 
    831         True 
    832         sage: is_SL2Z(Gamma0(6)) 
    833         False 
    834     """ 
    835     return isinstance(x, SL2Z_class) 
    836  
    837 class SL2Z_class(Gamma0_class): 
    838     def __init__(self): 
    839         r""" 
    840         The modular group ${\rm SL}_2(\Z)$. 
    841  
    842         EXAMPLES: 
    843             sage: G = SL2Z; G 
    844             Modular Group SL(2,Z) 
    845             sage: G.gens() 
    846             ([ 0 -1] 
    847             [ 1  0], [1 1] 
    848             [0 1]) 
    849             sage: G.0 
    850             [ 0 -1] 
    851             [ 1  0] 
    852             sage: G.1 
    853             [1 1] 
    854             [0 1] 
    855             sage: latex(G) 
    856             \mbox{\rm SL}_2(\mathbf{Z}) 
    857             sage: G([1,-1,0,1]) 
    858             [ 1 -1] 
    859             [ 0  1] 
    860             sage: loads(G.dumps()) == G 
    861             True 
    862             sage: SL2Z.0 * SL2Z.1 
    863             [ 0 -1] 
    864             [ 1  1] 
    865  
    866             sage: SL2Z == loads(dumps(SL2Z)) 
    867             True 
    868             sage: SL2Z is loads(dumps(SL2Z)) 
    869             True 
    870         """ 
    871         Gamma0_class.__init__(self, 1) 
    872  
    873     def __reduce__(self): 
    874         """ 
    875         Used for pickling self. 
    876  
    877         EXAMPLES: 
    878             sage: SL2Z.__reduce__() 
    879             (<function _SL2Z_ref at ...>, ()) 
    880         """ 
    881         return _SL2Z_ref, () 
    882  
    883     def _repr_(self): 
    884         """ 
    885         Return the string representation of self. 
    886  
    887         EXAMPLES: 
    888             sage: SL2Z._repr_() 
    889             'Modular Group SL(2,Z)' 
    890         """ 
    891         return "Modular Group SL(2,Z)" 
    892  
    893     def _latex_(self): 
    894         r""" 
    895         Return the \LaTeX representation of self. 
    896          
    897         EXAMPLES: 
    898             sage: SL2Z._latex_() 
    899             '\\mbox{\\rm SL}_2(\\mathbf{Z})' 
    900             sage: latex(SL2Z) 
    901             \mbox{\rm SL}_2(\mathbf{Z}) 
    902         """ 
    903         return "\\mbox{\\rm SL}_2(%s)"%(ZZ._latex_()) 
    904  
    905     def is_subgroup(self, right): 
    906         """ 
    907         Return True if self is a subgroup of right. 
    908  
    909         EXAMPLES: 
    910             sage: SL2Z.is_subgroup(SL2Z) 
    911             True 
    912             sage: SL2Z.is_subgroup(Gamma1(1)) 
    913             True 
    914             sage: SL2Z.is_subgroup(Gamma0(6)) 
    915             False 
    916         """ 
    917         return right.level() == 1 
    918  
    919 SL2Z = SL2Z_class() 
    920  
    921 def _SL2Z_ref(): 
    922     """ 
    923     Return SL2Z. (Used for pickling SL2Z.) 
    924  
    925     EXAMPLES: 
    926         sage: sage.modular.congroup._SL2Z_ref() 
    927         Modular Group SL(2,Z) 
    928         sage: sage.modular.congroup._SL2Z_ref() is SL2Z 
    929         True 
    930     """ 
    931     return SL2Z 
    932  
    933 def is_Gamma1(x): 
    934     """ 
    935     Return True if x is a congruence subgroup of type Gamma1. 
    936  
    937     EXAMPLES: 
    938         sage: from sage.modular.congroup import is_Gamma1     
    939         sage: is_Gamma1(SL2Z) 
    940         True 
    941         sage: is_Gamma1(Gamma1(13)) 
    942         True 
    943         sage: is_Gamma1(Gamma0(6)) 
    944         False 
    945     """ 
    946     return (isinstance(x, Gamma1_class) or is_SL2Z(x)) 
    947  
    948 _gamma1_cache = {} 
    949 def Gamma1(N): 
    950     r""" 
    951     Return the congruence subgroup $\Gamma_1(N)$. 
    952  
    953     EXAMPLES: 
    954         sage: Gamma1(5) 
    955         Congruence Subgroup Gamma1(5) 
    956         sage: G = Gamma1(23) 
    957         sage: G is Gamma1(23) 
    958         True 
    959         sage: G == loads(dumps(G)) 
    960         True 
    961         sage: G is loads(dumps(G)) 
    962         True 
    963     """ 
    964     try: 
    965         return _gamma1_cache[N] 
    966     except KeyError: 
    967         _gamma1_cache[N] = Gamma1_class(N) 
    968         return _gamma1_cache[N] 
    969  
    970 class Gamma1_class(CongruenceSubgroup): 
    971     def __init__(self, level): 
    972         r""" 
    973         The congruence subgroup $\Gamma_1(N)$. 
    974  
    975         EXAMPLES: 
    976             sage: G = Gamma1(11); G 
    977             Congruence Subgroup Gamma1(11) 
    978             sage: loads(G.dumps()) == G 
    979             True 
    980         """ 
    981         CongruenceSubgroup.__init__(self, level) 
    982  
    983     def _repr_(self): 
    984         """ 
    985         Return the string representation of self. 
    986  
    987         EXAMPLES: 
    988             sage: Gamma1(133)._repr_() 
    989             'Congruence Subgroup Gamma1(133)' 
    990         """ 
    991         return "Congruence Subgroup Gamma1(%s)"%self.level() 
    992      
    993     def __reduce__(self): 
    994         """ 
    995         Used for pickling self. 
    996  
    997         EXAMPLES: 
    998             sage: Gamma1(82).__reduce__() 
    999             (<function Gamma1 at ...>, (82,)) 
    1000         """ 
    1001         return Gamma1, (self.level(),) 
    1002  
    1003     def _latex_(self): 
    1004         r""" 
    1005         Return the \LaTeX representation of self. 
    1006          
    1007         EXAMPLES: 
    1008             sage: Gamma1(3)._latex_() 
    1009             '\\Gamma_1(3)' 
    1010             sage: latex(Gamma1(3)) 
    1011             \Gamma_1(3) 
    1012         """ 
    1013         return "\\Gamma_1(%s)"%self.level() 
    1014  
    1015     def __cmp__(self, right): 
    1016         """ 
    1017         Compare self to right. 
    1018  
    1019         EXAMPLES: 
    1020             sage: G = Gamma1(111) 
    1021             sage: G.__cmp__(Gamma1(111)) 
    1022             0 
    1023             sage: G.__cmp__(135) is not 0 
    1024             True 
    1025         """ 
    1026         if not is_Gamma1(right): 
    1027             if is_CongruenceSubgroup(right): 
    1028                 c = cmp(self.level(), right.level()) 
    1029                 if c: return c 
    1030             return cmp(type(self), type(right)) 
    1031         return cmp(self.level(), right.level()) 
    1032  
    1033     def is_even(self): 
    1034         """ 
    1035         Return True precisely if this subgroup contains the matrix -1. 
    1036  
    1037         EXAMPLES: 
    1038             sage: Gamma1(1).is_even() 
    1039             True 
    1040             sage: Gamma1(2).is_even() 
    1041             True 
    1042             sage: Gamma1(15).is_even() 
    1043             False 
    1044         """ 
    1045         return self.level() in [1,2] 
    1046  
    1047     def is_subgroup(self, right): 
    1048         """ 
    1049         Return True if self is a subgroup of right. 
    1050  
    1051         EXAMPLES: 
    1052             sage: Gamma1(3).is_subgroup(SL2Z) 
    1053             True 
    1054             sage: Gamma1(3).is_subgroup(Gamma1(5)) 
    1055             False 
    1056             sage: Gamma1(3).is_subgroup(Gamma1(6)) 
    1057             False 
    1058             sage: Gamma1(6).is_subgroup(Gamma1(3)) 
    1059             True 
    1060             sage: Gamma1(6).is_subgroup(Gamma0(2)) 
    1061             True 
    1062         """ 
    1063         if right.level() == 1: 
    1064             return True 
    1065         if is_Gamma0(right) or is_Gamma1(right): 
    1066             return self.level() % right.level() == 0 
    1067         raise NotImplementedError 
    1068  
    1069     def generators(self): 
    1070         r""" 
    1071         Return generators for this congruence subgroup. 
    1072  
    1073         The result is cached. 
    1074  
    1075         EXAMPLE: 
    1076             sage: for g in Gamma1(3).generators(): 
    1077             ...     print g 
    1078             ...     print '---' 
    1079             [1 1] 
    1080             [0 1] 
    1081             --- 
    1082             [ 31 -14] 
    1083             [ 51 -23] 
    1084             --- 
    1085             [-5  4] 
    1086             [-9  7] 
    1087             --- 
    1088             ... 
    1089             --- 
    1090             [4 3] 
    1091             [9 7] 
    1092             --- 
    1093             [ -5  -2] 
    1094             [-12  -5] 
    1095             --- 
    1096  
    1097         """ 
    1098         try: 
    1099             return self.__gens 
    1100         except AttributeError: 
    1101             from sage.modular.modsym.g1list import G1list 
    1102             from congroup_pyx import generators_helper 
    1103             level = self.level() 
    1104             gen_list = generators_helper(G1list(level), level, Mat2Z) 
    1105             self.__gens = [self(g, check=False) for g in gen_list] 
    1106             return self.__gens 
    1107  
    1108     def __call__(self, x, check=True): 
    1109         r""" 
    1110         Create an element of this congruence subgroup from x. 
    1111  
    1112         If the optional flag check is True (default), check whether 
    1113         x actually gives an element of self. 
    1114  
    1115         EXAMPLES: 
    1116             sage: G = Gamma1(5) 
    1117             sage: G([1, 0, -10, 1]) 
    1118             [ 1   0] 
    1119             [-10  1] 
    1120             sage: G(matrix(ZZ, 2, [6, 1, 5, 1])) 
    1121             [6  1] 
    1122             [5  1] 
    1123             sage: G([1, 1, 6, 7]) 
    1124             Traceback (most recent call last): 
    1125             ... 
    1126             TypeError: matrix must have diagonal entries (=1, 7) congruent to 1 modulo 5, and lower left entry (=6) divisible by 5 
    1127         """ 
    1128         if isinstance(x, CongruenceSubgroupElement) and x.parent() == self: 
    1129             return x 
    1130         x = CongruenceSubgroupElement(self, x, check=check) 
    1131         if not check: 
    1132             return x 
    1133          
    1134         a = x.a() 
    1135         c = x.c() 
    1136         d = x.d() 
    1137         N = self.level() 
    1138         if (a%N == 1) and (c%N == 0) and (d%N == 1): 
    1139             return x 
    1140         else: 
    1141             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) 
    1142  
    1143594_gammaH_cache = {} 
    1144595def GammaH(level, H): 
    1145596    r""" 
    1146     Return the congruence subgroup $\Gamma_H(N)$. 
     597    Return the congruence subgroup $\Gamma_H(N)$, which is the subgroup of 
     598    $SL_2(\Z)$ consisting of matrices of the form $\begin{pmatrix} a & b \\ 
     599    c & d \end{pmatrix$ with $N | c$ and $a, b \in H$, for $H$ a specified 
     600    subgroup of $(\Z/N\Z)^\times$. 
    1147601     
    1148602    INPUT: 
    1149603        level -- an integer 
     
    1182636    Return True if x is a congruence subgroup of type GammaH. 
    1183637 
    1184638    EXAMPLES: 
    1185         sage: from sage.modular.congroup import is_GammaH     
     639        sage: from sage.modular.congroup import is_GammaH 
    1186640        sage: is_GammaH(GammaH(13, [2])) 
    1187641        True 
    1188642        sage: is_GammaH(Gamma0(6)) 
     643        True 
     644        sage: is_GammaH(sage.modular.congroup.CongruenceSubgroup(5)) 
    1189645        False 
    1190646    """ 
    1191647    return isinstance(x, GammaH_class) 
     
    1297753 
    1298754    def __cmp__(self, other): 
    1299755        """ 
    1300         Compare self to right. 
     756        Compare self to right. The ordering on congruence subgroups is first by 
     757        level, then by the set of elements of H. Note that Gamma1 and Gamma0 
     758        groups are treated as instances of GammaH for the purposes of 
     759        comparison. 
    1301760 
    1302761        EXAMPLES: 
    1303762            sage: G = GammaH(86, [9]) 
     
    1305764            0 
    1306765            sage: G.__cmp__(GammaH(86, [11])) is not 0 
    1307766            True 
     767            sage: Gamma1(11) < Gamma0(11) 
     768            True 
     769            sage: Gamma1(11) == GammaH(11, []) 
     770            True 
     771            sage: Gamma0(11) == GammaH(11, [2]) 
     772            True 
    1308773        """ 
    1309774        if not is_CongruenceSubgroup(other): 
    1310775            return cmp(type(self), type(other)) 
     776 
     777        c = cmp(self.level(), other.level()) 
     778        if c: return c 
     779 
    1311780        if is_GammaH(other): 
    1312             c = cmp(self.level(), other.level()) 
    1313             if c: return c 
    1314781            return cmp(self._list_of_elements_in_H(), other._list_of_elements_in_H()) 
    1315782        return cmp(type(self), type(other)) 
    1316783 
     
    16371104 
    16381105        return (new_u, new_v) 
    16391106 
     1107    def reduce_cusp(self, c): 
     1108        r""" 
     1109        Compute a minimal representative for the given cusp c. Returns a cusp 
     1110        c' which is equivalent to the given cusp, and is in lowest terms with 
     1111        minimal positive denominator, and minimal positive numerator for that 
     1112        denominator.  
     1113         
     1114        Two cusps $u1/v1$ and $u2/v2$ are equivalent modulo $\Gamma_H(N)$ 
     1115        if and only if 
     1116            $v1 =  h*v2 (mod N)$ and $u1 =  h^(-1)*u2 (mod gcd(v1,N))$ 
     1117        or 
     1118            $v1 = -h*v2 (mod N)$ and $u1 = -h^(-1)*u2 (mod gcd(v1,N))$ 
     1119        for some $h \in H$.  
     1120 
     1121        EXAMPLES: 
     1122            sage: GammaH(6,[5]).reduce_cusp(Cusp(5,3)) 
     1123            1/3 
     1124            sage: GammaH(12,[5]).reduce_cusp(Cusp(8,9)) 
     1125            1/3 
     1126            sage: GammaH(12,[5]).reduce_cusp(Cusp(5,12)) 
     1127            Infinity 
     1128            sage: GammaH(12,[]).reduce_cusp(Cusp(5,12)) 
     1129            5/12 
     1130            sage: GammaH(21,[5]).reduce_cusp(Cusp(-9/14)) 
     1131            1/7 
     1132        """ 
     1133 
     1134        return self._reduce_cusp(c)[0] 
     1135 
    16401136    def _reduce_cusp(self, c): 
    16411137        r""" 
    1642         Compute a minimal representative for the given cusp c. 
    1643         Returns a pair (c', t), where c' is the minimal representative 
    1644         for the given cusp, and t is either 1 or -1, as explained 
    1645         below. 
    1646  
     1138        Compute a minimal representative for the given cusp c.  
     1139        Returns a pair (c', t), where c' is the minimal representative  
     1140        for the given cusp, and t is either 1 or -1, as explained  
     1141        below. Largely for internal use. 
     1142         
    16471143        The minimal representative for a cusp is the element in $P^1(Q)$ 
    16481144        in lowest terms with minimal positive denominator, and minimal 
    16491145        positive numerator for that denominator. 
     
    16681164            sage: GammaH(21,[5])._reduce_cusp(Cusp(-9/14)) 
    16691165            (1/7, 1) 
    16701166        """ 
     1167 
    16711168        N = int(self.level()) 
    16721169        Cusps = c.parent() 
    16731170        v = int(c.denominator() % N) 
     
    17501247                sign = s 
    17511248 
    17521249        return Cusps((u_min, val_min)), sign 
     1250      
     1251    def _find_cusps(self): 
     1252        r""" 
     1253            Return a set of inequivalent cusps for self, i.e. a set of 
     1254        representatives for the orbits of self on $\mathbb{P}^1(\mathbb{Q})$. 
     1255        These are returned in a reduced form; see self.reduce_cusp for the  
     1256        definition of reduced. 
     1257         
     1258        ALGORITHM: 
     1259            Lemma 3.2 in Cremona's 1997 book shows that for the action of 
     1260            Gamma1(N) on "signed projective space" $\Q^2 / (\Q_{\ge 0}^+)$, we 
     1261            have $u_1/v_1 \sim u_2 / v_2$ if and only if $v_1 = v_2 \bmod N$ 
     1262            and $u_1 = u_2 \bmod gcd(v_1, N)$. It follows that every orbit has 
     1263            a representative $u/v$ with $v \le N$ and $0 \le u \le gcd(v, N)$. 
     1264            We iterate through all pairs $(u,v)$ satisfying this.  
    17531265             
     1266            Having found a set containing at least one of every equivalence 
     1267            class modulo Gamma1(N), we can be sure of picking up every class 
     1268            modulo GammaH(N) since this contains Gamma1(N); and the reduce_cusp 
     1269            call does the checking to make sure we don't get too many 
     1270            duplicates. 
     1271 
     1272        EXAMPLES: 
     1273            sage: Gamma1(5)._find_cusps() 
     1274            {0, Infinity, 1/2, 2/5} 
     1275            sage: Gamma1(35)._find_cusps()  
     1276            {3/35, 9/10, 9/14, 11/35, 3/14, 9/35, 3/10, 11/14, 8/35, 4/7, 8/15, Infinity, 13/14, 16/35, 13/35, 0, 4/15, 1/13, 2/35, 1/11, 1/10, 1/17, 1/16, 1/15, 1/14, 1/7, 1/6, 1/5, 1/4, 1/3, 1/2, 6/35, 1/9, 1/8, 6/7, 3/5, 3/7, 7/10, 4/35, 2/5, 17/35, 2/7, 5/7, 1/12, 4/5, 5/14, 12/35, 2/15} 
     1277            sage: Gamma1(24)._find_cusps() == Gamma1(24).cusps(bdmap=True) 
     1278            True 
     1279            sage: GammaH(24, [13,17])._find_cusps() == GammaH(24,[13,17]).cusps(bdmap=True) 
     1280            True 
     1281        """ 
     1282 
     1283        s = [] 
     1284        N=self.level() 
     1285        for d in xrange(1, 1+N): 
     1286            w = arith.gcd(d, N) 
     1287            for a in xrange(1,(w==1 and 2) or w): 
     1288                if arith.gcd([a, d, w]) != 1:  
     1289                    continue 
     1290                while arith.gcd(a, d) != 1: 
     1291                    a += w 
     1292                s.append(self.reduce_cusp(cusps.Cusp(a,d))) 
     1293        return Set(s) 
     1294        
    17541295    def __call__(self, x, check=True): 
    17551296        r""" 
    17561297        Create an element of this congruence subgroup from x. 
     
    17881329            raise TypeError, "matrix must have lower right entry (=%s) congruent modulo %s to some element of H" %(d, N) 
    17891330 
    17901331 
     1332def is_Gamma0(x): 
     1333    """ 
     1334    Return True if x is a congruence subgroup of type Gamma0. 
     1335 
     1336    EXAMPLES: 
     1337        sage: from sage.modular.congroup import is_Gamma0 
     1338        sage: is_Gamma0(SL2Z) 
     1339        True 
     1340        sage: is_Gamma0(Gamma0(13)) 
     1341        True 
     1342        sage: is_Gamma0(Gamma1(6)) 
     1343        False 
     1344    """ 
     1345    return isinstance(x, Gamma0_class) 
     1346 
     1347_gamma0_cache = {} 
     1348def Gamma0(N): 
     1349    """ 
     1350    Return the congruence subgroup Gamma0(N). 
     1351 
     1352    EXAMPLES: 
     1353        sage: G = Gamma0(51) ; G 
     1354        Congruence Subgroup Gamma0(51) 
     1355        sage: G == Gamma0(51) 
     1356        True 
     1357        sage: G is Gamma0(51) 
     1358        True 
     1359    """ 
     1360    try: 
     1361        return _gamma0_cache[N] 
     1362    except KeyError: 
     1363        _gamma0_cache[N] = Gamma0_class(N) 
     1364        return _gamma0_cache[N] 
     1365 
     1366class Gamma0_class(GammaH_class): 
     1367    def __init__(self, level): 
     1368        r""" 
     1369        The congruence subgroup $\Gamma_0(N)$. 
     1370 
     1371        EXAMPLES: 
     1372            sage: G = Gamma0(11); G 
     1373            Congruence Subgroup Gamma0(11) 
     1374            sage: loads(G.dumps()) == G 
     1375            True 
     1376        """ 
     1377        GammaH_class.__init__(self, level, [int(x) for x in IntegerModRing(level).unit_gens()]) 
     1378 
     1379    def _repr_(self): 
     1380        """ 
     1381        Return the string representation of self. 
     1382 
     1383        EXAMPLES: 
     1384            sage: Gamma0(98)._repr_() 
     1385            'Congruence Subgroup Gamma0(98)' 
     1386        """ 
     1387        return "Congruence Subgroup Gamma0(%s)"%self.level() 
     1388 
     1389    def __reduce__(self): 
     1390        """ 
     1391        Used for pickling self. 
     1392 
     1393        EXAMPLES: 
     1394            sage: Gamma0(22).__reduce__() 
     1395            (<function Gamma0 at ...>, (22,)) 
     1396        """ 
     1397        return Gamma0, (self.level(),) 
     1398 
     1399    def _latex_(self): 
     1400        r""" 
     1401        Return the \LaTeX representation of self. 
     1402         
     1403        EXAMPLES: 
     1404            sage: Gamma0(20)._latex_() 
     1405            '\\Gamma_0(20)' 
     1406            sage: latex(Gamma0(20)) 
     1407            \Gamma_0(20) 
     1408        """ 
     1409        return "\\Gamma_0(%s)"%self.level() 
     1410 
     1411    def _generators_for_H(self): 
     1412        """ 
     1413        Return generators for the subgroup H of the units mod 
     1414        self.level() that defines self. 
     1415         
     1416        EXAMPLES: 
     1417            sage: Gamma0(15)._generators_for_H() 
     1418            [11, 7] 
     1419        """ 
     1420        try: 
     1421            return self.__generators_for_H 
     1422        except AttributeError: 
     1423            self.__generators_for_H = [int(x) for x in IntegerModRing(self.level()).unit_gens()] 
     1424            return self.__generators_for_H 
     1425 
     1426    def _list_of_elements_in_H(self): 
     1427        """ 
     1428        Returns a sorted list of Python ints that are representatives 
     1429        between 0 and N-1 of the elements of H. 
     1430 
     1431        EXAMPLES: 
     1432            sage: G = Gamma0(11) 
     1433            sage: G._list_of_elements_in_H() 
     1434            [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] 
     1435 
     1436            sage: G = Gamma0(6) 
     1437            sage: G._list_of_elements_in_H() 
     1438            [1, 5] 
     1439 
     1440            sage: G = Gamma0(1) 
     1441            sage: G._list_of_elements_in_H() 
     1442            [1] 
     1443        """ 
     1444        N = self.level() 
     1445        if N != 1: 
     1446            gcd = arith.gcd 
     1447            return [ x for x in range(1, N) if gcd(x, N) == 1 ] 
     1448        else: 
     1449            return [1] 
     1450     
     1451    def is_even(self): 
     1452        """ 
     1453        Return True precisely if this subgroup contains the matrix -1. 
     1454 
     1455        Since Gamma0(N) always contains the matrix -1, this always 
     1456        returns True. 
     1457 
     1458        EXAMPLES: 
     1459            sage: Gamma0(12).is_even() 
     1460            True 
     1461            sage: SL2Z.is_even() 
     1462            True 
     1463        """ 
     1464        return True 
     1465 
     1466    def is_subgroup(self, right): 
     1467        """ 
     1468        Return True if self is a subgroup of right. 
     1469 
     1470        EXAMPLES: 
     1471