def local_coordinates_at_nonweierstrass(self, P, prec=20, name='t'): """ For a non-Weierstrass point `P = (a,b)` on the hyperelliptic curve `y^2 = f(x)`, return `(x(t), y(t))` such that `(y(t))^2 = f(x(t))`, where `t = x - a` is the local parameter. INPUT: - ``P = (a, b)`` -- a non-Weierstrass point on self - ``prec`` -- desired precision of the local coordinates - ``name`` -- gen of the power series ring (default: ``t``) OUTPUT: `(x(t),y(t))` such that `y(t)^2 = f(x(t))` and `t = x - a` is the local parameter at `P` EXAMPLES:: sage: R.<x> = QQ['x'] sage: H = HyperellipticCurve(x^5-23*x^3+18*x^2+40*x) sage: P = H(1,6) sage: x,y = H.local_coordinates_at_nonweierstrass(P,prec=5) sage: x 1 + t + O(t^5) sage: y 6 + t - 7/2*t^2 - 1/2*t^3 - 25/48*t^4 + O(t^5) sage: Q = H(-2,12) sage: x,y = H.local_coordinates_at_nonweierstrass(Q,prec=5) sage: x -2 + t + O(t^5) sage: y 12 - 19/2*t - 19/32*t^2 + 61/256*t^3 - 5965/24576*t^4 + O(t^5) AUTHOR: - Jennifer Balakrishnan (2007-12) """ d = P[1] if d == 0: raise TypeError( "P = %s is a Weierstrass point. Use local_coordinates_at_weierstrass instead!" % P) pol = self.hyperelliptic_polynomials()[0] L = PowerSeriesRing(self.base_ring(), name) t = L.gen() L.set_default_prec(prec) K = PowerSeriesRing(L, 'x') pol = K(pol) x = K.gen() b = P[0] f = pol(t + b) for i in range((RR(log(prec) / log(2))).ceil()): d = (d + f / d) / 2 return t + b + O(t**(prec)), d + O(t**(prec))
def local_coordinates_at_weierstrass(self, P, prec=20, name='t'): """ For a finite Weierstrass point on the hyperelliptic curve y^2 = f(x), returns (x(t), y(t)) such that (y(t))^2 = f(x(t)), where t = y is the local parameter. INPUT: - P a finite Weierstrass point on self - prec: desired precision of the local coordinates - name: gen of the power series ring (default: 't') OUTPUT: (x(t),y(t)) such that y(t)^2 = f(x(t)) and t = y is the local parameter at P EXAMPLES: sage: R.<x> = QQ['x'] sage: H = HyperellipticCurve(x^5-23*x^3+18*x^2+40*x) sage: A = H(4,0) sage: x,y = H.local_coordinates_at_weierstrass(A,prec =5) sage: x 4 + 1/360*t^2 - 191/23328000*t^4 + 7579/188956800000*t^6 + O(t^7) sage: y t + O(t^7) sage: B = H(-5,0) sage: x,y = H.local_coordinates_at_weierstrass(B,prec = 5) sage: x -5 + 1/1260*t^2 + 887/2000376000*t^4 + 643759/1587898468800000*t^6 + O(t^7) sage: y t + O(t^7) AUTHOR: - Jennifer Balakrishnan (2007-12) """ if P[1] != 0: raise TypeError, "P = %s is not a finite Weierstrass point. Use local_coordinates_at_nonweierstrass instead!" % P pol = self.hyperelliptic_polynomials()[0] L = PowerSeriesRing(self.base_ring(), name) t = L.gen() L.set_default_prec(prec + 2) K = PowerSeriesRing(L, 'x') pol = K(pol) x = K.gen() b = P[0] g = pol / (x - b) c = b + 1 / g(b) * t**2 f = pol - t**2 fprime = f.derivative() for i in range((RR(log(prec + 2) / log(2))).ceil()): c = c - f(c) / fprime(c) return c + O(t**(prec + 2)), t + O(t**(prec + 2))
def an_list(euler_factor_polynomial_fn, upperbound=100000, base_field=sage.rings.all.RationalField()): """ Takes a fn that gives for each prime the polynomial of the associated with the prime, given as a list, with independent coefficient first. This list is of length the degree+1. """ from sage.rings.fast_arith import prime_range from sage.rings.all import PowerSeriesRing from math import ceil, log PP = PowerSeriesRing(base_field, 'x', 1 + ceil(log(upperbound) / log(2.))) x = PP('x') prime_l = prime_range(upperbound + 1) result = [1 for i in range(upperbound)] for p in prime_l: euler_factor = (1 / (PP(euler_factor_polynomial_fn(p)))).padded_list() if len(euler_factor) == 1: for j in range(1, 1 + upperbound // p): result[j * p - 1] = 0 continue k = 1 while True: if p**k > upperbound: break for j in range(1, 1 + upperbound // (p**k)): if j % p == 0: continue result[j * p**k - 1] *= euler_factor[k] k += 1 return result
def _e_bounds(self, n, prec): p = self._p prec = max(2,prec) R = PowerSeriesRing(ZZ,'T',prec+1) T = R(R.gen(),prec +1) w = (1+T)**(p**n) - 1 return [infinity] + [valuation(w[j],p) for j in range(1,min(w.degree()+1,prec))]
def get_basic_integral(G, cocycle, gamma, center, j, prec=None): p = G.p HOC = cocycle.parent() V = HOC.coefficient_module() if prec is None: prec = V.precision_cap() Cp = Qp(p, prec) verbose('precision = %s' % prec) R = PolynomialRing(Cp, names='t') PS = PowerSeriesRing(Cp, names='z') t = R.gen() z = PS.gen() if prec is None: prec = V.precision_cap() try: coeff_depth = V.precision_cap() except AttributeError: coeff_depth = V.coefficient_module().precision_cap() resadd = ZZ(0) edgelist = G.get_covering(1)[1:] for rev, h in edgelist: a, b, c, d = [Cp(o) for o in G.embed(h, prec).list()] try: c0val = 0 pol = PS(d * z + b) / PS(c * z + a) pol -= Cp.teichmuller(center) pol = pol**j pol = pol.polynomial() newgamma = G.Gpn( G.reduce_in_amalgam(h * gamma.quaternion_rep, return_word=False)) if rev: # DEBUG newgamma = newgamma.conjugate_by(G.wp()) print 'reversing' if G.use_shapiro(): mu_e = cocycle.evaluate_and_identity(newgamma) else: mu_e = cocycle.evaluate(newgamma) if newgamma.quaternion_rep != 1: print 'newgamma = ', newgamma except AttributeError: verbose('...') continue if HOC._use_ps_dists: tmp = sum(a * mu_e.moment(i) for a, i in izip(pol.coefficients(), pol.exponents()) if i < len(mu_e._moments)) else: tmp = mu_e.evaluate_at_poly(pol, Cp, coeff_depth) resadd += tmp try: if G.use_shapiro(): tmp = cocycle.get_liftee().evaluate_and_identity(newgamma) else: tmp = cocycle.get_liftee().evaluate(newgamma) except IndexError: pass return resadd
def modular_ratio_space(chi): r""" Compute the space of 'modular ratios', i.e. meromorphic modular forms f level N and character chi such that f * E is a holomorphic cusp form for every Eisenstein series E of weight 1 and character 1/chi. Elements are returned as q-expansions up to precision R, where R is one greater than the weight 3 Sturm bound. EXAMPLES:: sage: chi = DirichletGroup(31,QQ).0 sage: sage.modular.modform.weight1.modular_ratio_space(chi) [q - 8/3*q^3 + 13/9*q^4 + 43/27*q^5 - 620/81*q^6 + 1615/243*q^7 + 3481/729*q^8 + O(q^9), q^2 - 8/3*q^3 + 13/9*q^4 + 70/27*q^5 - 620/81*q^6 + 1858/243*q^7 + 2752/729*q^8 + O(q^9)] """ from sage.modular.modform.constructor import EisensteinForms, CuspForms if chi(-1) == 1: return [] N = chi.modulus() chi = chi.minimize_base_ring() K = chi.base_ring() R = Gamma0(N).sturm_bound(3) + 1 verbose("Working precision is %s" % R, level=1) verbose("Coeff field is %s" % K, level=1) V = K**R I = V d = I.rank() t = verbose("Calculating Eisenstein forms in weight 1...", level=1) B0 = EisensteinForms(~chi, 1).q_echelon_basis(prec=R) B = [b + B0[0] for b in B0] verbose("Done (dimension %s)" % len(B), level=1, t=t) t = verbose("Calculating in weight 2...", level=1) C = CuspForms(Gamma0(N), 2).q_echelon_basis(prec=R) verbose("Done (dimension %s)" % len(C), t=t, level=1) t = verbose("Computing candidate space", level=1) for b in B: quots = (c / b for c in C) W = V.span(V(x.padded_list(R)) for x in quots) I = I.intersection(W) if I.rank() < d: verbose(" Cut down to dimension %s" % I.rank(), level=1) d = I.rank() if I.rank() == 0: break verbose("Done: intersection is %s-dimensional" % I.dimension(), t=t, level=1) A = PowerSeriesRing(K, 'q') return [A(x.list()).add_bigoh(R) for x in I.gens()]
def local_coordinates_at_weierstrass(self, P, prec=20, name='t'): """ For a finite Weierstrass point on the hyperelliptic curve y^2 = f(x), returns (x(t), y(t)) such that (y(t))^2 = f(x(t)), where t = y is the local parameter. INPUT: - P a finite Weierstrass point on self - prec: desired precision of the local coordinates - name: gen of the power series ring (default: 't') OUTPUT: (x(t),y(t)) such that y(t)^2 = f(x(t)) and t = y is the local parameter at P EXAMPLES: sage: R.<x> = QQ['x'] sage: H = HyperellipticCurve(x^5-23*x^3+18*x^2+40*x) sage: A = H(4, 0) sage: x, y = H.local_coordinates_at_weierstrass(A, prec=7) sage: x 4 + 1/360*t^2 - 191/23328000*t^4 + 7579/188956800000*t^6 + O(t^7) sage: y t + O(t^7) sage: B = H(-5, 0) sage: x, y = H.local_coordinates_at_weierstrass(B, prec=5) sage: x -5 + 1/1260*t^2 + 887/2000376000*t^4 + O(t^5) sage: y t + O(t^5) AUTHOR: - Jennifer Balakrishnan (2007-12) - Francis Clarke (2012-08-26) """ if P[1] != 0: raise TypeError( "P = %s is not a finite Weierstrass point. Use local_coordinates_at_nonweierstrass instead!" % P) L = PowerSeriesRing(self.base_ring(), name) t = L.gen() pol = self.hyperelliptic_polynomials()[0] pol_prime = pol.derivative() b = P[0] t2 = t**2 c = b + t2 / pol_prime(b) c = c.add_bigoh(prec) for _ in range(1 + log(prec, 2)): c -= (pol(c) - t2) / pol_prime(c) return (c, t.add_bigoh(prec))
def zeta_series(self, n, t): """ Return the zeta series. Compute a power series approximation to the zeta function of a scheme over a finite field. INPUT: - ``n`` -- the number of terms of the power series to compute - ``t`` -- the variable which the series should be returned OUTPUT: A power series approximating the zeta function of self EXAMPLES:: sage: P.<x> = PolynomialRing(GF(3)) sage: C = HyperellipticCurve(x^3+x^2+1) sage: R.<t> = PowerSeriesRing(Integers()) sage: C.zeta_series(4,t) 1 + 6*t + 24*t^2 + 78*t^3 + 240*t^4 + O(t^5) sage: (1+2*t+3*t^2)/(1-t)/(1-3*t) + O(t^5) 1 + 6*t + 24*t^2 + 78*t^3 + 240*t^4 + O(t^5) Note that this function depends on count_points, which is only defined for prime order fields for general schemes. Nonetheless, since :trac:`15108` and :trac:`15148`, it supports hyperelliptic curves over non-prime fields:: sage: C.base_extend(GF(9,'a')).zeta_series(4,t) 1 + 12*t + 120*t^2 + 1092*t^3 + 9840*t^4 + O(t^5) """ F = self.base_ring() if not F.is_finite(): raise TypeError( 'zeta functions only defined for schemes over finite fields') try: a = self.count_points(n) except AttributeError: raise NotImplementedError( 'count_points() required but not implemented') R = PowerSeriesRing(Rationals(), 'u') u = R.gen() temp = sum(a[i - 1] * (u.O(n + 1))**i / i for i in range(1, n + 1)) temp2 = temp.exp() return (temp2(t).O(n + 1))
def approximate_series(self, prec, name=None): """ Return the Laurent series with absolute precision ``prec`` approximated from this series. INPUT: - ``prec`` -- an integer - ``name`` -- name of the variable; if it is ``None``, the name of the variable of the series is used OUTPUT: a Laurent series with absolute precision ``prec`` EXAMPLES:: sage: L = LazyLaurentSeriesRing(ZZ, 'z') sage: z = L.gen() sage: f = (z - 2*z^3)^5/(1 - 2*z) sage: f z^5 + 2*z^6 - 6*z^7 - 12*z^8 + 16*z^9 + 32*z^10 - 16*z^11 + ... sage: g = f.approximate_series(10) sage: g z^5 + 2*z^6 - 6*z^7 - 12*z^8 + 16*z^9 + O(z^10) sage: g.parent() Power Series Ring in z over Integer Ring :: sage: h = (f^-1).approximate_series(3) sage: h z^-5 - 2*z^-4 + 10*z^-3 - 20*z^-2 + 60*z^-1 - 120 + 280*z - 560*z^2 + O(z^3) sage: h.parent() Laurent Series Ring in z over Integer Ring """ S = self.parent() if name is None: name = S.variable_name() if self.valuation() < 0: from sage.rings.all import LaurentSeriesRing R = LaurentSeriesRing(S.base_ring(), name=name) n = self.valuation() return R([self.coefficient(i) for i in range(n, prec)], n).add_bigoh(prec) else: from sage.rings.all import PowerSeriesRing R = PowerSeriesRing(S.base_ring(), name=name) return R([self.coefficient(i) for i in range(prec)]).add_bigoh(prec)
def theta_qexp(prec=10, var='q', K=ZZ, sparse=False): r""" Return the `q`-expansion of the standard `\theta` series ` \theta = 1 + 2\sum_{n=1}{^\infty} q^{n^2}. ` INPUT: - prec -- integer; the absolute precision of the output - var -- (default: 'q') variable name - K -- (default: ZZ) base ring of answer OUTPUT: a power series over K EXAMPLES:: sage: theta_qexp(25) 1 + 2*q + 2*q^4 + 2*q^9 + 2*q^16 + O(q^25) sage: theta_qexp(10) 1 + 2*q + 2*q^4 + 2*q^9 + O(q^10) sage: theta_qexp(100) 1 + 2*q + 2*q^4 + 2*q^9 + 2*q^16 + 2*q^25 + 2*q^36 + 2*q^49 + 2*q^64 + 2*q^81 + O(q^100) sage: theta_qexp(100, 't') 1 + 2*t + 2*t^4 + 2*t^9 + 2*t^16 + 2*t^25 + 2*t^36 + 2*t^49 + 2*t^64 + 2*t^81 + O(t^100) sage: theta_qexp(100, 't', GF(2)) 1 + O(t^100) sage: f = theta_qexp(20,sparse=True); f 1 + 2*q + 2*q^4 + 2*q^9 + 2*q^16 + O(q^20) sage: parent(f) Sparse Power Series Ring in q over Integer Ring """ prec = Integer(prec) if prec <= 0: raise ValueError("prec must be positive") if sparse: v = {} else: v = [Integer(0)] * prec v[0] = Integer(1) two = Integer(2) n = int(sqrt(prec)) if n*n != prec: n += 1 for m in xrange(1, n): v[m*m] = two R = PowerSeriesRing(K, sparse=sparse, names=var) return R(v, prec=prec)
def theta2_qexp(prec=10, var='q', K=ZZ, sparse=False): r""" Return the `q`-expansion of the series ` \theta_2 = \sum_{n odd} q^{n^2}. ` INPUT: - prec -- integer; the absolute precision of the output - var -- (default: 'q') variable name - K -- (default: ZZ) base ring of answer OUTPUT: a power series over K EXAMPLES:: sage: theta2_qexp(18) q + q^9 + O(q^18) sage: theta2_qexp(49) q + q^9 + q^25 + O(q^49) sage: theta2_qexp(100, 'q', QQ) q + q^9 + q^25 + q^49 + q^81 + O(q^100) sage: f = theta2_qexp(100, 't', GF(3)); f t + t^9 + t^25 + t^49 + t^81 + O(t^100) sage: parent(f) Power Series Ring in t over Finite Field of size 3 sage: theta2_qexp(200) q + q^9 + q^25 + q^49 + q^81 + q^121 + q^169 + O(q^200) sage: f = theta2_qexp(20,sparse=True); f q + q^9 + O(q^20) sage: parent(f) Sparse Power Series Ring in q over Integer Ring """ prec = Integer(prec) if prec <= 0: raise ValueError("prec must be positive") if sparse: v = {} else: v = [Integer(0)] * prec one = Integer(1) n = int(sqrt(prec)) if n*n < prec: n += 1 for m in xrange(1, n, 2): v[m*m] = one R = PowerSeriesRing(K, sparse=sparse, names=var) return R(v, prec=prec)
def zeta_series(self, n, t): """ Return the zeta series. Compute a power series approximation to the zeta function of a scheme over a finite field. INPUT: - ``n`` - the number of terms of the power series to compute - ``t`` - the variable which the series should be returned OUTPUT: A power series approximating the zeta function of self EXAMPLES:: sage: P.<x> = PolynomialRing(GF(3)) sage: C = HyperellipticCurve(x^3+x^2+1) sage: R.<t> = PowerSeriesRing(Integers()) sage: C.zeta_series(4,t) 1 + 6*t + 24*t^2 + 78*t^3 + 240*t^4 + O(t^5) sage: (1+2*t+3*t^2)/(1-t)/(1-3*t) + O(t^5) 1 + 6*t + 24*t^2 + 78*t^3 + 240*t^4 + O(t^5) Note that this function depends on count_points, which is only defined for prime order fields:: sage: C.base_extend(GF(9,'a')).zeta_series(4,t) Traceback (most recent call last): ... NotImplementedError: Point counting only implemented for schemes over prime fields """ F = self.base_ring() if not F.is_finite(): raise TypeError, "Zeta functions only defined for schemes over finite fields" a = self.count_points(n) R = PowerSeriesRing(Rationals(), 'u') u = R.gen() temp = sum(a[i - 1] * (u.O(n + 1))**i / i for i in range(1, n + 1)) temp2 = temp.exp() return (temp2(t).O(n + 1))
def taylor_series(self, s, k=6, var='z'): r""" Return the first `k` terms of the Taylor series expansion of the `L`-series about `s`. This is returned as a formal power series in ``var``. INPUT: - ``s`` -- complex number; point about which to expand - ``k`` -- optional integer (default: 6), series is `O(``var``^k)` - ``var`` -- optional string (default: 'z'), variable of power series EXAMPLES:: sage: from sage.lfunctions.pari import lfun_number_field, LFunction sage: lf = lfun_number_field(QQ) sage: L = LFunction(lf) sage: L.taylor_series(2, 3) 1.64493406684823 - 0.937548254315844*z + 0.994640117149451*z^2 + O(z^3) sage: E = EllipticCurve('37a') sage: L = E.lseries().dokchitser(algorithm="pari") sage: L.taylor_series(1) 0.000000000000000 + 0.305999773834052*z + 0.186547797268162*z^2 - 0.136791463097188*z^3 + 0.0161066468496401*z^4 + 0.0185955175398802*z^5 + O(z^6) We compute a Taylor series where each coefficient is to high precision:: sage: E = EllipticCurve('389a') sage: L = E.lseries().dokchitser(200,algorithm="pari") sage: L.taylor_series(1,3) 2...e-63 + (...e-63)*z + 0.75931650028842677023019260789472201907809751649492435158581*z^2 + O(z^3) Check that :trac:`25402` is fixed:: sage: L = EllipticCurve("24a1").modular_form().lseries() sage: L.taylor_series(-1, 3) 0.000000000000000 - 0.702565506265199*z + 0.638929001045535*z^2 + O(z^3) """ pt = pari.Ser([s, 1], d=k) # s + x + O(x^k) B = PowerSeriesRing(self._CC, var) return B(pari.lfun(self._L, pt, precision=self.prec))
def an_list(euler_factor_polynomial_fn, upperbound=100000, base_field=sage.rings.all.RationalField()): """ Takes a fn that gives for each prime the Euler polynomial of the associated with the prime, given as a list, with independent coefficient first. This list is of length the degree+1. Output the first `upperbound` coefficients built from the Euler polys. Example: The `euler_factor_polynomial_fn` should in practice come from an L-function or data. For a simple example, we construct just the 2 and 3 factors of the Riemann zeta function, which have Euler factors (1 - 1*2^(-s))^(-1) and (1 - 1*3^(-s))^(-1). >>> euler = lambda p: [1, -1] if p <= 3 else [1, 0] >>> an_list(euler)[:20] [1, 1, 1, 1, 0, 1, 0, 1, 1, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0] """ from sage.rings.fast_arith import prime_range from sage.rings.all import PowerSeriesRing from math import ceil, log PP = PowerSeriesRing(base_field, 'x', 1 + ceil(log(upperbound) / log(2.))) prime_l = prime_range(upperbound + 1) result = [1 for i in range(upperbound)] for p in prime_l: euler_factor = (1 / (PP(euler_factor_polynomial_fn(p)))).padded_list() if len(euler_factor) == 1: for j in range(1, 1 + upperbound // p): result[j * p - 1] = 0 continue k = 1 while True: if p**k > upperbound: break for j in range(1, 1 + upperbound // (p**k)): if j % p == 0: continue result[j * p**k - 1] *= euler_factor[k] k += 1 return result
def __init__(self, group, prec): r""" Constructor for the Fourier expansion of some (specific, basic) modular forms. INPUT: - ``group`` -- A Hecke triangle group (default: HeckeTriangleGroup(3)). - ``prec`` -- An integer (default: 10), the default precision used in calculations in the LaurentSeriesRing or PowerSeriesRing. OUTPUT: The constructor for Fourier expansion with the specified settings. EXAMPLES:: sage: from sage.modular.modform_hecketriangle.series_constructor import MFSeriesConstructor sage: MFC = MFSeriesConstructor() sage: MFC Power series constructor for Hecke modular forms for n=3 with (basic series) precision 10 sage: MFC.group() Hecke triangle group for n = 3 sage: MFC.prec() 10 sage: MFC._series_ring Power Series Ring in q over Rational Field sage: MFSeriesConstructor(group=4) Power series constructor for Hecke modular forms for n=4 with (basic series) precision 10 sage: MFSeriesConstructor(group=5, prec=12) Power series constructor for Hecke modular forms for n=5 with (basic series) precision 12 sage: MFSeriesConstructor(group=infinity) Power series constructor for Hecke modular forms for n=+Infinity with (basic series) precision 10 """ self._group = group self._prec = prec self._series_ring = PowerSeriesRing(QQ, 'q', default_prec=self._prec)
def _l_action_(self, c): """ Multivariate power series support multiplication by any ring for which there is a supported action on the base ring. EXAMPLES:: sage: R.<s,t> = PowerSeriesRing(ZZ); R Multivariate Power Series Ring in s, t over Integer Ring sage: f = 1 + t + s + s*t + R.O(3) sage: g = f._l_action_(1/2); g 1/2 + 1/2*s + 1/2*t + 1/2*s*t + O(s, t)^3 sage: g.parent() Multivariate Power Series Ring in s, t over Rational Field sage: g = (1/2)*f; g 1/2 + 1/2*s + 1/2*t + 1/2*s*t + O(s, t)^3 sage: g.parent() Multivariate Power Series Ring in s, t over Rational Field sage: K = NumberField(x-3,'a') sage: g = K.random_element()*f sage: g.parent() Multivariate Power Series Ring in s, t over Number Field in a with defining polynomial x - 3 """ try: f = c * self._bg_value if f.parent() == self.parent()._bg_ps_ring(): return MPowerSeries(self.parent(), f, prec=f.prec()) else: from sage.rings.all import PowerSeriesRing new_parent = PowerSeriesRing(f.base_ring().base_ring(), num_gens=f.base_ring().ngens(), names=f.base_ring().gens()) return MPowerSeries(new_parent, f, prec=f.prec()) except (TypeError, AttributeError): raise TypeError("Action not defined.")
def series(self, n=2, quadratic_twist=+1, prec=5): r""" Returns the `n`-th approximation to the `p`-adic L-series as a power series in `T` (corresponding to `\gamma-1` with `\gamma=1+p` as a generator of `1+p\ZZ_p`). Each coefficient is a `p`-adic number whose precision is provably correct. Here the normalization of the `p`-adic L-series is chosen such that `L_p(J,1) = (1-1/\alpha)^2 L(J,1)/\Omega_J` where `\alpha` is the unit root INPUT: - ``n`` - (default: 2) a positive integer - ``quadratic_twist`` - (default: +1) a fundamental discriminant of a quadratic field, coprime to the conductor of the curve - ``prec`` - (default: 5) maximal number of terms of the series to compute; to compute as many as possible just give a very large number for ``prec``; the result will still be correct. ALIAS: power_series is identical to series. EXAMPLES:: sage: J = J0(188)[0] sage: p = 7 sage: L = J.padic_lseries(p) sage: L.is_ordinary() True sage: f = L.series(2) sage: f[0] O(7^20) sage: f[1].norm() 3 + 4*7 + 3*7^2 + 6*7^3 + 5*7^4 + 5*7^5 + 6*7^6 + 4*7^7 + 5*7^8 + 7^10 + 5*7^11 + 4*7^13 + 4*7^14 + 5*7^15 + 2*7^16 + 5*7^17 + 7^18 + 7^19 + O(7^20) """ n = ZZ(n) if n < 1: raise ValueError("n (={0}) must be a positive integer".format(n)) if not self.is_ordinary(): raise ValueError("p (={0}) must be an ordinary prime".format( self._p)) # check if the conditions on quadratic_twist are satisfied D = ZZ(quadratic_twist) if D != 1: if D % 4 == 0: d = D // 4 if not d.is_squarefree() or d % 4 == 1: raise ValueError( "quadratic_twist (={0}) must be a fundamental discriminant of a quadratic field" .format(D)) else: if not D.is_squarefree() or D % 4 != 1: raise ValueError( "quadratic_twist (={0}) must be a fundamental discriminant of a quadratic field" .format(D)) if gcd(D, self._p) != 1: raise ValueError( "quadratic twist (={0}) must be coprime to p (={1}) ". format(D, self._p)) if gcd(D, self._E.conductor()) != 1: for ell in prime_divisors(D): if valuation(self._E.conductor(), ell) > valuation(D, ell): raise ValueError( "can not twist a curve of conductor (={0}) by the quadratic twist (={1})." .format(self._E.conductor(), D)) p = self._p if p == 2 and self._normalize: print('Warning : For p=2 the normalization might not be correct !') #verbose("computing L-series for p=%s, n=%s, and prec=%s"%(p,n,prec)) # bounds = self._prec_bounds(n,prec) # padic_prec = max(bounds[1:]) + 5 padic_prec = 10 # verbose("using p-adic precision of %s"%padic_prec) res_series_prec = min(p**(n - 1), prec) verbose("using series precision of %s" % res_series_prec) ans = self._get_series_from_cache(n, res_series_prec, D) if not ans is None: verbose("found series in cache") return ans K = QQ gamma = K(1 + p) R = PowerSeriesRing(K, 'T', res_series_prec) T = R(R.gen(), res_series_prec) #L = R(0) one_plus_T_factor = R(1) gamma_power = K(1) teich = self.teichmuller(padic_prec) p_power = p**(n - 1) # F = Qp(p,padic_prec) verbose("Now iterating over %s summands" % ((p - 1) * p_power)) verbose_level = get_verbose() count_verb = 0 alphas = self.alpha() #print len(alphas) Lprod = [] self._emb = 0 if len(alphas) == 2: split = True else: split = False for alpha in alphas: L = R(0) self._emb = self._emb + 1 for j in range(p_power): s = K(0) if verbose_level >= 2 and j / p_power * 100 > count_verb + 3: verbose("%.2f percent done" % (float(j) / p_power * 100)) count_verb += 3 for a in range(1, p): if split: b = (teich[a]) % ZZ(p**n) b = b * gamma_power else: b = teich[a] * gamma_power s += self.measure(b, n, padic_prec, D, alpha) L += s * one_plus_T_factor one_plus_T_factor *= 1 + T gamma_power *= gamma Lprod = Lprod + [L] if len(Lprod) == 1: return Lprod[0] else: return Lprod[0] * Lprod[1]
def local_analytic_interpolation(self, P, Q): """ For points `P`, `Q` in the same residue disc, this constructs an interpolation from `P` to `Q` (in homogeneous coordinates) in a power series in the local parameter `t`, with precision equal to the `p`-adic precision of the underlying ring. INPUT: - P and Q points on self in the same residue disc OUTPUT: Returns a point `X(t) = ( x(t) : y(t) : z(t) )` such that: (1) `X(0) = P` and `X(1) = Q` if `P, Q` are not in the infinite disc (2) `X(P[0]^g/P[1]) = P` and `X(Q[0]^g/Q[1]) = Q` if `P, Q` are in the infinite disc EXAMPLES:: sage: R.<x> = QQ['x'] sage: H = HyperellipticCurve(x^3-10*x+9) sage: K = Qp(5,8) sage: HK = H.change_ring(K) A non-Weierstrass disc:: sage: P = HK(0,3) sage: Q = HK(5, 3 + 3*5^2 + 2*5^3 + 3*5^4 + 2*5^5 + 2*5^6 + 3*5^7 + O(5^8)) sage: x,y,z, = HK.local_analytic_interpolation(P,Q) sage: x(0) == P[0], x(1) == Q[0], y(0) == P[1], y.polynomial()(1) == Q[1] (True, True, True, True) A finite Weierstrass disc:: sage: P = HK.lift_x(1 + 2*5^2) sage: Q = HK.lift_x(1 + 3*5^2) sage: x,y,z = HK.local_analytic_interpolation(P,Q) sage: x(0) == P[0], x.polynomial()(1) == Q[0], y(0) == P[1], y(1) == Q[1] (True, True, True, True) The infinite disc:: sage: P = HK.lift_x(5^-2) sage: Q = HK.lift_x(4*5^-2) sage: x,y,z = HK.local_analytic_interpolation(P,Q) sage: x = x/z sage: y = y/z sage: x(P[0]/P[1]) == P[0] True sage: x(Q[0]/Q[1]) == Q[0] True sage: y(P[0]/P[1]) == P[1] True sage: y(Q[0]/Q[1]) == Q[1] True An error if points are not in the same disc:: sage: x,y,z = HK.local_analytic_interpolation(P,HK(1,0)) Traceback (most recent call last): ... ValueError: (5^-2 + O(5^6) : 5^-3 + 4*5^2 + 5^3 + 3*5^4 + O(5^5) : 1 + O(5^8)) and (1 + O(5^8) : 0 : 1 + O(5^8)) are not in the same residue disc AUTHORS: - Robert Bradshaw (2007-03) - Jennifer Balakrishnan (2010-02) """ prec = self.base_ring().precision_cap() if not self.is_same_disc(P, Q): raise ValueError("%s and %s are not in the same residue disc" % (P, Q)) disc = self.residue_disc(P) t = PowerSeriesRing(self.base_ring(), 't', prec).gen(0) if disc == self.change_ring(self.base_ring().residue_field())(0, 1, 0): x, y = self.local_coordinates_at_infinity(2 * prec) g = self.genus() return (x * t**(2 * g + 1), y * t**(2 * g + 1), t**(2 * g + 1)) if disc[1] != 0: x = P[0] + t * (Q[0] - P[0]) pts = self.lift_x(x, all=True) if pts[0][1][0] == P[1]: return pts[0] else: return pts[1] else: S = self.find_char_zero_weier_point(P) x, y = self.local_coord(S) a = P[1] b = Q[1] - P[1] y = a + b * t x = x.polynomial()(y).add_bigoh(x.prec()) return (x, y, 1)
def __init__(self, precision, p): self.__precision = precision self.__power_series_ring = PowerSeriesRing(GF(p), 'q') self.__p = int(p)
def frobenius_polynomial(self): r""" Return the characteristic polynomial of Frobenius. EXAMPLES: Hyperelliptic curves:: sage: p = 11 sage: x = PolynomialRing(GF(p),"x").gen() sage: f = x^7 + 4*x^2 + 10*x + 4 sage: CyclicCover(2, f).frobenius_polynomial() == \ ....: HyperellipticCurve(f).frobenius_polynomial() True sage: f = 2*x^5 + 4*x^3 + x^2 + 2*x + 1 sage: CyclicCover(2, f).frobenius_polynomial() == \ ....: HyperellipticCurve(f).frobenius_polynomial() True sage: f = 2*x^6 + 4*x^4 + x^3 + 2*x^2 + x sage: CyclicCover(2, f).frobenius_polynomial() == \ ....: HyperellipticCurve(f).frobenius_polynomial() True sage: p = 1117 sage: x = PolynomialRing(GF(p),"x").gen() sage: f = x^9 + 4*x^2 + 10*x + 4 sage: CyclicCover(2, f).frobenius_polynomial() == \ ....: HyperellipticCurve(f).frobenius_polynomial() # long time True sage: f = 2*x^5 + 4*x^3 + x^2 + 2*x + 1 sage: CyclicCover(2, f).frobenius_polynomial() == \ ....: HyperellipticCurve(f).frobenius_polynomial() True Superelliptic curves:: sage: p = 11 sage: x = PolynomialRing(GF(p),"x").gen() sage: CyclicCover(3, x^4 + 4*x^3 + 9*x^2 + 3*x + 1).frobenius_polynomial() x^6 + 21*x^4 + 231*x^2 + 1331 sage: CyclicCover(4, x^3 + x + 1).frobenius_polynomial() x^6 + 2*x^5 + 11*x^4 + 121*x^2 + 242*x + 1331 sage: p = 4999 sage: x = PolynomialRing(GF(p),"x").gen() sage: CyclicCover(4, x^3 - 1).frobenius_polynomial() == \ ....: CyclicCover(3, x^4 + 1).frobenius_polynomial() True sage: CyclicCover(3, x^4 + 4*x^3 + 9*x^2 + 3*x + 1).frobenius_polynomial() x^6 + 180*x^5 + 20988*x^4 + 1854349*x^3 + 104919012*x^2 + 4498200180*x + 124925014999 sage: CyclicCover(4,x^5 + x + 1).frobenius_polynomial() x^12 - 64*x^11 + 5018*x^10 - 488640*x^9 + 28119583*x^8 - 641791616*x^7 + 124245485932*x^6 - 3208316288384*x^5 + 702708407289583*x^4 - 61043359329111360*x^3 + 3133741752599645018*x^2 - 199800079984001599936*x + 15606259372500374970001 sage: CyclicCover(11, PolynomialRing(GF(1129), 'x')([-1] + [0]*(5-1) + [1])).frobenius_polynomial() # long time x^40 + 7337188909826596*x^30 + 20187877911930897108199045855206*x^20 + 24687045654725446027864774006541463602997309796*x^10 + 11320844849639649951608809973589776933203136765026963553258401 sage: CyclicCover(3, PolynomialRing(GF(1009^2), 'x')([-1] + [0]*(5-1) + [1])).frobenius_polynomial() # long time x^8 + 532*x^7 - 2877542*x^6 - 242628176*x^5 + 4390163797795*x^4 - 247015136050256*x^3 - 2982540407204025062*x^2 + 561382189105547134612*x + 1074309286591662654798721 A non-monic example checking that :trac:`29015` is fixed:: sage: a = 3 sage: K.<s>=GF(83^3); sage: R.<x>= PolynomialRing(K) sage: h = s*x^4 +x*3+ 8; sage: C = CyclicCover(a,h) sage: C.frobenius_polynomial() x^6 + 1563486*x^4 + 893980969482*x^2 + 186940255267540403 Non-superelliptic curves:: sage: p = 13 sage: x = PolynomialRing(GF(p),"x").gen() sage: C = CyclicCover(4, x^4 + 1) sage: C.frobenius_polynomial() x^6 - 6*x^5 + 3*x^4 + 60*x^3 + 39*x^2 - 1014*x + 2197 sage: R.<t> = PowerSeriesRing(Integers()) sage: C.projective_closure().zeta_series(2,t) 1 + 8*t + 102*t^2 + O(t^3) sage: C.frobenius_polynomial().reverse()(t)/((1-t)*(1-p*t)) + O(t^5) 1 + 8*t + 102*t^2 + 1384*t^3 + 18089*t^4 + O(t^5) sage: x = PolynomialRing(GF(11),"x").gen() sage: CyclicCover(4, x^6 - 11*x^3 + 70*x^2 - x + 961).frobenius_polynomial() # long time x^14 + 14*x^12 + 287*x^10 + 3025*x^8 + 33275*x^6 + 381997*x^4 + 2254714*x^2 + 19487171 sage: x = PolynomialRing(GF(4999),"x").gen() sage: CyclicCover(4, x^6 - 11*x^3 + 70*x^2 - x + 961).frobenius_polynomial() # long time x^14 - 4*x^13 - 2822*x^12 - 30032*x^11 + 37164411*x^10 - 152369520*x^9 + 54217349361*x^8 - 1021791160888*x^7 + 271032529455639*x^6 - 3807714457169520*x^5 + 4642764601604000589*x^4 - 18754988504199390032*x^3 - 8809934776794570547178*x^2 - 62425037490001499880004*x + 78015690603129374475034999 sage: p = 11 sage: x = PolynomialRing(GF(p),"x").gen() sage: CyclicCover(3, 5*x^3 - 5*x + 13).frobenius_polynomial() x^2 + 11 sage: CyclicCover(3, x^6 + x^4 - x^3 + 2*x^2 - x - 1).frobenius_polynomial() x^8 + 32*x^6 + 462*x^4 + 3872*x^2 + 14641 sage: p = 4999 sage: x = PolynomialRing(GF(p),"x").gen() sage: CyclicCover(3, 5*x^3 - 5*x + 13).frobenius_polynomial() x^2 - 47*x + 4999 sage: CyclicCover(3, x^6 + x^4 - x^3 + 2*x^2 - x - 1).frobenius_polynomial() x^8 + 122*x^7 + 4594*x^6 - 639110*x^5 - 82959649*x^4 - 3194910890*x^3 + 114804064594*x^2 + 15240851829878*x + 624500149980001 sage: p = 11 sage: x = PolynomialRing(GF(p),"x").gen() sage: CyclicCover(5, x^5 + x).frobenius_polynomial() # long time x^12 + 4*x^11 + 22*x^10 + 108*x^9 + 503*x^8 + 1848*x^7 + 5588*x^6 + 20328*x^5 + 60863*x^4 + 143748*x^3 + 322102*x^2 + 644204*x + 1771561 sage: CyclicCover(5, 2*x^5 + x).frobenius_polynomial() # long time x^12 - 9*x^11 + 42*x^10 - 108*x^9 - 47*x^8 + 1782*x^7 - 8327*x^6 + 19602*x^5 - 5687*x^4 - 143748*x^3 + 614922*x^2 - 1449459*x + 1771561 sage: p = 49999 sage: x = PolynomialRing(GF(p),"x").gen() sage: CyclicCover(5, x^5 + x ).frobenius_polynomial() # long time x^12 + 299994*x^10 + 37498500015*x^8 + 2499850002999980*x^6 + 93742500224997000015*x^4 + 1874812507499850001499994*x^2 + 15623125093747500037499700001 sage: CyclicCover(5, 2*x^5 + x).frobenius_polynomial() # long time x^12 + 299994*x^10 + 37498500015*x^8 + 2499850002999980*x^6 + 93742500224997000015*x^4 + 1874812507499850001499994*x^2 + 15623125093747500037499700001 TESTS:: sage: for _ in range(5): # long time ....: fail = False ....: p = random_prime(500, lbound=5) ....: for i in range(1, 4): ....: F = GF(p**i) ....: Fx = PolynomialRing(F, 'x') ....: b = F.random_element() ....: while b == 0: ....: b = F.random_element() ....: E = EllipticCurve(F, [0, b]) ....: C1 = CyclicCover(3, Fx([-b, 0, 1])) ....: C2 = CyclicCover(2, Fx([b, 0, 0, 1])) ....: frob = [elt.frobenius_polynomial() for elt in [E, C1, C2]] ....: if len(set(frob)) != 1: ....: E ....: C1 ....: C2 ....: frob ....: fail = True ....: break ....: if fail: ....: break ....: else: ....: True True """ self._init_frob() F = self.frobenius_matrix(self._N0) def _denominator(): R = PolynomialRing(ZZ, "T") T = R.gen() denom = R(1) lc = self._f.list()[-1] if lc == 1: # MONIC for i in range(2, self._delta + 1): if self._delta % i == 0: phi = euler_phi(i) G = IntegerModRing(i) ki = G(self._q).multiplicative_order() denom = denom * (T**ki - 1)**(phi // ki) return denom else: # Non-monic x = PolynomialRing(self._Fq, "x").gen() f = x**self._delta - lc L = f.splitting_field("a") roots = [r for r, _ in f.change_ring(L).roots()] roots_dict = dict([(r, i) for i, r in enumerate(roots)]) rootsfrob = [ L.frobenius_endomorphism(self._Fq.degree())(r) for r in roots ] m = zero_matrix(len(roots)) for i, r in enumerate(roots): m[i, roots_dict[rootsfrob[i]]] = 1 return R(R(m.characteristic_polynomial()) // (T - 1)) denom = _denominator() R = PolynomialRing(ZZ, "x") if self._nodenominators: min_val = 0 else: # are there any denominators in F? min_val = min( self._Qq(elt).valuation() for row in F.rows() for elt in row) if min_val >= 0: prec = _N0_nodenominators(self._p, self._genus, self._n) charpoly_prec = [ prec + i for i in reversed(range(1, self._genus + 1)) ] + [prec] * (self._genus + 1) cp = charpoly_frobenius(F, charpoly_prec, self._p, 1, self._n, denom.list()) return R(cp) else: cp = F.charpoly().reverse() denom = denom.reverse() PS = PowerSeriesRing(self._Zp, "T") cp = PS(cp) / PS(denom) cp = cp.padded_list(self._genus + 1) cpZZ = [None for _ in range(2 * self._genus + 1)] cpZZ[0] = 1 cpZZ[-1] = self._p**self._genus for i in range(1, self._genus + 1): cmod = cp[i] bound = binomial(2 * self._genus, i) * self._p**(i * self._n * 0.5) localmod = self._p**(ceil(log(bound, self._p))) c = cmod.lift() % localmod if c > bound: c = -(-cmod.lift() % localmod) cpZZ[i] = c if i != self._genus + 1: cpZZ[2 * self._genus - i] = c * self._p**(self._genus - i) cpZZ.reverse() return R(cpZZ)
def victor_miller_basis(k, prec=10, cusp_only=False, var='q'): r""" Compute and return the Victor Miller basis for modular forms of weight `k` and level 1 to precision `O(q^{prec})`. If ``cusp_only`` is True, return only a basis for the cuspidal subspace. INPUT: - ``k`` -- an integer - ``prec`` -- (default: 10) a positive integer - ``cusp_only`` -- bool (default: False) - ``var`` -- string (default: 'q') OUTPUT: A sequence whose entries are power series in ``ZZ[[var]]``. EXAMPLES:: sage: victor_miller_basis(1, 6) [] sage: victor_miller_basis(0, 6) [ 1 + O(q^6) ] sage: victor_miller_basis(2, 6) [] sage: victor_miller_basis(4, 6) [ 1 + 240*q + 2160*q^2 + 6720*q^3 + 17520*q^4 + 30240*q^5 + O(q^6) ] sage: victor_miller_basis(6, 6, var='w') [ 1 - 504*w - 16632*w^2 - 122976*w^3 - 532728*w^4 - 1575504*w^5 + O(w^6) ] sage: victor_miller_basis(6, 6) [ 1 - 504*q - 16632*q^2 - 122976*q^3 - 532728*q^4 - 1575504*q^5 + O(q^6) ] sage: victor_miller_basis(12, 6) [ 1 + 196560*q^2 + 16773120*q^3 + 398034000*q^4 + 4629381120*q^5 + O(q^6), q - 24*q^2 + 252*q^3 - 1472*q^4 + 4830*q^5 + O(q^6) ] sage: victor_miller_basis(12, 6, cusp_only=True) [ q - 24*q^2 + 252*q^3 - 1472*q^4 + 4830*q^5 + O(q^6) ] sage: victor_miller_basis(24, 6, cusp_only=True) [ q + 195660*q^3 + 12080128*q^4 + 44656110*q^5 + O(q^6), q^2 - 48*q^3 + 1080*q^4 - 15040*q^5 + O(q^6) ] sage: victor_miller_basis(24, 6) [ 1 + 52416000*q^3 + 39007332000*q^4 + 6609020221440*q^5 + O(q^6), q + 195660*q^3 + 12080128*q^4 + 44656110*q^5 + O(q^6), q^2 - 48*q^3 + 1080*q^4 - 15040*q^5 + O(q^6) ] sage: victor_miller_basis(32, 6) [ 1 + 2611200*q^3 + 19524758400*q^4 + 19715347537920*q^5 + O(q^6), q + 50220*q^3 + 87866368*q^4 + 18647219790*q^5 + O(q^6), q^2 + 432*q^3 + 39960*q^4 - 1418560*q^5 + O(q^6) ] sage: victor_miller_basis(40,200)[1:] == victor_miller_basis(40,200,cusp_only=True) True sage: victor_miller_basis(200,40)[1:] == victor_miller_basis(200,40,cusp_only=True) True AUTHORS: - William Stein, Craig Citro: original code - Martin Raum (2009-08-02): use FLINT for polynomial arithmetic (instead of NTL) """ k = Integer(k) if k % 2 == 1 or k == 2: return Sequence([]) elif k < 0: raise ValueError("k must be non-negative") elif k == 0: return Sequence([PowerSeriesRing(ZZ, var)(1).add_bigoh(prec)], cr=True) e = k.mod(12) if e == 2: e += 12 n = (k - e) // 12 if n == 0 and cusp_only: return Sequence([]) # If prec is less than or equal to the dimension of the space of # cusp forms, which is just n, then we know the answer, and we # simply return it. if prec <= n: q = PowerSeriesRing(ZZ, var).gen(0) err = bigO(q**prec) ls = [0] * (n + 1) if not cusp_only: ls[0] = 1 + err for i in range(1, prec): ls[i] = q**i + err for i in range(prec, n + 1): ls[i] = err return Sequence(ls, cr=True) F6 = eisenstein_series_poly(6, prec) if e == 0: A = Fmpz_poly(1) elif e == 4: A = eisenstein_series_poly(4, prec) elif e == 6: A = F6 elif e == 8: A = eisenstein_series_poly(8, prec) elif e == 10: A = eisenstein_series_poly(10, prec) else: # e == 14 A = eisenstein_series_poly(14, prec) if A[0] == -1: A = -A if n == 0: return Sequence([PowerSeriesRing(ZZ, var)(A.list()).add_bigoh(prec)], cr=True) F6_squared = F6**2 F6_squared._unsafe_mutate_truncate(prec) D = _delta_poly(prec) Fprod = F6_squared Dprod = D if cusp_only: ls = [Fmpz_poly(0)] + [A] * n else: ls = [A] * (n + 1) for i in xrange(1, n + 1): ls[n - i] *= Fprod ls[i] *= Dprod ls[n - i]._unsafe_mutate_truncate(prec) ls[i]._unsafe_mutate_truncate(prec) Fprod *= F6_squared Dprod *= D Fprod._unsafe_mutate_truncate(prec) Dprod._unsafe_mutate_truncate(prec) P = PowerSeriesRing(ZZ, var) if cusp_only: for i in xrange(1, n + 1): for j in xrange(1, i): ls[j] = ls[j] - ls[j][i] * ls[i] return Sequence([P(l.list()).add_bigoh(prec) for l in ls[1:]], cr=True) else: for i in xrange(1, n + 1): for j in xrange(i): ls[j] = ls[j] - ls[j][i] * ls[i] return Sequence([P(l.list()).add_bigoh(prec) for l in ls], cr=True)
def delta_qexp(prec=10, var='q', K=ZZ): """ Return the `q`-expansion of the weight 12 cusp form `\Delta` as a power series with coefficients in the ring K (`= \ZZ` by default). INPUT: - ``prec`` -- integer (default 10), the absolute precision of the output (must be positive) - ``var`` -- string (default: 'q'), variable name - ``K`` -- ring (default: `\ZZ`), base ring of answer OUTPUT: a power series over K in the variable ``var`` ALGORITHM: Compute the theta series .. math:: \sum_{n \ge 0} (-1)^n (2n+1) q^{n(n+1)/2}, a very simple explicit modular form whose 8th power is `\Delta`. Then compute the 8th power. All computations are done over `\ZZ` or `\ZZ` modulo `N` depending on the characteristic of the given coefficient ring `K`, and coerced into `K` afterwards. EXAMPLES:: sage: delta_qexp(7) q - 24*q^2 + 252*q^3 - 1472*q^4 + 4830*q^5 - 6048*q^6 + O(q^7) sage: delta_qexp(7,'z') z - 24*z^2 + 252*z^3 - 1472*z^4 + 4830*z^5 - 6048*z^6 + O(z^7) sage: delta_qexp(-3) Traceback (most recent call last): ... ValueError: prec must be positive sage: delta_qexp(20, K = GF(3)) q + q^4 + 2*q^7 + 2*q^13 + q^16 + 2*q^19 + O(q^20) sage: delta_qexp(20, K = GF(3^5, 'a')) q + q^4 + 2*q^7 + 2*q^13 + q^16 + 2*q^19 + O(q^20) sage: delta_qexp(10, K = IntegerModRing(60)) q + 36*q^2 + 12*q^3 + 28*q^4 + 30*q^5 + 12*q^6 + 56*q^7 + 57*q^9 + O(q^10) TESTS: Test algorithm with modular arithmetic (see also #11804):: sage: delta_qexp(10^4).change_ring(GF(13)) == delta_qexp(10^4, K=GF(13)) True sage: delta_qexp(1000).change_ring(IntegerModRing(5^100)) == delta_qexp(1000, K=IntegerModRing(5^100)) True AUTHORS: - William Stein: original code - David Harvey (2007-05): sped up first squaring step - Martin Raum (2009-08-02): use FLINT for polynomial arithmetic (instead of NTL) """ R = PowerSeriesRing(K, var) if K in (ZZ, QQ): return R(_delta_poly(prec).list(), prec, check=False) ch = K.characteristic() if ch > 0 and prec > 150: return R(_delta_poly_modulo(ch, prec), prec, check=False) else: # compute over ZZ and coerce return R(_delta_poly(prec).list(), prec, check=True)
def coeff_to_power_series(c, var='q', prec=None): """ Convert a list or dictionary giving coefficients to a sage power series. """ from sage.all import PowerSeriesRing, QQ return PowerSeriesRing(QQ, var)(c, prec)
def double_integral_zero_infty(Phi, tau1, tau2): p = Phi.parent().prime() K = tau1.parent() R = PolynomialRing(K, 'x') x = R.gen() R1 = PowerSeriesRing(K, 'r1') r1 = R1.gen() try: R1.set_default_prec(Phi.precision_absolute()) except AttributeError: R1.set_default_prec(Phi.precision_relative()) level = Phi._map._manin.level() E0inf = [M2Z([0, -1, level, 0])] E0Zp = [M2Z([p, a, 0, 1]) for a in range(p)] predicted_evals = num_evals(tau1, tau2) a, b, c, d = find_center(p, level, tau1, tau2).list() h = M2Z([a, b, c, d]) E = [h * e0 for e0 in E0Zp + E0inf] resadd = 0 resmul = 1 total_evals = 0 percentage = QQ(0) ii = 0 f = (x - tau2) / (x - tau1) while len(E) > 0: ii += 1 increment = QQ((100 - percentage) / len(E)) verbose( 'remaining %s percent (and done %s of %s evaluations)' % (RealField(10)(100 - percentage), total_evals, predicted_evals)) newE = [] for e in E: a, b, c, d = e.list() assert ZZ(c) % level == 0 try: y0 = f((a * r1 + b) / (c * r1 + d)) val = y0(y0.parent().base_ring()(0)) if all([xx.valuation(p) > 0 for xx in (y0 / val - 1).list()]): if total_evals % 100 == 0: Phi._map._codomain.clear_cache() pol = val.log(p_branch=0) + ( (y0.derivative() / y0).integral()) V = [0] * pol.valuation() + pol.shift( -pol.valuation()).list() try: phimap = Phi._map(M2Z([b, d, a, c])) except OverflowError: print(a, b, c, d) raise OverflowError, 'Matrix too large?' # mu_e0 = ZZ(phimap.moment(0).rational_reconstruction()) mu_e0 = ZZ(Phi._liftee._map(M2Z([b, d, a, c])).moment(0)) mu_e = [mu_e0] + [ phimap.moment(o).lift() for o in range(1, len(V)) ] resadd += sum(starmap(mul, izip(V, mu_e))) resmul *= val**mu_e0 percentage += increment total_evals += 1 else: newE.extend([e * e0 for e0 in E0Zp]) except ZeroDivisionError: #raise RuntimeError,'Probably not enough working precision...' newE.extend([e * e0 for e0 in E0Zp]) E = newE verbose('total evaluations = %s' % total_evals) val = resmul.valuation() return p**val * K.teichmuller(p**(-val) * resmul) * resadd.exp()
def __init__(self, precision, p): JacobiFormD1NNFactory_class.__init__(self, precision) self.__power_series_ring_modular = PowerSeriesRing(GF(p), 'q') self.__p = int(p)
def hecke_stable_subspace(chi, aux_prime=ZZ(2)): r""" Compute a q-expansion basis for S_1(chi). Results are returned as q-expansions to a certain fixed (and fairly high) precision. If more precision is required this can be obtained with :func:`modular_ratio_to_prec`. EXAMPLES:: sage: from sage.modular.modform.weight1 import hecke_stable_subspace sage: hecke_stable_subspace(DirichletGroup(59, QQ).0) [q - q^3 + q^4 - q^5 - q^7 - q^12 + q^15 + q^16 + 2*q^17 - q^19 - q^20 + q^21 + q^27 - q^28 - q^29 + q^35 + O(q^40)] """ # Deal quickly with the easy cases. if chi(-1) == 1: return [] N = chi.modulus() H = chi.kernel() G = GammaH(N, H) try: if ArithmeticSubgroup.dimension_cusp_forms(G, 1) == 0: verbose("no wt 1 cusp forms for N=%s, chi=%s by Riemann-Roch" % (N, chi._repr_short_()), level=1) return [] except NotImplementedError: pass from sage.modular.modform.constructor import EisensteinForms chi = chi.minimize_base_ring() K = chi.base_ring() # Auxiliary prime for Hecke stability method l = aux_prime while l.divides(N): l = l.next_prime() verbose("Auxiliary prime: %s" % l, level=1) # Compute working precision R = l * Gamma0(N).sturm_bound(l + 2) t = verbose("Computing modular ratio space", level=1) mrs = modular_ratio_space(chi) t = verbose("Computing modular ratios to precision %s" % R, level=1) qexps = [modular_ratio_to_prec(chi, f, R) for f in mrs] verbose("Done", t=t, level=1) # We want to compute the largest subspace of I stable under T_l. To do # this, we compute I intersect T_l(I) modulo q^(R/l), and take its preimage # under T_l, which is then well-defined modulo q^R. from sage.modular.modform.hecke_operator_on_qexp import hecke_operator_on_qexp t = verbose("Computing Hecke-stable subspace", level=1) A = PowerSeriesRing(K, 'q') r = R // l V = K**R W = K**r Tl_images = [hecke_operator_on_qexp(f, l, 1, chi) for f in qexps] qvecs = [V(x.padded_list(R)) for x in qexps] qvecs_trunc = [W(x.padded_list(r)) for x in qexps] Tvecs = [W(x.padded_list(r)) for x in Tl_images] I = V.submodule(qvecs) Iimage = W.span(qvecs_trunc) TlI = W.span(Tvecs) Jimage = Iimage.intersection(TlI) J = I.Hom(W)(Tvecs).inverse_image(Jimage) verbose("Hecke-stable subspace is %s-dimensional" % J.dimension(), t=t, level=1) if J.rank() == 0: return [] # The theory does not guarantee that J is exactly S_1(chi), just that it is # intermediate between S_1(chi) and M_1(chi). In every example I know of, # it is equal to S_1(chi), but just for honesty, we check this anyway. t = verbose("Checking cuspidality", level=1) JEis = V.span( V(x.padded_list(R)) for x in EisensteinForms(chi, 1).q_echelon_basis(prec=R)) D = JEis.intersection(J) if D.dimension() != 0: raise ArithmeticError("Got non-cuspidal form!") verbose("Done", t=t, level=1) qexps = Sequence(A(x.list()).add_bigoh(R) for x in J.gens()) return qexps