Path: blob/master/sage/modular/modform/half_integral.py
4048 views
r"""1Compute spaces of half-integral weight modular forms23Based on an algorithm in Basmaji's thesis.45AUTHORS:67- William Stein (2007-08)8"""910from sage.matrix.all import MatrixSpace11from sage.modular.dirichlet import DirichletGroup1213import constructor1415from theta import theta2_qexp, theta_qexp16from copy import copy1718def half_integral_weight_modform_basis(chi, k, prec):19r"""20A basis for the space of weight `k/2` forms with character21`\chi`. The modulus of `\chi` must be divisible by22`16` and `k` must be odd and `>1`.2324INPUT:252627- ``chi`` - a Dirichlet character with modulus28divisible by 162930- ``k`` - an odd integer = 13132- ``prec`` - a positive integer333435OUTPUT: a list of power series3637.. warning::38391. This code is very slow because it requests computation of a40basis of modular forms for integral weight spaces, and that41computation is still very slow.42432. If you give an input prec that is too small, then the output44list of power series may be larger than the dimension of the45space of half-integral forms.4647EXAMPLES:4849We compute some half-integral weight forms of level 16\*75051::5253sage: half_integral_weight_modform_basis(DirichletGroup(16*7).0^2,3,30)54[q - 2*q^2 - q^9 + 2*q^14 + 6*q^18 - 2*q^21 - 4*q^22 - q^25 + O(q^30),55q^2 - q^14 - 3*q^18 + 2*q^22 + O(q^30),56q^4 - q^8 - q^16 + q^28 + O(q^30),57q^7 - 2*q^15 + O(q^30)]5859The following illustrates that choosing too low of a precision can60give an incorrect answer.6162::6364sage: half_integral_weight_modform_basis(DirichletGroup(16*7).0^2,3,20)65[q - 2*q^2 - q^9 + 2*q^14 + 6*q^18 + O(q^20),66q^2 - q^14 - 3*q^18 + O(q^20),67q^4 - 2*q^8 + 2*q^12 - 4*q^16 + O(q^20),68q^7 - 2*q^8 + 4*q^12 - 2*q^15 - 6*q^16 + O(q^20),69q^8 - 2*q^12 + 3*q^16 + O(q^20)]7071We compute some spaces of low level and the first few possible72weights.7374::7576sage: half_integral_weight_modform_basis(DirichletGroup(16,QQ).1, 3, 10)77[]78sage: half_integral_weight_modform_basis(DirichletGroup(16,QQ).1, 5, 10)79[q - 2*q^3 - 2*q^5 + 4*q^7 - q^9 + O(q^10)]80sage: half_integral_weight_modform_basis(DirichletGroup(16,QQ).1, 7, 10)81[q - 2*q^2 + 4*q^3 + 4*q^4 - 10*q^5 - 16*q^7 + 19*q^9 + O(q^10),82q^2 - 2*q^3 - 2*q^4 + 4*q^5 + 4*q^7 - 8*q^9 + O(q^10),83q^3 - 2*q^5 - 2*q^7 + 4*q^9 + O(q^10)]84sage: half_integral_weight_modform_basis(DirichletGroup(16,QQ).1, 9, 10)85[q - 2*q^2 + 4*q^3 - 8*q^4 + 14*q^5 + 16*q^6 - 40*q^7 + 16*q^8 - 57*q^9 + O(q^10),86q^2 - 2*q^3 + 4*q^4 - 8*q^5 - 8*q^6 + 20*q^7 - 8*q^8 + 32*q^9 + O(q^10),87q^3 - 2*q^4 + 4*q^5 + 4*q^6 - 10*q^7 - 16*q^9 + O(q^10),88q^4 - 2*q^5 - 2*q^6 + 4*q^7 + 4*q^9 + O(q^10),89q^5 - 2*q^7 - 2*q^9 + O(q^10)]9091This example once raised an error (see trac #5792).9293::9495sage: half_integral_weight_modform_basis(trivial_character(16),9,10)96[q - 2*q^2 + 4*q^3 - 8*q^4 + 4*q^6 - 16*q^7 + 48*q^8 - 15*q^9 + O(q^10),97q^2 - 2*q^3 + 4*q^4 - 2*q^6 + 8*q^7 - 24*q^8 + O(q^10),98q^3 - 2*q^4 - 4*q^7 + 12*q^8 + O(q^10),99q^4 - 6*q^8 + O(q^10)]100101102ALGORITHM: Basmaji (page 55 of his Essen thesis, "Ein Algorithmus103zur Berechnung von Hecke-Operatoren und Anwendungen auf modulare104Kurven", http://wstein.org/scans/papers/basmaji/).105106Let `S = S_{k+1}(\epsilon)` be the space of cusp forms of107even integer weight `k+1` and character108`\varepsilon = \chi \psi^{(k+1)/2}`, where `\psi`109is the nontrivial mod-4 Dirichlet character. Let `U` be the110subspace of `S \times S` of elements `(a,b)` such111that `\Theta_2 a = \Theta_3 b`. Then `U` is112isomorphic to `S_{k/2}(\chi)` via the map113`(a,b) \mapsto a/\Theta_3`.114"""115116if chi.modulus() % 16:117raise ValueError, "the character must have modulus divisible by 16"118119if not k%2:120raise ValueError, "k (=%s) must be odd"%k121122if k < 3:123raise ValueError, "k (=%s) must be at least 3"%k124125chi = chi.minimize_base_ring()126psi = chi.parent()(DirichletGroup(4, chi.base_ring()).gen())127eps = chi*psi**((k+1) // 2)128eps = eps.minimize_base_ring()129M = constructor.ModularForms(eps, (k+1)//2)130C = M.cuspidal_subspace()131B = C.basis()132133# This computation of S below -- of course --dominates the whole function.134#from sage.misc.all import cputime135#tm = cputime()136#print "Computing basis..."137S = [f.q_expansion(prec) for f in B]138#print "Time to compute basis", cputime(tm)139140T2 = theta2_qexp(prec)141T3 = theta_qexp(prec)142n = len(S)143MS = MatrixSpace(M.base_ring(), 2*n, prec)144A = copy(MS.zero_matrix())145146for i in range(n):147T2f = T2*S[i]148T3f = T3*S[i]149for j in range(prec):150A[i, j] = T2f[j]151A[n+i, j] = -T3f[j]152153B = A.kernel().basis()154a_vec = [sum([b[i]*S[i] for i in range(n)]) for b in B]155if len(a_vec) == 0:156return []157R = a_vec[0].parent()158t3 = R(T3)159return [R(a) / t3 for a in a_vec]160161162163