Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemath
GitHub Repository: sagemath/sagesmc
Path: blob/master/src/ext/pari/buzzard/DimensionSk.g
8820 views
\\ DimensionSk.g, V2.2: program to compute dimensions of spaces of cusp
\\ forms with non-trivial character.
\\
\\ By Kevin Buzzard ([email protected])
\\
\\ Please report any problems to [email protected] .
\\
\\ Needs: genusn.g function S0(n,k)
\\
\\ This started off as my port of William's DimensionCuspForms magma script,
\\ and has grown since then.
\\
\\
\\ Version history:
\\
\\ V2.2: Fixed a bug in localevaluate() pointed out by Fernando Gouvea:
\\       s was used as a local variable but not declared as such.
\\       (this did actually cause problems with another script, Tpprog.g,
\\       which happened to use s for something else), 14/2/2002.
\\
\\ V2.1: minor tidying up and added a few \\ lines, 10/8/2001.
\\
\\ V2.0: severe tidying up, e.g. got rid of all the \s at end
\\ of lines and used the { trick instead; used local() for local
\\ variables instead of the old version, and so on, 9/8/2001.
\\
\\ V1.0, 26/7/00, just found it in the mess.
\\
\\ TODO: Optimise CohenOesterle2 and CohenOesterle3, currently they
\\       are ridiculous. See the magma version.
\\
\\ Remarks: has a superugly way of storing Dirichlet characters.
\\
\\ Syntax for characters:
\\
\\ eps is [N, i x 3 matrix], where eps[2][,1] is the primes dividing
\\ N, eps[2][,2] is the powers of these primes that divide N, and eps[2][,3]
\\ is the following: for p odd, p^n||N, it's t such that znprimroot(p^n)
\\ gets sent to exp(2*pi*i/phi(p^n))^t. And for p=2, it's
\\ 0 for 2^1, it's 0 (trivial) or -1 (non-trivial) for 2^2, and for p^n>=8
\\ it's either t>=0 for the even char sending 5 to exp(2*pi*i/p^(n-2))^t,
\\ or t<=-1 for the odd char sending 5 to exp(2*pi*i/p^(n-2))^(-1-t).
\\ (so either 0<=t<2^(n-2) or -1>=t>-1-2^(n-2) )

\\ Examples of creation:
\\
\\ TrivialCharacter(100) creates the trivial character of level 100.
\\ DirichletCharacter(45,[1,2]) creates the character of level 45
\\ which is the product of the character of level 9 sending
\\ znprimroot(9)=2 to exp(2*Pi*I/6)^1 and the character of level 5
\\ sending znprimroot(5)=2 to exp(2*Pi*I/4)^2=-1.

print("DimensionCuspForms(eps,k) computes the dimension of the space");
print("of cusp forms of character eps and weight k (note that eps knows");
print("its level!) The syntax for characters is rather complicated, see");
print("the detailed remarks at the beginning of the source code for");
print("more information.");


nearestinteger(z)=
{
  if(abs(z-round(z))>10^(-10),
    error("argument ",z," not near to an integer in nearestinteger()")
  ,
    real(round(z))
  )
}

DimensionCuspForms(eps,k)=
{
  local(N=0);
  if(k<=0,
    0
  ,
    if(k==1,
      error("Can't compute dimension of a space of cusp forms of weight one")
    );

    N=eps[1];
    if(istrivial(eps),
      S0(N,k)
    ,
      if(nearestinteger(evaluate(eps,N-1))!=(-1)^k,
        0
      ,
        nearestinteger(idxG0(N)*(k-1)/12 \
         +CohenOesterle1(eps,k)+CohenOesterle2(eps,k)+CohenOesterle3(eps,k))
      )
    )
  )
}

DimensionModularForms(eps,k)=
{
  local(N=0);
  if(k<=0,
    0
  ,
    if(k==1,
      error("Can't compute dimension of a space of modular
       forms of weight one")
    );
    \\ k>=2

    N=eps[1];
    if(nearestinteger(evaluate(eps,N-1))!=(-1)^k,
      0
    ,
      if(istrivial(eps),
        S0(N,k)+c0(N)-(k==2)
      ,
        nearestinteger(idxG0(N)*(k-1)/12 \
         -CohenOesterle1(eps,k)+CohenOesterle2(eps,k)+CohenOesterle3(eps,k) \
         -(k==2))
      )
    )
  )
}

CohenOesterle1(eps,k)=
{
  local(facN,f,facf);
  facN=matrix(matsize(eps[2])[1],2,i,j,eps[2][i,j]);
  f=charconductor(eps);
  facf=facN;facf[,2]=vectorv(matsize(facN)[1],i,valuation(f,facN[i,1]));

  (-1/2)*prod(i=1,matsize(facN)[1],lambda(facN[i,2],facf[i,2],facN[i,1]))
}

CohenOesterle2(eps,k)=
{
  local(N,gamma_k=0);
  N=eps[1];
  if(k%4==2,gamma_k=-1/4,if(k%4==0,gamma_k=1/4));
  if(gamma_k==0,
    0
  ,
    gamma_k*sum(i=0,N-1,if((i^2+1)%N==0,evaluate(eps,i),0))
  )
}

CohenOesterle3(eps,k)=
{
  local(N,mu_k=0);
  N=eps[1];
  if(k%3==2,mu_k=-1/3,if(k%3==0,mu_k=1/3));
  if(mu_k==0,
    0
  ,
    mu_k*sum(i=0,N-1,if((i^2+i+1)%N==0,evaluate(eps,i),0))
  )
}

lambda(r,s,p)=
{
  if(2*s<=r,
    if(r%2==0,
      p^(r\2)+p^((r\2)-1)
    ,
      2*p^((r-1)\2)
    )
  ,
   2*p^(r-s)
  )
}

evaluate(eps,n)=
{
  if(gcd(n,eps[1])>1,
    0
  ,
    if(istrivial(eps),
      1
    ,
      \\ main case here.
      prod(i=1,matsize(eps[2])[1],localevaluate(eps[2][i,],n))
    )
  )
}

localevaluate(v,n)=
{
  local(p,e,s,t);
  p=v[1];e=v[2];t=v[3];
  if(p==2, \\ deal with 2 separately
    if(e==1,
      1
    ,
      s=if(n%4==1,1,-1);
      if(t>=0,
        exp(2*Pi*I/2^(e-2)*t*z2log(Mod(n*s,2^e)))
      ,
        s*exp(2*Pi*I/2^(e-2)*(-1-t)*z2log(Mod(n*s,2^e)))
      )
    )
  ,
    exp(2*Pi*I/(p-1)/p^(e-1)*t*znlog(n,znprimroot(p^e)))
  )
}

charconductor(eps)=
{
  if(istrivial(eps),
    1
  ,
    prod(i=1,matsize(eps[2])[1],localconductor(eps[2][i,]))
  )
}

localconductor(v)=
{
  local(p,e,t,tp);
  p=v[1];e=v[2];t=v[3];
  if(p==2, \\ deal with this case first
    if(e==1||t==0,
      1
    ,
      if(e==2||t==-1,
        4
      ,
        \\ p=2 and e>=3 and im(5) isn't trivial
        tp=if(t>=0,t,-1-t); \\ 1<=tp<2^(e-2)
        2^(e-valuation(tp,2))
      )
    )
  ,
  \\ p odd
    if(t==0,
      1
    ,
      p^(e-valuation(t,p))
    )
  )
}

z2log(t)=
{
  \\ This returns the 2-adic log of t.
  if(padicprec(t,2)<3,
    1
  ,
    truncate(log(lift(t)+O(2^padicprec(t,2)))/log(5+O(2^padicprec(t,2))))
  )
}

idxG0(N)=
{
  local(facN);
  facN=factor(N);
  prod(i=1,matsize(facN)[1],facN[i,1]^facN[i,2]+facN[i,1]^(facN[i,2]-1))
}

istrivial(eps)=(eps[2][,3]==vectorv(matsize(eps[2])[1],i,0))

TrivialCharacter(N)=
{
  local(facN);
  facN=factor(N);

  [N,matrix(matsize(facN)[1],3,i,j,if(j<3,facN[i,j],0))]
}

DirichletCharacter(N,v)=
{
  local(facN);
  facN=factor(N);
  [N,matrix(matsize(facN)[1],3,i,j,if(j<3,facN[i,j],v[i]))]
}

\\
\\ Syntax for DirichletCharacter: takes (N,v) where N>0 is an integer
\\ and v is a vector of length equal to the number of factors of N;
\\ p_i will get assigned v[i]. Note that we *CAN* have factors
\\ in a non-standard order. Equality of chars will be difficult but
\\ who cares!

charmult(chi1,chi2)=
{
  if(gcd(chi1[1],chi2[1])>1,
    error("Too lazy to multiply Dirichlet characters together properly")
  );

  [chi1[1]*chi2[1],concat(chi1[2]~,chi2[2]~)~]
}