Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Download

Testing latest pari + WASM + node.js... and it works?! Wow.

28493 views
License: GPL3
ubuntu2004
Function: lfuncreate
Section: l_functions
C-Name: lfuncreate
Prototype: G
Help: lfuncreate(obj): given either an object such as a polynomial, elliptic
 curve, Dirichlet or Hecke character, eta quotient, etc., or an explicit
 6 or 7 component vector [dir,real,Vga,k,N,eps,r],
 create the Ldata structure necessary for lfun computation.
Doc: This low-level routine creates \tet{Ldata} structures, needed by
 \var{lfun} functions, describing an $L$-function and its functional equation.
 We advise using a high-level constructor when one is available, see
 \kbd{??lfun}, and this function accepts them:
 \bprog
 ? L = lfuncreate(1); \\ Riemann zeta
 ? L = lfuncreate(5); \\ Dirichlet L-function for quadratic character (5/.)
 ? L = lfuncreate(x^2+1); \\ Dedekind zeta for Q(i)
 ? L = lfuncreate(ellinit([0,1])); \\ L-function of E/Q: y^2=x^3+1
 @eprog\noindent One can then use, e.g., \kbd{lfun(L,s)} to directly
 evaluate the respective $L$-functions at $s$, or \kbd{lfuninit(L, [c,w,h]}
 to initialize computations in the rectangular box $\Re(s-c) \leq w$,
 $\Im(s) \leq h$.

 We now describe the low-level interface, used to input nonbuiltin
 $L$-functions. The input is now a $6$ or $7$ component vector
 $V=[a, astar, Vga, k, N, eps, poles]$, whose components are as follows:

 \item \kbd{V[1]=a} encodes the Dirichlet series coefficients $(a_n)$. The
 preferred format is a closure of arity 1: \kbd{n->vector(n,i,a(i))} giving
 the vector of the first $n$ coefficients. The closure is allowed to return
 a vector of more than $n$ coefficients (only the first $n$ will be
 considered) or even less than $n$, in which case loss of accuracy will occur
 and a warning that \kbd{\#an} is less than expected is issued. This
 allows to precompute and store a fixed large number of Dirichlet
 coefficients in a vector $v$ and use the closure \kbd{n->v}, which
 does not depend on $n$. As a shorthand for this latter case, you can input
 the vector $v$ itself instead of the closure.
 \bprog
 ? z = lfuncreate([n->vector(n,i,1), 1, [0], 1, 1, 1, 1]); \\ Riemann zeta
 ? lfun(z,2) - Pi^2/6
 %2 = -5.877471754111437540 E-39
 @eprog

 A second format is limited to $L$-functions affording an
 Euler product. It is a closure of arity 2 \kbd{(p,d)->F(p)} giving the
 local factor $L_p(X)$ at $p$ as a rational function, to be evaluated at
 $p^{-s}$ as in \kbd{direuler}; $d$ is set to \kbd{logint}$(n,p)$ + 1, where
 $n$ is the total number of Dirichlet coefficients $(a_1,\dots,a_n)$ that will
 be computed. In other words, the smallest integer $d$ such that $p^d > n$.
 This parameter $d$ allows to compute only part of
 $L_p$ when $p$ is large and $L_p$ expensive to compute: any polynomial
 (or \typ{SER}) congruent to $L_p$ modulo $X^d$ is acceptable since only
 the coefficients of $X^0, \dots, X^{d-1}$ are needed to expand the Dirichlet
 series. The closure can of course ignore this parameter:

 \bprog
 ? z = lfuncreate([(p,d)->1/(1-x), 1, [0], 1, 1, 1, 1]); \\ Riemann zeta
 ? lfun(z,2) - Pi^2/6
 %4 = -5.877471754111437540 E-39
 @eprog\noindent
 One can describe separately the generic local factors coefficients
 and the bad local factors by setting $\kbd{dir} = [F, L_{bad}]$,
 were $L_{bad} = [[p_1,L_{p_1}], \dots,[p_k,L_{p_k}]]$, where $F$
 describes the generic local factors as above, except that when $p = p_i$
 for some $i \leq k$, the coefficient $a_p$ is directly set to $L_{p_i}$
 instead of calling $F$.

 \bprog
 N = 15;
 E = ellinit([1, 1, 1, -10, -10]); \\ = "15a1"
 F(p,d) = 1 / (1 - ellap(E,p)*'x + p*'x^2);
 Lbad = [[3, 1/(1+'x)], [5, 1/(1-'x)]];
 L = lfuncreate([[F,Lbad], 0, [0,1], 2, N, ellrootno(E)]);
 @eprog\noindent Of course, in this case, \kbd{lfuncreate(E)} is preferable!

 \item \kbd{V[2]=astar} is the Dirichlet series coefficients of the dual
 function, encoded as \kbd{a} above. The sentinel values $0$ and $1$ may
 be used for the special cases where $a = a^*$ and $a = \overline{a^*}$,
 respectively.

 \item \kbd{V[3]=Vga} is the vector of $\alpha_j$ such that the gamma
 factor of the $L$-function is equal to
 $$\gamma_A(s)=\prod_{1\le j\le d}\Gamma_{\R}(s+\alpha_j),$$
 where $\Gamma_{\R}(s)=\pi^{-s/2}\Gamma(s/2)$.
 This same syntax is used in the \kbd{gammamellininv} functions.
 In particular the length $d$ of \kbd{Vga} is the degree of the $L$-function.
 In the present implementation, the $\alpha_j$ are assumed to be exact
 rational numbers. However when calling theta functions with \emph{complex}
 (as opposed to real) arguments, determination problems occur which may
 give wrong results when the $\alpha_j$ are not integral.

 \item \kbd{V[4]=k} is a positive integer $k$. The functional equation relates
 values at $s$ and $k-s$. For instance, for an Artin $L$-series such as a
 Dedekind zeta function we have $k = 1$, for an elliptic curve $k = 2$, and
 for a modular form, $k$ is its weight. For motivic $L$-functions, the
 \emph{motivic} weight $w$ is $w = k-1$.

 By default we assume that $a_n = O_\epsilon(n^{k_1+\epsilon})$, where
 $k_1 = w$ and even $k_1 = w/2$ when the $L$ function has no pole
 (Ramanujan-Petersson). If this is not the case, you can replace the
 $k$ argument by a vector $[k,k_1]$, where $k_1$ is the upper bound you can
 assume.

 \item \kbd{V[5]=N} is the conductor, an integer $N\ge1$, such that
 $\Lambda(s)=N^{s/2}\gamma_A(s)L(s)$ with $\gamma_A(s)$ as above.

 \item \kbd{V[6]=eps} is the root number $\varepsilon$, i.e., the
 complex number (usually of modulus $1$) such that
 $\Lambda(a, k-s) = \varepsilon \Lambda(a^*, s)$.

 \item The last optional component \kbd{V[7]=poles} encodes the poles of the
 $L$ or $\Lambda$-functions, and is omitted if they have no poles.
 A polar part is given by a list of $2$-component vectors
 $[\beta,P_{\beta}(x)]$, where
 $\beta$ is a pole and the power series $P_{\beta}(x)$ describes
 the attached polar part, such that $L(s) - P_\beta(s-\beta)$ is holomorphic
 in a neighbourhood of $\beta$. For instance $P_\beta = r/x+O(1)$ for a
 simple pole at $\beta$ or $r_1/x^2+r_2/x+O(1)$ for a double pole.
 The type of the list describing the polar part allows to distinguish between
 $L$ and $\Lambda$: a \typ{VEC} is attached to $L$, and a \typ{COL}
 is attached to $\Lambda$. Unless $a = \overline{a^*}$ (coded by \kbd{astar}
 equal to $0$ or $1$), it is mandatory to specify the polar part of $\Lambda$
 rather than those of $L$ since the poles of $L^*$ cannot be infered from the
 latter ! Whereas the functional equation allows to deduce the polar part of
 $\Lambda^*$ from the polar part of $\Lambda$.

 Finally, if $a = \overline{a^*}$, we allow a shortcut to describe
 the frequent situation where $L$ has at most simple pole, at $s = k$,
 with residue $r$ a complex scalar: you may then input $\kbd{poles} = r$.
 This value $r$ can be set to $0$ if unknown and it will be computed.

 \misctitle{When one component is not exact}
 Alternatively, \kbd{obj} can be a closure of arity $0$ returning the above
 vector to the current real precision. This is needed if some components
 are not available exactly but only through floating point approximations.
 The closure allows algorithms to recompute them to higher accuracy when
 needed. Compare
 \bprog
 ? Ld1() = [n->lfunan(Mod(2,7),n),1,[0],1,7,((-13-3*sqrt(-3))/14)^(1/6)];
 ? Ld2 = [n->lfunan(Mod(2,7),n),1,[0],1,7,((-13-3*sqrt(-3))/14)^(1/6)];
 ? L1 = lfuncreate(Ld1);
 ? L2 = lfuncreate(Ld2);
 ? lfun(L1,1/2+I*200) \\ OK
 %5 = 0.55943925130316677665287870224047183265 -
      0.42492662223174071305478563967365980756*I
 ? lfun(L2,1/2+I*200) \\ all accuracy lost
 %6 = 0.E-38 + 0.E-38*I
 @eprog\noindent
 The accuracy lost in \kbd{Ld2} is due to the root number being given to
 an insufficient precision. To see what happens try
 \bprog
 ? Ld3() = printf("prec needed: %ld bits",getlocalbitprec());Ld1()
 ? L3 = lfuncreate(Ld3);
 prec needed: 64 bits
 ? z3 = lfun(L3,1/2+I*200)
 prec needed: 384 bits
 %16 = 0.55943925130316677665287870224047183265 -
       0.42492662223174071305478563967365980756*I
 @eprog