def _basic_integral(self, a, j, twist=None): r""" Computes the integral .. MATH:: \int_{a+p\ZZ_p}(z-\omega(a))^jd\mu_\chi. If ``twist`` is ``None``, `\\chi` is the trivial character. Otherwise, ``twist`` can be a primitive quadratic character of conductor prime to `p`. """ #is this the negative of what we want? #if Phis is fixed for this p-adic L-function, we should make this method cached p = self._Phis.parent().prime() if twist is None: pass elif twist in ZZ: twist = kronecker_character(twist) if twist.is_trivial(): twist = None else: D = twist.level() assert(D.gcd(p) == 1) else: if twist.is_trivial(): twist = None else: assert((twist**2).is_trivial()) twist = twist.primitive_character() D = twist.level() assert(D.gcd(p) == 1) onDa = self._on_Da(a, twist)#self._Phis(Da) aminusat = a - self._Phis.parent().base_ring().base_ring().teichmuller(a) #aminusat = a - self._coefficient_ring.base_ring().teichmuller(a) try: ap = self._ap except AttributeError: self._ap = self._Phis.Tq_eigenvalue(p) #catch exception if not eigensymbol ap = self._ap if not twist is None: ap *= twist(p) if j == 0: return (~ap) * onDa.moment(0) if a == 1: #aminusat is 0, so only the j=r term is non-zero return (~ap) * (p ** j) * onDa.moment(j) #print "j =", j, "a = ", a ans = onDa.moment(0) * (aminusat ** j) #ans = onDa.moment(0) #print "\tr =", 0, " ans =", ans for r in range(1, j+1): if r == j: ans += binomial(j, r) * (p ** r) * onDa.moment(r) else: ans += binomial(j, r) * (aminusat ** (j - r)) * (p ** r) * onDa.moment(r) #print "\tr =", r, " ans =", ans #print " " return (~ap) * ans
def __init__(self, E, A, prec=53): r""" Class for the Gross-Zagier L-series. This is attached to a pair `(E,A)` where `E` is an elliptic curve over `\QQ` and `A` is an ideal class in an imaginary quadratic number field. For the exact definition, in the more general setting of modular forms instead of elliptic curves, see section IV of [GrossZagier]_. INPUT: - ``E`` -- an elliptic curve over `\QQ` - ``A`` -- an ideal class in an imaginary quadratic number field - ``prec`` -- an integer (default 53) giving the required precision EXAMPLES:: sage: e = EllipticCurve('37a') sage: K.<a> = QuadraticField(-40) sage: A = K.class_group().gen(0) sage: from sage.modular.modform.l_series_gross_zagier import GrossZagierLseries sage: G = GrossZagierLseries(e, A) TESTS:: sage: K.<b> = QuadraticField(131) sage: A = K.class_group().one() sage: G = GrossZagierLseries(e, A) Traceback (most recent call last): ... ValueError: A is not an ideal class in an imaginary quadratic field """ self._E = E self._N = N = E.conductor() self._A = A ideal = A.ideal() K = A.gens()[0].parent() D = K.disc() if not (K.degree() == 2 and D < 0): raise ValueError("A is not an ideal class in an" " imaginary quadratic field") Q = ideal.quadratic_form().reduced_form() epsilon = -kronecker_character(D)(N) self._dokchister = Dokchitser(N**2 * D**2, [0, 0, 1, 1], weight=2, eps=epsilon, prec=prec) self._nterms = nterms = Integer(self._dokchister.gp()('cflength()')) if nterms > 1e6: # just takes way to long raise ValueError("Too many terms: {}".format(nterms)) zeta_ord = ideal.number_field().zeta_order() an_list = gross_zagier_L_series(E.anlist(nterms + 1), Q, N, zeta_ord) self._dokchister.gp().set('a', an_list[1:]) self._dokchister.init_coeffs('a[k]', 1)
def __init__(self, E, A, prec=53): r""" Class for the Gross-Zagier L-series. This is attached to a pair `(E,A)` where `E` is an elliptic curve over `\QQ` and `A` is an ideal class in an imaginary quadratic number field. For the exact definition, in the more general setting of modular forms instead of elliptic curves, see section IV of [GrossZagier]_. INPUT: - ``E`` -- an elliptic curve over `\QQ` - ``A`` -- an ideal class in an imaginary quadratic number field - ``prec`` -- an integer (default 53) giving the required precision EXAMPLES:: sage: e = EllipticCurve('37a') sage: K.<a> = QuadraticField(-40) sage: A = K.class_group().gen(0) sage: from sage.modular.modform.l_series_gross_zagier import GrossZagierLseries sage: G = GrossZagierLseries(e, A) TESTS:: sage: K.<b> = QuadraticField(131) sage: A = K.class_group().one() sage: G = GrossZagierLseries(e, A) Traceback (most recent call last): ... ValueError: A is not an ideal class in an imaginary quadratic field """ self._E = E self._N = N = E.conductor() self._A = A ideal = A.ideal() K = A.gens()[0].parent() D = K.disc() if not(K.degree() == 2 and D < 0): raise ValueError("A is not an ideal class in an" " imaginary quadratic field") Q = ideal.quadratic_form().reduced_form() epsilon = - kronecker_character(D)(N) self._dokchister = Dokchitser(N ** 2 * D ** 2, [0, 0, 1, 1], weight=2, eps=epsilon, prec=prec) self._nterms = nterms = Integer(self._dokchister.num_coeffs()) if nterms > 1e6: # just takes way to long raise ValueError("Too many terms: {}".format(nterms)) zeta_ord = ideal.number_field().zeta_order() an_list = gross_zagier_L_series(E.anlist(nterms + 1), Q, N, zeta_ord) self._dokchister.gp().set('a', an_list[1:]) self._dokchister.init_coeffs('a[k]', 1)
def _evalf_(self, x, D, **kwargs): #numerical value D = Integer(D) if D % 4 > 1: raise ValueError('Not a discriminant') s = kronecker_character(D).lfunction(algorithm='lcalc').value(x).real() f = D.squarefree_part() if f % 4 > 1 and not D % 4: f *= 4 m = D // f if m != 1: return prod(1 - p**(-x) * kronecker(f, p) for p in prime_divisors(m)) * s return s
def _basic_integral(self, a, j, twist=None): r""" Computes the integral .. MATH:: \int_{a+p\ZZ_p}(z-\omega(a))^jd\mu_\chi. If ``twist`` is ``None``, `\\chi` is the trivial character. Otherwise, ``twist`` can be a primitive quadratic character of conductor prime to `p`. """ #is this the negative of what we want? #if Phis is fixed for this p-adic L-function, we should make this method cached p = self._Phis.parent().prime() if twist is None: pass elif twist in ZZ: twist = kronecker_character(twist) if twist.is_trivial(): twist = None else: D = twist.level() assert (D.gcd(p) == 1) else: if twist.is_trivial(): twist = None else: assert ((twist**2).is_trivial()) twist = twist.primitive_character() D = twist.level() assert (D.gcd(p) == 1) onDa = self._on_Da(a, twist) #self._Phis(Da) aminusat = a - self._Phis.parent().base_ring().base_ring().teichmuller( a) #aminusat = a - self._coefficient_ring.base_ring().teichmuller(a) try: ap = self._ap except AttributeError: self._ap = self._Phis.Tq_eigenvalue( p) #catch exception if not eigensymbol ap = self._ap if not twist is None: ap *= twist(p) if j == 0: return (~ap) * onDa.moment(0) if a == 1: #aminusat is 0, so only the j=r term is non-zero return (~ap) * (p**j) * onDa.moment(j) #print "j =", j, "a = ", a ans = onDa.moment(0) * (aminusat**j) #ans = onDa.moment(0) #print "\tr =", 0, " ans =", ans for r in range(1, j + 1): if r == j: ans += binomial(j, r) * (p**r) * onDa.moment(r) else: ans += binomial(j, r) * (aminusat **(j - r)) * (p**r) * onDa.moment(r) #print "\tr =", r, " ans =", ans #print " " return (~ap) * ans