def cusp_matrix(cusp): """ Returns a matrix `M` such that `M * \infinity == cusp`. INPUT: - `cusp` -- a number \in \QQ. OUTPUT: - A matrix `M` \in \SL_2(\ZZ) such that M * \infinity == cusp . """ if cusp == 0: return matrix(ZZ,2,2,[0,-1,1,0]) else: a = cusp.numerator() c = cusp.denominator() _div, d, b = orig_xgcd(a, -c) assert _div == 1 return matrix(ZZ,2,2,[a,b,c,d])
def xgcd(self, a, b): """ The extended Euclidean algorithm. Mostly a standard implementation with a few fast paths. For the generic case, it uses `self.divmod`. INPUT: - `a`, `b` -- two elements of `self.maxorder`. OUTPUT: - A tuple `(d, s, t)`, such that `d == a * s + b * t` and `d` divides both `s` and `t`. `d` is the greatest common divisor. These are all elements of `self.maxorder`. """ if a == b: return a, 1, 0 if a == -b: return a, 1, 0 if a == 1: return 1, 1, 0 if b == 1: return 1, 0, 1 if a == 0: return b, 0, 1 if b == 0: return a, 1, 0 a1,a2 = self.as_tuple_b(a) b1,b2 = self.as_tuple_b(b) if a2 == b2 == 0: return orig_xgcd(a1, b1) if a1 == b1 == 0: d,s,t = orig_xgcd(a2, b2) B2 = (self.D + self.Droot) / 2 return d * B2, s, t # a,b = map(self.field, [a,b]) # gcd = 1 # factors_a,factors_b = [dict(list(x.factor())) for x in [a,b]] # for q in factors_a.keys(): # if q in factors_b: # e = min(factors_a[q], factors_b[q]) # factors_a[q] -= e # factors_b[q] -= e # gcd *= q * e a,b = map(self.maxorder, [a,b]) euc_a = self.euclidean_func(a) euc_b = self.euclidean_func(b) if euc_a < euc_b: d,s,t = self.xgcd(b, a) return d,t,s # We have euc_b <= euc_a now. q,r = self.divmod(a, b) # q * b + r == a. assert q * b + r == a # => a - b*q == r d2,s2,t2 = self.xgcd(b, r) # d2 = b * s2 + r * t2 assert d2 == b * s2 + r * t2 # => d2 = b * s2 + (a - b*q) * t2 # => d2 = a * t2 + b * (s2 - q * t2) d = d2 s = _simplify(t2) t = _simplify(s2 - q * t2) assert d == a * s + b * t assert self.divides(a, d) assert self.divides(b, d) return d, s, t