def factorize_matrix(m,M): #assert is_in_Gamma_1(m,M,determinant_condition = False) assert m.det().abs() == 1 a,b,c,d = m.list() if QQ(a).denominator() != 1: raise RuntimeError #return [m] assert a % M == 1 aabs = ZZ(a).abs() Zm = Zmod(M) for alphamul in sorted(range(-aabs.sqrt(50)/M,aabs.sqrt(50)/M),key = lambda x: ZZ(x).abs()): alpha = 1 + M*alphamul if alpha.abs() >= aabs: continue delta0 = (Zm(alpha)**(-1)).lift() for delta in xrange(delta0-10*M,delta0+10*M,M): if alpha * delta == 1: continue gamma0 = ZZ( (alpha*delta -1) / M) c1vec = gamma0.divisors() for c1 in c1vec: ulentry = (a*delta-b*c1*M).abs() urentry = (b*alpha-a*gamma0/c1).abs() if ulentry < aabs and urentry < b.abs(): gamma = c1*M beta = ZZ(gamma0/c1) r1 = Matrix(QQ,2,2,[alpha,beta,gamma,delta]) r2 = m*r1.adjugate() assert r1.determinant() == 1 assert is_in_Gamma_1(r1,M,determinant_condition = False) assert is_in_Gamma_1(r1,M,determinant_condition = False) V1 = factorize_matrix(r1,M) V2 = factorize_matrix(r2,M) return V2 + V1 return [m]
def factorize_matrix(m,M): #assert is_in_Gamma_1(m,M,determinant_condition = False) assert m.det().abs() == 1 a,b,c,d = m.list() if QQ(a).denominator() != 1: raise RuntimeError #return [m] assert a % M == 1 aabs = ZZ(a).abs() Zm = Zmod(M) for alphamul in sorted(range(-aabs.sqrt(50)/M,aabs.sqrt(50)/M),key = lambda x: ZZ(x).abs()): alpha = 1 + M*alphamul if alpha.abs() >= aabs: continue delta0 = (Zm(alpha)**(-1)).lift() for delta in xrange(delta0-10*M,delta0+10*M,M): if alpha * delta == 1: continue gamma0 = ZZ( (alpha*delta -1) / M) c1vec = gamma0.divisors() for c1 in c1vec: ulentry = (a*delta-b*c1*M).abs() urentry = (b*alpha-a*gamma0/c1).abs() if ulentry < aabs and urentry < b.abs(): gamma = c1*M beta = ZZ(gamma0/c1) r1 = Matrix(QQ,2,2,[alpha,beta,gamma,delta]) r2 = m*r1.adjoint() assert r1.determinant() == 1 assert is_in_Gamma_1(r1,M,determinant_condition = False) assert is_in_Gamma_1(r1,M,determinant_condition = False) V1 = factorize_matrix(r1,M) V2 = factorize_matrix(r2,M) return V2 + V1 return [m]
def find_matrix_from_cusp(self, cusp): r''' Returns a matrix gamma and a cusp representative modulo Gamma0(N) (c2:d2), represented as a matrix (a,b;c,d), such that gamma * cusp = (c2:d2). ''' a, c = cusp reduction_table, _ = self.cusp_reduction_table() P = self.get_P1List() if hasattr(P.N(),'number_field'): K = P.N().number_field() else: K = QQ # Find a matrix g = [a,b,c,d] in SL2(O_K) such that g * a/c = oo # Define (c1:d1) to be the rep in P1(O_K/N) such that (c1:d1) == (c:d). if c == 0: ## case cusp infinity: (a,c) should equal (1,0) a = 1 g = Matrix(2,2,[1,0,0,1]) c1, d1 = P.normalize(0, 1) else: if K == QQ: g0, d, b = ZZ(a).xgcd(-c) if g0 != 1: a /= g0 c /= g0 else: """ Compute gcd if a,c are coprime in F, and x,y such that ax + cy = 1. """ if a.parent() != c.parent(): raise ValueError('a,c not in the same field.') if a.gcd(c) != 1: raise ValueError('a,c not coprime.') d = next(o for o in K.ideal(c).residues() if a * o - 1 in K.ideal(c)) b = (a * d - 1) / c g = Matrix(2,2,[[d,-b],[-c,a]]) # the inverse c1, d1 = P.normalize(c, d) assert g.determinant() == 1 A, T = reduction_table[(c1,d1)] gamma = A.parent()(A * T * g) return gamma, A