def generators(self): r""" Return generators for this congruence subgroup. The result is cached. EXAMPLE:: sage: for g in Gamma0(3).generators(): ... print g ... print '---' [1 1] [0 1] --- [-1 0] [ 0 -1] --- ... --- [ 1 0] [-3 1] --- """ from sage.modular.modsym.p1list import P1List from congroup_pyx import generators_helper level = self.level() if level == 1: # P1List isn't very happy working mod 1 return [ self([0,-1,1,0]), self([1,1,0,1]) ] gen_list = generators_helper(P1List(level), level, Mat2Z) return [self(g, check=False) for g in gen_list]
def get_representatives(self, t, N): r""" A helper function used in hecke_coeff that computes the right coset representatives of $\Gamma^0(t) \cap \Gamma_0(N) \ Gamma_0(N)$ where $\Gamma^0(t)$ is the subgroup of $SL(2,Z)$ where the upper right hand corner is divisible by $t$. NOTE We use the bijection $\Gamma^0(t)\SL(2,Z) \rightarrow P^1(\Z/t\Z)$ given by $A \mapsto [1:0]A$. """ if t == 1: return [(1, 0, 0, 1)] rep_list = [] for (x, y) in P1List(t): ## we know that (N, x, y) = 1 N1 = gcd(N, x) if N1 != 1: x = x + t * N // N1 ## we calculate a pair c,d satisfying a minimality condition ## to make later multiplications cheaper (_, d, c) = Integer(x)._xgcd(Integer(N * y), minimal=True) #print (x, y, -N * c, d) rep_list.append((x, y, -N * c, d)) return rep_list
def generators(self, algorithm="farey"): r""" Return generators for this congruence subgroup. INPUT: - ``algorithm`` (string): either ``farey`` (default) or ``todd-coxeter``. If ``algorithm`` is set to ``"farey"``, then the generators will be calculated using Farey symbols, which will always return a *minimal* generating set. See :mod:`~sage.modular.arithgroup.farey_symbol` for more information. If ``algorithm`` is set to ``"todd-coxeter"``, a simpler algorithm based on Todd-Coxeter enumeration will be used. This tends to return far larger sets of generators. EXAMPLE:: sage: Gamma0(3).generators() [ [1 1] [-1 1] [0 1], [-3 2] ] sage: Gamma0(3).generators(algorithm="todd-coxeter") [ [1 1] [-1 0] [ 1 -1] [1 0] [1 1] [-1 0] [ 1 0] [0 1], [ 0 -1], [ 0 1], [3 1], [0 1], [ 3 -1], [-3 1] ] sage: SL2Z.gens() ( [ 0 -1] [1 1] [ 1 0], [0 1] ) """ if self.level() == 1: # we return a fixed set of generators for SL2Z, for historical # reasons, which aren't the ones the Farey symbol code gives return [self([0, -1, 1, 0]), self([1, 1, 0, 1])] elif algorithm == "farey": return self.farey_symbol().generators() elif algorithm == "todd-coxeter": from sage.modular.modsym.p1list import P1List from .congroup import generators_helper level = self.level() if level == 1: # P1List isn't very happy working mod 1 return [self([0, -1, 1, 0]), self([1, 1, 0, 1])] gen_list = generators_helper(P1List(level), level) return [self(g, check=False) for g in gen_list] else: raise ValueError( "Unknown algorithm '%s' (should be either 'farey' or 'todd-coxeter')" % algorithm)
def schmidt_t5_eigenvalue_numerical(self, t): (tau1, z, tau2) = t from sage.libs.mpmath import mp from sage.libs.mpmath.mp import exp, pi from sage.libs.mpmath.mp import j as i if not Integer(self.__level()).is_prime(): raise ValueError("T_5 is only unique if the level is a prime") precision = ParamodularFormD2Filter_trace(self.precision()) s = Sequence([tau1, z, tau2]) if not is_ComplexField(s): mp_precision = 30 else: mp_precision = ceil(3.33 * s.universe().precision()) mp.dps = mp_precision p1list = P1List(self.level()) ## Prepare the operation for d_1(N) ## We have to invert the lifts since we will later use apply_GL_to_form d1_matrices = [p1list.lift_to_sl2z(i) for i in range(len(p1list))] d1_matrices = [(a_b_c_d[3], -a_b_c_d[1], -a_b_c_d[2], a_b_c_d[0]) for a_b_c_d in d1_matrices] ## Prepare the evaluation points corresponding to d_02(N) d2_points = list() for i in range(len(p1list())): (a, b, c, d) = p1list.lift_to_sl2z(i) tau1p = (a * tau1 + b) / (c * tau1 + d) zp = z / (c * tau1 + d) tau2p = tau2 - c * z**2 / (c * tau1 + d) (e_tau1p, e_zp, e_tau2p) = (exp(2 * pi * i * tau1p), exp(2 * pi * i * zp), exp(2 * pi * i * tau2p)) d2_points.append((e_tau1p, e_zp, e_tau2p)) (e_tau1, e_z, e_tau2) = (exp(2 * pi * i * tau1), exp(2 * pi * i * z), exp(2 * pi * i * tau2)) self_value = s.universe().zero() trans_value = s.universe().zero() for k in precision: (a, b, c) = apply_GL_to_form(self._P1List()(k[1]), k[0]) self_value = self_value + self[k] * e_tau1**a * e_z**b * e_tau2**c for m in d1_matrices: (ap, bp, cp) = apply_GL_to_form(m, (a, b, c)) for (e_tau1p, e_zp, e_tau2p) in d2_points: trans_value = trans_value + self[(( ap, bp, cp), 0)] * e_tau1p**ap * e_zp**bp * e_tau2p**cp return trans_value / self_value
def __init__(self, level, reduced = True) : if level == 1 : ## P1List(1) does not accept 1 as an index which is what we consider the ## unit element in GL(2, ZZ) raise NotImplementedError( "Level must not be 1") self.__level = level self.__reduced = reduced self.__p1list = P1List(level)
def __init__(self, precision, level, reduced = True) : self.__level = level if isinstance(precision, ParamodularFormD2Filter_trace) : precision = precision.index() elif isinstance(precision, ParamodularFormD2Filter_discriminant) : if precision.index() is infinity : precision = infinity else : precision = isqrt(precision.index() - 1) + 1 self.__trace = precision self.__reduced = reduced self.__p1list = P1List(level)
def get_P1List(self): """ Generates the projective line of O_F/N, where N is an ideal specified in the input, or computed from a parent object (e.g. arithmetic group). """ N = self.level ## Return object representing Projective line over O_F/N if hasattr(N,'number_field'): ## Base field not Q # from sage.modular.modsym.p1list_nf import P1NFList from .my_p1list_nf import P1NFList return P1NFList(N) else: ## Base field Q from sage.modular.modsym.p1list import P1List return P1List(N)
def __init__(self, disc, level, reduced = True) : self.__level = level if isinstance(disc, ParamodularFormD2Filter_discriminant) : disc = disc.index() if disc is infinity : self.__disc = disc else : oDmod = (-disc + 1) % (4 * level) Dmod = oDmod while Dmod > 0 : if not Mod(Dmod, 4 * level) : Dmod = Dmod - 1 else : break self.__disc = disc - (oDmod - Dmod) self.__reduced = reduced self.__p1list = P1List(level)
from sage.libs.mpmath.mp import exp, pi from sage.libs.mpmath.mp import j as i if not Integer(self.__level()).is_prime() : raise ValueError, "T_5 is only unique if the level is a prime" precision = ParamodularFormD2Filter_trace(self.precision()) s = Sequence([tau1, z, tau2]) if not is_ComplexField(s) : mp_precision = 30 else : mp_precision = ceil(3.33 * s.universe().precision()) mp.dps = mp_precision p1list = P1List(self.level()) ## Prepare the operation for d_1(N) ## We have to invert the lifts since we will later use apply_GL_to_form d1_matrices = [p1list.lift_to_sl2z(i) for i in xrange(len(p1list))] d1_matrices = map(lambda (a,b,c,d): (d,-b,-c,a), d1_matrices) ## Prepare the evaluation points corresponding to d_02(N) d2_points = list() for i in xrange(len(p1list())) : (a, b, c, d) = p1list.lift_to_sl2z(i) tau1p = (a * tau1 + b) / (c * tau1 + d) zp = z / (c * tau1 + d) tau2p = tau2 - c * z**2 / (c * tau1 + d) (e_tau1p, e_zp, e_tau2p) = (exp(2 * pi * i * tau1p), exp(2 * pi * i * zp), exp(2 * pi * i * tau2p))