def anlist_over_nf(E, bound): """ Caution: This method is slow, especially for curves of high conductor, or defined over number fields of high degree. The method is to take the Euler product form, and retrieve the coefficients by expanding each product factor as a power series. The bottleneck is counting points over good reductions. TODO: Cache this method: it is computed when initializing the class dokchitser, if cached would have .num_coeffs() of a_i stored. EXAMPLE:: sage: K.<i> = NumberField(x^2+1) sage: E = EllipticCurve(K,[0,-1,1,0,0]) sage: from psage.ellcurve.lseries.lseries_nf import anlist_over_nf sage: anlist_over_nf(E, 20) [0, 1, -2, 0, 2, 2, 0, 0, 0, -5, -4, 0, 0, 8, 0, 0, -4, -4, 10, 0, 4] """ conductor = E.conductor() coefficients = [0, 1] + [0] * (bound - 1) for p in prime_range(bound + 1): accuracy_p = int(math.floor(old_div(math.log(bound), math.log(p)))) + 1 series_p = get_coeffs_p_over_nf(E, p, accuracy_p, conductor) for i in range(1, accuracy_p): coefficients[p**i] = series_p[i] extend_multiplicatively_generic(coefficients) return coefficients
def anlist_over_nf(E, bound): """ Caution: This method is slow, especially for curves of high conductor, or defined over number fields of high degree. The method is to take the Euler product form, and retrieve the coefficients by expanding each product factor as a power series. The bottleneck is counting points over good reductions. TODO: Cache this method: it is computed when initializing the class dokchitser, if cached would have .num_coeffs() of a_i stored. EXAMPLE:: sage: K.<i> = NumberField(x^2+1) sage: E = EllipticCurve(K,[0,-1,1,0,0]) sage: from psage.ellcurve.lseries.lseries_nf import anlist_over_nf sage: anlist_over_nf(E, 20) [0, 1, -2, 0, 2, 2, 0, 0, 0, -5, -4, 0, 0, 8, 0, 0, -4, -4, 10, 0, 4] """ conductor = E.conductor() coefficients = [0,1] + [0]*(bound-1) for p in prime_range(bound+1): accuracy_p = int(math.floor(math.log(bound)/math.log(p))) + 1 series_p = get_coeffs_p_over_nf(E, p, accuracy_p, conductor) for i in range(1, accuracy_p): coefficients[p**i] = series_p[i] extend_multiplicatively_generic(coefficients) return coefficients
def anlist_over_sqrt5(E, bound): """ Compute the Dirichlet L-series coefficients, up to and including a_bound. The i-th element of the return list is a[i]. INPUT: - E -- elliptic curve over Q(sqrt(5)), which must have defining polynomial `x^2-x-1`. - ``bound`` -- integer OUTPUT: - list of integers of length bound + 1 EXAMPLES:: sage: from psage.ellcurve.lseries.lseries_nf import anlist_over_sqrt5 sage: K.<a> = NumberField(x^2-x-1); E = EllipticCurve([0,-a,a,0,0]) sage: v = anlist_over_sqrt5(E, 50); v [0, 1, 0, 0, -2, -1, 0, 0, 0, -4, 0, 3, 0, 0, 0, 0, 0, 0, 0, 5, 2, 0, 0, 0, 0, -4, 0, 0, 0, 11, 0, -6, 0, 0, 0, 0, 8, 0, 0, 0, 0, -1, 0, 0, -6, 4, 0, 0, 0, -6, 0] sage: len(v) 51 This function isn't super fast, but at least it will work in a few seconds up to `10^4`:: sage: t = cputime() sage: v = anlist_over_sqrt5(E, 10^4) sage: assert cputime(t) < 5 """ from . import aplist_sqrt5 from psage.number_fields.sqrt5.prime import primes_of_bounded_norm, Prime # Compute all of the prime ideals of the ring of integers up to the given bound primes = primes_of_bounded_norm(bound + 1) # Compute the traces of Frobenius: this is supposed to be the hard part v = aplist_sqrt5.aplist(E, bound + 1) # Compute information about the primes of bad reduction, in # particular the integers i such that primes[i] is a prime of bad # reduction. bad_primes = set([Prime(a.prime()) for a in E.local_data()]) # We compute the local factors of the L-series as power series in ZZ[T]. P = PowerSeriesRing(ZZ, 'T') T = P.gen() # Table of powers of T, so we don't have to compute T^4 (say) thousands of times. Tp = [T**i for i in range(5)] # For each prime, we write down the local factor. L_P = [] for i, P in enumerate(primes): inertial_deg = 2 if P.is_inert() else 1 a_p = v[i] if P in bad_primes: # bad reduction f = 1 - a_p * Tp[inertial_deg] else: # good reduction q = P.norm() f = 1 - a_p * Tp[inertial_deg] + q * Tp[2 * inertial_deg] L_P.append(f) # Use the local factors of the L-series to compute the Dirichlet # series coefficients of prime-power index. coefficients = [0, 1] + [0] * (bound - 1) i = 0 while i < len(primes): P = primes[i] if P.is_split(): s = L_P[i] * L_P[i + 1] i += 2 else: s = L_P[i] i += 1 p = P.p # We need enough terms t so that p^t > bound accuracy_p = int(math.floor(old_div(math.log(bound), math.log(p)))) + 1 series_p = s.add_bigoh(accuracy_p)**(-1) for j in range(1, accuracy_p): coefficients[p**j] = series_p[j] # Using multiplicativity, fill in the non-prime power Dirichlet # series coefficients. extend_multiplicatively_generic(coefficients) return coefficients
def elliptic_cm_form(E, n, prec, aplist_only=False, anlist_only=False): """ Return q-expansion of the CM modular form associated to the n-th power of the Grossencharacter associated to the elliptic curve E. INPUT: - E -- CM elliptic curve - n -- positive integer - prec -- positive integer - aplist_only -- return list only of ap for p prime - anlist_only -- return list only of an OUTPUT: - power series with integer coefficients EXAMPLES:: sage: from psage.modform.rational.special import elliptic_cm_form sage: f = CuspForms(121,4).newforms(names='a')[0]; f q + 8*q^3 - 8*q^4 + 18*q^5 + O(q^6) sage: E = EllipticCurve('121b') sage: elliptic_cm_form(E, 3, 7) q + 8*q^3 - 8*q^4 + 18*q^5 + O(q^7) sage: g = elliptic_cm_form(E, 3, 100) sage: g == f.q_expansion(100) True """ if not E.has_cm(): raise ValueError, "E must have CM" n = ZZ(n) if n <= 0: raise ValueError, "n must be positive" prec = ZZ(prec) if prec <= 0: return [] elif prec <= 1: return [ZZ(0)] elif prec <= 2: return [ZZ(0), ZZ(1)] # Derive formula for sum of n-th powers of roots a,p,T = SR.var('a,p,T') roots = (T**2 - a*T + p).roots(multiplicities=False) s = sum(alpha**n for alpha in roots).simplify_full() # Create fast callable expression from formula g = fast_callable(s.polynomial(ZZ)) # Compute aplist for the curve v = E.aplist(prec) # Use aplist to compute ap values for the CM form attached to n-th # power of Grossencharacter. P = prime_range(prec) if aplist_only: # case when we only want the a_p (maybe for computing an # L-series via Euler product) return [g(ap,p) for ap,p in zip(v,P)] # Default cause where we want all a_n anlist = [ZZ(0),ZZ(1)] + [None]*(prec-2) for ap,p in zip(v,P): anlist[p] = g(ap,p) # Fill in the prime power a_{p^r} for r >= 2. N = E.conductor() for p in P: prm2 = 1 prm1 = p pr = p*p pn = p**n e = 1 if N%p else 0 while pr < prec: anlist[pr] = anlist[prm1] * anlist[p] if e: anlist[pr] -= pn * anlist[prm2] prm2 = prm1 prm1 = pr pr *= p # fill in a_n with n divisible by at least 2 primes extend_multiplicatively_generic(anlist) if anlist_only: return anlist f = Integer_list_to_polynomial(anlist, 'q') return ZZ[['q']](f, prec=prec)
def elliptic_cm_form(E, n, prec, aplist_only=False, anlist_only=False): """ Return q-expansion of the CM modular form associated to the n-th power of the Grossencharacter associated to the elliptic curve E. INPUT: - E -- CM elliptic curve - n -- positive integer - prec -- positive integer - aplist_only -- return list only of ap for p prime - anlist_only -- return list only of an OUTPUT: - power series with integer coefficients EXAMPLES:: sage: from psage.modform.rational.special import elliptic_cm_form sage: f = CuspForms(121,4).newforms(names='a')[0]; f q + 8*q^3 - 8*q^4 + 18*q^5 + O(q^6) sage: E = EllipticCurve('121b') sage: elliptic_cm_form(E, 3, 7) q + 8*q^3 - 8*q^4 + 18*q^5 + O(q^7) sage: g = elliptic_cm_form(E, 3, 100) sage: g == f.q_expansion(100) True """ if not E.has_cm(): raise ValueError, "E must have CM" n = ZZ(n) if n <= 0: raise ValueError, "n must be positive" prec = ZZ(prec) if prec <= 0: return [] elif prec <= 1: return [ZZ(0)] elif prec <= 2: return [ZZ(0), ZZ(1)] # Derive formula for sum of n-th powers of roots a,p,T = SR.var('a,p,T') roots = (T**2 - a*T + p).roots(multiplicities=False) s = sum(alpha**n for alpha in roots).simplify_full() # Create fast callable expression from formula g = fast_callable(s.polynomial(ZZ)) # Compute aplist for the curve v = E.aplist(prec) # Use aplist to compute ap values for the CM form attached to n-th # power of Grossencharacter. P = prime_range(prec) if aplist_only: # case when we only want the a_p (maybe for computing an # L-series via Euler product) return [g(ap,p) for ap,p in zip(v,P)] # Default cause where we want all a_n anlist = [ZZ(0),ZZ(1)] + [None]*(prec-2) for ap,p in zip(v,P): anlist[p] = g(ap,p) # Fill in the prime power a_{p^r} for r >= 2. N = E.conductor() for p in P: prm2 = 1 prm1 = p pr = p*p pn = p**n e = 1 if N%p else 0 while pr < prec: anlist[pr] = anlist[prm1] * anlist[p] if e: anlist[pr] -= pn * anlist[prm2] prm2 = prm1 prm1 = pr pr *= p # fill in a_n with n divisible by at least 2 primes extend_multiplicatively_generic(anlist) if anlist_only: return anlist f = Integer_list_to_polynomial(anlist, 'q') return ZZ[['q']](f, prec=prec)
def anlist_over_sqrt5(E, bound): """ Compute the Dirichlet L-series coefficients, up to and including a_bound. The i-th element of the return list is a[i]. INPUT: - E -- elliptic curve over Q(sqrt(5)), which must have defining polynomial `x^2-x-1`. - ``bound`` -- integer OUTPUT: - list of integers of length bound + 1 EXAMPLES:: sage: from psage.ellcurve.lseries.lseries_nf import anlist_over_sqrt5 sage: K.<a> = NumberField(x^2-x-1); E = EllipticCurve([0,-a,a,0,0]) sage: v = anlist_over_sqrt5(E, 50); v [0, 1, 0, 0, -2, -1, 0, 0, 0, -4, 0, 3, 0, 0, 0, 0, 0, 0, 0, 5, 2, 0, 0, 0, 0, -4, 0, 0, 0, 11, 0, -6, 0, 0, 0, 0, 8, 0, 0, 0, 0, -1, 0, 0, -6, 4, 0, 0, 0, -6, 0] sage: len(v) 51 This function isn't super fast, but at least it will work in a few seconds up to `10^4`:: sage: t = cputime() sage: v = anlist_over_sqrt5(E, 10^4) sage: assert cputime(t) < 5 """ import aplist_sqrt5 from psage.number_fields.sqrt5.prime import primes_of_bounded_norm, Prime # Compute all of the prime ideals of the ring of integers up to the given bound primes = primes_of_bounded_norm(bound+1) # Compute the traces of Frobenius: this is supposed to be the hard part v = aplist_sqrt5.aplist(E, bound+1) # Compute information about the primes of bad reduction, in # particular the integers i such that primes[i] is a prime of bad # reduction. bad_primes = set([Prime(a.prime()) for a in E.local_data()]) # We compute the local factors of the L-series as power series in ZZ[T]. P = PowerSeriesRing(ZZ, 'T') T = P.gen() # Table of powers of T, so we don't have to compute T^4 (say) thousands of times. Tp = [T**i for i in range(5)] # For each prime, we write down the local factor. L_P = [] for i, P in enumerate(primes): inertial_deg = 2 if P.is_inert() else 1 a_p = v[i] if P in bad_primes: # bad reduction f = 1 - a_p*Tp[inertial_deg] else: # good reduction q = P.norm() f = 1 - a_p*Tp[inertial_deg] + q*Tp[2*inertial_deg] L_P.append(f) # Use the local factors of the L-series to compute the Dirichlet # series coefficients of prime-power index. coefficients = [0,1] + [0]*(bound-1) i = 0 while i < len(primes): P = primes[i] if P.is_split(): s = L_P[i] * L_P[i+1] i += 2 else: s = L_P[i] i += 1 p = P.p # We need enough terms t so that p^t > bound accuracy_p = int(math.floor(math.log(bound)/math.log(p))) + 1 series_p = s.add_bigoh(accuracy_p)**(-1) for j in range(1, accuracy_p): coefficients[p**j] = series_p[j] # Using multiplicativity, fill in the non-prime power Dirichlet # series coefficients. extend_multiplicatively_generic(coefficients) return coefficients