/* Fonction nu */ nu(N)= { my(P,f,p); P=N; f=factor(N); for(i=1,matsize(f)[1], p=f[i,1]; P+=P/p); P; } /* Fonction nu_2 Nombre de points elliptiques d'ordre 2 de X_0(N) */ nu2(N)= { my(f,r,p); if(N%4==0,return(0)); f=factor(N); r=matsize(f)[1]; for(i=1,r, p=f[i,1]; if(kronecker(-1,p)==-1,return(0))); if(N%2,2^r,2^(r-1)); } /* Fonction nu_3 Nombre de points elliptiques d'ordre 3 de X_0(N) */ nu3(N)= { my(P,f,r,p); if(N%9==0,return(0)); if(N%2==0,return(0)); f=factor(N); r=matsize(f)[1]; for(i=1,r, p=f[i,1]; if(kronecker(-3,p)==-1,return(0))); if(N%3==0,2^(r-1),2^r); } /* Fonction nu_infini Plus rapide que sumdiv(N,d,eulerphi(gcd(d,N/d))) */ nuinf(N)= { my(P,f,p,e); P=1; f=factor(N); for(i=1,matsize(f)[1], p=f[i,1]; e=f[i,2]; if(e%2, P*=2*p^((e-1)/2), P*=p^(e/2-1)*(p+1))); P; } /* Indice de Gamma(N) dans SL_2(Z) */ indice_Gamma(N)= { my(P,f,p); P=N^3; f=factor(N); for(i=1,matsize(f)[1], p=f[i,1]; P-=P/p^2); P; } /* Indice de Gamma_0(N) dans SL_2(Z) */ indice_Gamma0(N)=nu(N); /* Indice de Gamma_1(N) dans SL_2(Z) */ { indice_Gamma1(N) = my(P,f,p); P=N^2; f=factor(N); for(i=1,matsize(f)[1], p=f[i,1]; P-=P\p^2); P; } /* Indice de PGamma(N) dans PSL_2(Z) */ indice_PGamma(N)= { if(N==1,return(1)); if(N==2,return(6)); indice_Gamma(N)/2; } /* Indice de PGamma_0(N) dans PSL_2(Z) */ indice_PGamma0(N)=indice_Gamma0(N); /* Indice de PGamma_1(N) dans PSL_2(Z) */ indice_PGamma1(N)= { if(N==1,return(1)); if(N==2,return(3)); indice_Gamma1(N)/2; } /* Nombre de pointes de X(N) */ nb_pointes_X(N)= { my(P,f,p); if(N==1,return(1)); if(N==2,return(3)); P=N^2; f=factor(N); for(i=1,matsize(f)[1], p=f[i,1]; P-=P/p^2); P/2; } /* Nombre de pointes de X_1(N) */ nb_pointes_X1(N)= { my(P,f,p,e,m); if(N==1,return(1)); if(N==2,return(2)); if(N==3,return(2)); if(N==4,return(3)); P=1; f=factor(N); for(i=1,matsize(f)[1], p=f[i,1]; e=f[i,2]; if(e==1, P*=2*p-2, P*=p^(e-2)*(p-1); if(e%2, m=floor(e/2); P*=2*((m+1)*p-m), P*=((e+1)*p-(e-1))))); P/2; } /* Nombre de pointes de X_0(N) */ nb_pointes_X0(N)=nuinf(N); /* Nombre de points elliptiques d'ordre 2 de X_0(N) */ nb_ell2_X0(N)=nu2(N); /* Nombre de points elliptiques d'ordre 3 de X_0(N) */ nb_ell3_X0(N)=nu3(N); /* Nombre de points elliptiques d'ordre 2 de X_1(N) */ nb_ell2_X1(N)= { if(N==1,return(1)); if(N==2,return(1)); if(N==3,return(0)); 0; } /* Nombre de points elliptiques d'ordre 3 de X_1(N) */ nb_ell3_X1(N)= { if(N==1,return(1)); if(N==2,return(0)); if(N==3,return(1)); 0; } /* Nombre de points elliptiques d'ordre 2 de X(N) */ nb_ell2_X(N)=(N==1); /* Nombre de points elliptiques d'ordre 3 de X(N) */ nb_ell3_X(N)=(N==1); /* Dimension de M_k(Gamma_0(N)) */ dim_Mk_Gamma0(k,N)= { if(k%2,return(0)); if(k<0,return(0)); if(k==0,return(1)); (k-1)*nu(N)/12+(floor(k/4)-(k-1)/4)*nu2(N)+(floor(k/3)-(k-1)/3)*nu3(N)+nuinf(N)/2; } /* Dimension de S_k(Gamma_0(N)) */ dim_Sk_Gamma0(k,N)= { if(k%2,return(0)); if(k<=0,return(0)); if(k==2,return(nu(N)/12-nu2(N)/4-nu3(N)/3-nuinf(N)/2+1)); (k-1)*nu(N)/12+(floor(k/4)-(k-1)/4)*nu2(N)+(floor(k/3)-(k-1)/3)*nu3(N)-nuinf(N)/2; } /* Genre de X_0(N) */ genre_X0(N)=dim_Sk_Gamma0(2,N); /* Genre de X_1(N) */ genre_X1(N)= { my(mu,n2,n3,ninf); mu=indice_PGamma1(N); n2=nb_ell2_X1(N); n3=nb_ell3_X1(N); ninf=nb_pointes_X1(N); 1+mu/12-n2/4-n3/3-ninf/2; } /* Genre de X(N) */ genre_X(N)= { my(mu,n2,n3,ninf); mu=indice_PGamma(N); n2=nb_ell2_X(N); n3=nb_ell3_X(N); ninf=nb_pointes_X(N); 1+mu/12-n2/4-n3/3-ninf/2; } /* Dimension de Eis_k(Gamma_0(N)) */ dim_Eisk_Gamma0(k,N)= { if(k%2,return(0)); if(k<0,return(0)); if(k==0,return(1)); if(k==2,return(nuinf(N)-1)); nuinf(N); } /* Dimension de S_k(Gamma_1(N)) */ dim_Sk_Gamma1(k,N)= { my(g,n2,n3,ninf,u,v); if(N<=2,return(dim_Sk_Gamma0(k,N))); \\ Cas N >= 3 if(k<=0,return(0)); \\ Cas k = 1 if(k==1,error("Dimension des formes de poids 1 non implementee !")); g=genre_X1(N); \\ Cas k = 2 if(k==2,return(g)); \\ Cas k >= 3 n2=nb_ell2_X1(N); n3=nb_ell3_X1(N); ninf=nb_pointes_X1(N); \\ Cas k pair >= 4 if(k%2==0,return((k-1)*(g-1)+n2*floor(k/4)+n3*floor(k/3)+(k/2-1)*ninf)); \\ Cas k impair >= 3 if(N==4,u=2;v=1,u=ninf;v=0); (k-1)*(g-1)+n2*floor(k/4)+n3*floor(k/3)+(k/2-1)*u+(k-1)/2*v; } /* Dimension de Eis_k(Gamma1(N)) */ dim_Eisk_Gamma1(k,N)= { my(ninf); if(N<=2,return(dim_Eisk_Gamma0(k,N))); \\ Cas N >= 3 if(k<0,return(0)); if(k==0,return(1)); ninf=nb_pointes_X1(N); \\ Cas k = 1 if(k==1, if(N==4,return(1),return(ninf/2))); \\ Cas k = 2 if(k==2,return(ninf-1)); \\ Cas k pair >= 4 if(k%2==0,return(ninf)); \\ Cas k impair >= 3 if(N==4,return(2)); ninf; } /* Dimension de M_k(Gamma_1(N)) */ dim_Mk_Gamma1(k,N)=dim_Sk_Gamma1(k,N)+dim_Eisk_Gamma1(k,N); /* Dimension de S_k(Gamma(N)) */ dim_Sk_Gamma(k,N)= { my(g,n2,n3,ninf,u,v); if(N==1,return(dim_Sk_Gamma0(k,1))); \\ Cas N >= 2 if(k<=0,return(0)); \\ Cas k = 1 if(k==1, if(N==2,return(0)); error("Dimension des formes de poids 1 non implementee !")); g=genre_X(N); \\ Cas k = 2 if(k==2,return(g)); \\ Cas k >= 3 n2=nb_ell2_X(N); n3=nb_ell3_X(N); ninf=nb_pointes_X(N); \\ Cas k pair >= 4 if(k%2==0,return((k-1)*(g-1)+n2*floor(k/4)+n3*floor(k/3)+(k/2-1)*ninf)); \\ Cas k impair >= 3 if(N==2,return(0)); \\ Cas N >= 3 (k-1)*(g-1)+n2*floor(k/4)+n3*floor(k/3)+(k/2-1)*ninf; } /* Dimension de Eis_k(Gamma(N)) */ dim_Eisk_Gamma(k,N)= { my(ninf); if(N==1,return(dim_Eisk_Gamma0(k,1))); \\ Cas N >= 2 if(k<0,return(0)); if(k==0,return(1)); ninf=nb_pointes_X(N); \\ Cas k = 1 if(k==1, if(N==2,return(0),return(ninf/2))); \\ Cas k = 2 if(k==2,return(ninf-1)); \\ Cas k pair >= 4 if(k%2==0,return(ninf)); \\ Cas k impair >= 3 if(N==2,return(0)); \\ Cas N >= 3 ninf; } /* Dimension de M_k(Gamma(N)) */ dim_Mk_Gamma(k,N)=dim_Sk_Gamma(k,N)+dim_Eisk_Gamma(k,N); /* Dimension de S_k^new(Gamma_0(N)) */ dim_Sknew_Gamma0(k,N)= { my(S,f,v,Nd,mumu); S=0; f=factor(N); v=vector(matsize(f)[1],i,[0,min(f[i,2],2)]); forvec(X=v, Nd=1; mumu=1; for(i=1,matsize(f)[1], Nd*=f[i,1]^(f[i,2]-X[i]); if(X[i]==1,mumu*=-2)); S+=mumu*dim_Sk_Gamma0(k,Nd)); S; } /* Dimension de S_k^new(Gamma_1(N)) */ dim_Sknew_Gamma1(k,N)= { my(S,f,v,Nd,mumu); S=0; f=factor(N); v=vector(matsize(f)[1],i,[0,min(f[i,2],2)]); forvec(X=v, Nd=1; mumu=1; for(i=1,matsize(f)[1], Nd*=f[i,1]^(f[i,2]-X[i]); if(X[i]==1,mumu*=-2)); S+=mumu*dim_Sk_Gamma1(k,Nd)); S; } /* Dimension des séries d'Eisentein nouvelles ?? */ /* BUGS il y a des dimensions négatives !!! */ dim_Eisknew_Gamma0(k,N)= { my(S,f,v,Nd,mumu); S=0; f=factor(N); v=vector(matsize(f)[1],i,[0,min(f[i,2],2)]); forvec(X=v, Nd=1; mumu=1; for(i=1,matsize(f)[1], Nd*=f[i,1]^(f[i,2]-X[i]); if(X[i]==1,mumu*=-2)); S+=mumu*dim_Eisk_Gamma0(k,Nd)); S; } dim_Eisknew_Gamma1(k,N)= { my(S,f,v,Nd,mumu); S=0; f=factor(N); v=vector(matsize(f)[1],i,[0,min(f[i,2],2)]); forvec(X=v, Nd=1; mumu=1; for(i=1,matsize(f)[1], Nd*=f[i,1]^(f[i,2]-X[i]); if(X[i]==1,mumu*=-2)); S+=mumu*dim_Eisk_Gamma1(k,Nd)); S; } /* Borne de Sturm */ \\ Référence : Théorème 9.18 dans [W. Stein, Modular Forms, A Computational Approach] \\ La borne de Sturm est un entier B tel que pour tout f \\ dans M_k(Gamma), si a_n(f) = 0 pour tout 0 <= n <= B, \\ alors f = 0. Cette condition signifie f = O(x^{B+1}), \\ où x est un paramètre local en la pointe infinie \\ (pour Gamma = Gamma(N), on a x = q^{1/N}, et pour \\ Gamma = Gamma_1(N) ou Gamma_0(N), on a x = q). \\ L'entier B donné ici n'est pas le plus petit entier \\ vérifiant cette propriété. \\ Pour la preuve, voir ma note "Sturm bounds for general \\ congruence subgroups" : https://perso.ens-lyon.fr/francois.brunault/recherche/Sturm-bound-general.pdf \\ \\ Y a-t-il une autre preuve de tout ça en utilisant Shimura ? \\ cf. Shimura, Intro Arithm Theory Autom Forms, Prop. 2.16, Prop. 1.40 Borne_Sturm_Gamma(k, N)= { my(indice); indice = indice_PGamma(N); floor(k*indice/12); } Borne_Sturm_Gamma1(k,N)= { my(indice); indice = indice_PGamma1(N); floor(k*indice/12); } Borne_Sturm_Gamma0(k,N)= { my(indice); indice = indice_PGamma0(N); floor(k*indice/12); }