def systems_of_abs(self, bound): """ Return the absolute values of all systems of eigenvalues for self for primes up to bound. EXAMPLES:: sage: numerical_eigenforms(61).systems_of_abs(10) # rel tol 6e-14 [ [0.3111078174659775, 2.903211925911551, 2.525427560843529, 3.214319743377552], [1.0, 2.0000000000000027, 3.000000000000003, 1.0000000000000044], [1.4811943040920152, 0.8060634335253695, 3.1563251746586642, 0.6751308705666477], [2.170086486626034, 1.7092753594369208, 1.63089761381512, 0.46081112718908984], [3.0, 4.0, 6.0, 8.0] ] """ P = prime_range(bound) e = self.eigenvalues(P) v = Sequence([], cr=True) if len(e) == 0: return v for i in range(len(e[0])): v.append([abs(e[j][i]) for j in range(len(e))]) v.sort() v.set_immutable() return v
def multiple_of_order(self, maxp=None): """ Return a multiple of the order of this torsion group. The multiple is computed using characteristic polynomials of Hecke operators of odd index not dividing the level. INPUT: - ``maxp`` - (default: None) If maxp is None (the default), return gcd of best bound computed so far with bound obtained by computing GCD's of orders modulo p until this gcd stabilizes for 3 successive primes. If maxp is given, just use all primes up to and including maxp. EXAMPLES:: sage: J = J0(11) sage: G = J.rational_torsion_subgroup() sage: G.multiple_of_order(11) 5 sage: J = J0(389) sage: G = J.rational_torsion_subgroup(); G Torsion subgroup of Abelian variety J0(389) of dimension 32 sage: G.multiple_of_order() 97 sage: [G.multiple_of_order(p) for p in prime_range(3,11)] [92645296242160800, 7275, 291] sage: [G.multiple_of_order(p) for p in prime_range(3,13)] [92645296242160800, 7275, 291, 97] sage: [G.multiple_of_order(p) for p in prime_range(3,19)] [92645296242160800, 7275, 291, 97, 97, 97] :: sage: J = J0(33) * J0(11) ; J.rational_torsion_subgroup().order() Traceback (most recent call last): ... NotImplementedError: torsion multiple only implemented for Gamma0 The next example illustrates calling this function with a larger input and how the result may be cached when maxp is None:: sage: T = J0(43)[1].rational_torsion_subgroup() sage: T.multiple_of_order() 14 sage: T.multiple_of_order(50) 7 sage: T.multiple_of_order() 7 """ if maxp is None: try: return self.__multiple_of_order except AttributeError: pass bnd = ZZ(0) A = self.abelian_variety() if A.dimension() == 0: T = ZZ(1) self.__multiple_of_order = T return T N = A.level() if not (len(A.groups()) == 1 and is_Gamma0(A.groups()[0])): # to generalize to this case, you'll need to # (1) define a charpoly_of_frob function: # this is tricky because I don't know a simple # way to do this for Gamma1 and GammaH. Will # probably have to compute explicit matrix for # <p> operator (add to modular symbols code), # then compute some charpoly involving # that directly... # (2) use (1) -- see my MAGMA code. raise NotImplementedError( "torsion multiple only implemented for Gamma0") cnt = 0 if maxp is None: X = Primes() else: X = prime_range(maxp + 1) for p in X: if (2 * N) % p == 0: continue f = A.hecke_polynomial(p) b = ZZ(f(p + 1)) if bnd == 0: bnd = b else: bnd_last = bnd bnd = ZZ(gcd(bnd, b)) if bnd == bnd_last: cnt += 1 else: cnt = 0 if maxp is None and cnt >= 2: break # The code below caches the computed bound and # will be used if this function is called # again with maxp equal to None (the default). if maxp is None: # maxp is None but self.__multiple_of_order is # not set, since otherwise we would have immediately # returned at the top of this function self.__multiple_of_order = bnd else: # maxp is given -- record new info we get as # a gcd... try: self.__multiple_of_order = gcd(self.__multiple_of_order, bnd) except AttributeError: # ... except in the case when self.__multiple_of_order # was never set. In this case, we just set # it as long as the gcd stabilized for 3 in a row. if cnt >= 2: self.__multiple_of_order = bnd return bnd
def multiple_of_order(self, maxp=None): """ Return a multiple of the order of this torsion group. The multiple is computed using characteristic polynomials of Hecke operators of odd index not dividing the level. INPUT: - ``maxp`` - (default: None) If maxp is None (the default), return gcd of best bound computed so far with bound obtained by computing GCD's of orders modulo p until this gcd stabilizes for 3 successive primes. If maxp is given, just use all primes up to and including maxp. EXAMPLES:: sage: J = J0(11) sage: G = J.rational_torsion_subgroup() sage: G.multiple_of_order(11) 5 sage: J = J0(389) sage: G = J.rational_torsion_subgroup(); G Torsion subgroup of Abelian variety J0(389) of dimension 32 sage: G.multiple_of_order() 97 sage: [G.multiple_of_order(p) for p in prime_range(3,11)] [92645296242160800, 7275, 291] sage: [G.multiple_of_order(p) for p in prime_range(3,13)] [92645296242160800, 7275, 291, 97] sage: [G.multiple_of_order(p) for p in prime_range(3,19)] [92645296242160800, 7275, 291, 97, 97, 97] :: sage: J = J0(33) * J0(11) ; J.rational_torsion_subgroup().order() Traceback (most recent call last): ... NotImplementedError: torsion multiple only implemented for Gamma0 The next example illustrates calling this function with a larger input and how the result may be cached when maxp is None:: sage: T = J0(43)[1].rational_torsion_subgroup() sage: T.multiple_of_order() 14 sage: T.multiple_of_order(50) 7 sage: T.multiple_of_order() 7 """ if maxp is None: try: return self.__multiple_of_order except AttributeError: pass bnd = ZZ(0) A = self.abelian_variety() if A.dimension() == 0: T = ZZ(1) self.__multiple_of_order = T return T N = A.level() if not (len(A.groups()) == 1 and is_Gamma0(A.groups()[0])): # to generalize to this case, you'll need to # (1) define a charpoly_of_frob function: # this is tricky because I don't know a simple # way to do this for Gamma1 and GammaH. Will # probably have to compute explicit matrix for # <p> operator (add to modular symbols code), # then compute some charpoly involving # that directly... # (2) use (1) -- see my MAGMA code. raise NotImplementedError("torsion multiple only implemented for Gamma0") cnt = 0 if maxp is None: X = Primes() else: X = prime_range(maxp+1) for p in X: if (2*N) % p == 0: continue f = A.hecke_polynomial(p) b = ZZ(f(p+1)) if bnd == 0: bnd = b else: bnd_last = bnd bnd = ZZ(gcd(bnd, b)) if bnd == bnd_last: cnt += 1 else: cnt = 0 if maxp is None and cnt >= 2: break # The code below caches the computed bound and # will be used if this function is called # again with maxp equal to None (the default). if maxp is None: # maxp is None but self.__multiple_of_order is # not set, since otherwise we would have immediately # returned at the top of this function self.__multiple_of_order = bnd else: # maxp is given -- record new info we get as # a gcd... try: self.__multiple_of_order = gcd(self.__multiple_of_order, bnd) except AttributeError: # ... except in the case when self.__multiple_of_order # was never set. In this case, we just set # it as long as the gcd stabilized for 3 in a row. if cnt >= 2: self.__multiple_of_order = bnd return bnd