Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Download

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

28495 views
License: GPL3
ubuntu2004
Function: intnum
Section: sums
C-Name: intnum0
Prototype: V=GGEDGp
Help: intnum(X=a,b,expr,{tab}): numerical integration of expr from a to b with
 respect to X. Plus/minus infinity is coded as +oo/-oo. Finally tab is
 either omitted (let the program choose the integration step), a nonnegative
 integer m (divide integration step by 2^m), or data precomputed with
 intnuminit.
Wrapper: (,,G)
Description:
  (gen,gen,gen,?gen):gen:prec intnum(${3 cookie}, ${3 wrapper}, $1, $2, $4, $prec)
Doc: numerical integration
 of \var{expr} on $]a,b[$ with respect to $X$, using the
 double-exponential method, and thus $O(D\log D)$ evaluation of
 the integrand in precision $D$. The integrand may have values
 belonging to a vector space over the real numbers; in particular, it can be
 complex-valued or vector-valued. But it is assumed that the function is
 regular on $]a,b[$. If the endpoints $a$ and $b$ are finite and the
 function is regular there, the situation is simple:
 \bprog
 ? intnum(x = 0,1, x^2)
 %1 = 0.3333333333333333333333333333
 ? intnum(x = 0,Pi/2, [cos(x), sin(x)])
 %2 = [1.000000000000000000000000000, 1.000000000000000000000000000]
 @eprog\noindent
 An endpoint equal to $\pm\infty$ is coded as \kbd{+oo} or \kbd{-oo}, as
 expected:
 \bprog
 ? intnum(x = 1,+oo, 1/x^2)
 %3 = 1.000000000000000000000000000
 @eprog\noindent
 In basic usage, it is assumed that the function does not decrease
 exponentially fast at infinity:
 \bprog
 ? intnum(x=0,+oo, exp(-x))
   ***   at top-level: intnum(x=0,+oo,exp(-
   ***                 ^--------------------
   *** exp: overflow in expo().
 @eprog\noindent
 We shall see in a moment how to avoid that last problem, after describing
 the last \emph{optional} argument \var{tab}.

 \misctitle{The \var{tab} argument} The routine uses weights $w_i$, which are
 mostly independent of the function
 being integrated, evaluated at many sampling points $x_i$ and
 approximates the integral by $\sum w_i f(x_i)$. If \var{tab} is

 \item a nonnegative integer $m$, we multiply the number of sampling points
 by $2^m$, hopefully increasing accuracy. Note that the running time
 increases roughly by a factor $2^m$. One may try consecutive values of $m$
 until they give the same value up to an accepted error.

 \item a set of integration tables containing precomputed $x_i$ and $w_i$
 as output by \tet{intnuminit}. This is useful if several integrations of
 the same type are performed (on the same kind of interval and functions,
 for a given accuracy): we skip a precomputation of $O(D\log D)$
 elementary functions in accuracy $D$, whose running time has the same order
 of magnitude as the evaluation of the integrand. This is in particular
 useful for multivariate integrals.

 \misctitle{Specifying the behavior at endpoints} This is done as follows.
 An endpoint $a$ is either given as such (a scalar,
 real or complex, \kbd{oo} or \kbd{-oo} for $\pm\infty$), or as a two
 component vector $[a,\alpha]$, to indicate the behavior of the integrand in a
 neighborhood of $a$.

 If $a$ is finite, the code $[a,\alpha]$ means the function has a
 singularity of the form $(x-a)^{\alpha}$, up to logarithms. (If $\alpha \ge
 0$, we only assume the function is regular, which is the default assumption.)
 If a wrong singularity exponent is used, the result will lose decimals:
 \bprog
 ? c = -9/10;
 ? intnum(x=0, 1, x^c)         \\@com assume $x^{-9/10}$ is regular at 0
 %1 = 9.9999839078827082322596783301939063944
 ? intnum(x=[0,c], 1, x^c)  \\@com no, it's not
 %2 = 10.000000000000000000000000000000000000
 ? intnum(x=[0,c/2], 1, x^c) \\@com using a wrong exponent is bad
 %3 = 9.9999999997122749095442279375719919769
 @eprog

 If $a$ is $\pm\infty$, which is coded as \kbd{+oo} or \kbd{-oo},
 the situation is more complicated, and $[\pm\kbd{oo},\alpha]$ means:

 \item $\alpha=0$ (or no $\alpha$ at all, i.e. simply $\pm\kbd{oo}$)
 assumes that the integrand tends to zero moderately quickly, at least as
 $O(x^{-2})$ but not exponentially fast.

 \item $\alpha>0$ assumes that the function tends to zero exponentially fast
 approximately as $\exp(-\alpha|x|)$. This includes oscillating but quickly
 decreasing functions such as $\exp(-x)\sin(x)$.
 \bprog
 ? intnum(x=0, +oo, exp(-2*x))
   ***   at top-level: intnum(x=0,+oo,exp(-
   ***                 ^--------------------
   *** exp: exponent (expo) overflow
 ? intnum(x=0, [+oo, 2], exp(-2*x))  \\@com OK!
 %1 = 0.50000000000000000000000000000000000000
 ? intnum(x=0, [+oo, 3], exp(-2*x))  \\@com imprecise exponent, still OK !
 %2 = 0.50000000000000000000000000000000000000
 ? intnum(x=0, [+oo, 10], exp(-2*x)) \\@com wrong exponent $\Rightarrow$ disaster
 %3 = 0.49999999999952372962457451698256707393
 @eprog\noindent As the last exemple shows, the exponential decrease rate
 \emph{must} be indicated to avoid overflow, but the method is robust enough
 for a rough guess to be acceptable.

 \item $\alpha<-1$ assumes that the function tends to $0$ slowly, like
 $x^{\alpha}$. Here the algorithm is less robust and it is essential to give a
 sharp $\alpha$, unless $\alpha \le -2$ in which case we use
 the default algorithm as if $\alpha$ were missing (or equal to $0$).
 \bprog
 ? intnum(x=1, +oo, x^(-3/2))         \\ default
 %1 = 1.9999999999999999999999999999646391207
 ? intnum(x=1, [+oo,-3/2], x^(-3/2))  \\ precise decrease rate
 %2 = 2.0000000000000000000000000000000000000
 ? intnum(x=1, [+oo,-11/10], x^(-3/2)) \\ worse than default
 %3 = 2.0000000000000000000000000089298011973
 @eprog

 \smallskip The last two codes are reserved for oscillating functions.
 Let $k > 0$ real, and $g(x)$ a nonoscillating function tending slowly to $0$
 (e.g. like a negative power of $x$), then

 \item $\alpha=k * I$ assumes that the function behaves like $\cos(kx)g(x)$.

 \item $\alpha=-k* I$ assumes that the function behaves like $\sin(kx)g(x)$.

 \noindent Here it is critical to give the exact value of $k$. If the
 oscillating part is not a pure sine or cosine, one must expand it into a
 Fourier series, use the above codings, and sum the resulting contributions.
 Otherwise you will get nonsense. Note that $\cos(kx)$, and similarly
 $\sin(kx)$, means that very function, and not a translated version such as
 $\cos(kx+a)$.

 \misctitle{Note} If $f(x)=\cos(kx)g(x)$ where $g(x)$ tends to zero
 exponentially fast as $\exp(-\alpha x)$, it is up to the user to choose
 between $[\pm\kbd{oo},\alpha]$ and $[\pm\kbd{oo},k* I]$, but a good rule of
 thumb is that
 if the oscillations are weaker than the exponential decrease, choose
 $[\pm\kbd{oo},\alpha]$, otherwise choose $[\pm\kbd{oo},k*I]$, although the
 latter can reasonably be used in all cases, while the former cannot. To take
 a specific example, in most inverse Mellin transforms, the integrand is a
 product of an exponentially decreasing and an oscillating factor. If we
 choose the oscillating type of integral we perhaps obtain the best results,
 at the expense of having to recompute our functions for a different value of
 the variable $z$ giving the transform, preventing us to use a function such
 as \kbd{intfuncinit}. On the other hand using the exponential type of
 integral, we obtain less accurate results, but we skip expensive
 recomputations. See \kbd{intfuncinit} for more explanations.

 \misctitle{Power series limits}
 The limits $a$ and $b$ can be power series of nonnegative valuation,
 giving a power series expansion for the integral -- provided it exists.
 \bprog
 ? intnum(t=0,X + O(X^3), exp(t))
 %4 = 1.000...*X - 0.5000...*X^2 + O(X^3)
 ? bestappr( intnum(t=0,X + O(X^17), exp(t)) )- exp(X) + 1
 %5 = O(X^17)
 @eprog\noindent The valuation of the limit cannot be negative
 since $\int_0^{1/X}(1+t^2)^{-1}\, dt = \pi/2 - \kbd{sign}(X)+O(X^2)$.

 Polynomials and rational functions are also allowed and
 converted to power series using current \kbd{seriesprecision}:
 \bprog
 ? bestappr( intnum(t=1,1+X, 1/t) )
 %6 = X - 1/2*X^2 + 1/3*X^3 - 1/4*X^4 + [...] + 1/15*X^15 + O(X^16)
 @eprog\noindent
 The function does not work if the integral is singular with the constant
 coefficient of the series as limit:
 \bprog
 ? intnum(t=X^2+O(X^4),1, 1/sqrt(t))
 %8 = 2.000... - 6.236608109630992528 E28*X^2 + O(X^4)
 @eprog\noindent
 however you can use
 \bprog
 ? intnum(t=[X^2+O(X^4),-1/2],1, 1/sqrt(t))
 %10 = 2.000000000000000000000000000-2.000000000000000000000000000*X^2+O(X^4)
 @eprog\noindent whis is translated internally to
 \bprog
 ? intnum(t=[0,-1/2],1, 1/sqrt(t))-intnum(t=[0,-1/2],X^2+O(X^4), 1/sqrt(t))
 @eprog\noindent
 For this form the argument \var{tab} can be used only as an integer, not a
 table precomputed by \kbd{intnuminit}.

 \smallskip

 We shall now see many examples to get a feeling for what the various
 parameters achieve. All examples below assume precision is set to $115$
 decimal digits. We first type
 \bprog
 ? \p 115
 @eprog

 \misctitle{Apparent singularities} In many cases, apparent singularities
 can be ignored. For instance, if $f(x) = 1
 /(\exp(x)-1) - \exp(-x)/x$, then $\int_0^\infty f(x)\,dx=\gamma$, Euler's
 constant \kbd{Euler}. But

 \bprog
 ? f(x) = 1/(exp(x)-1) - exp(-x)/x
 ? intnum(x = 0, [oo,1],  f(x)) - Euler
 %1 = 0.E-115
 @eprog\noindent
 But close to $0$ the function $f$ is computed with an enormous loss of
 accuracy, and we are in fact lucky that it get multiplied by weights which are
 sufficiently close to $0$ to hide this:
 \bprog
 ? f(1e-200)
 %2 = -3.885337784451458142 E84
 @eprog

 A more robust solution is to define the function differently near special
 points, e.g. by a Taylor expansion
 \bprog
 ? F = truncate( f(t + O(t^10)) ); \\@com expansion around t = 0
 ? poldegree(F)
 %4 = 7
 ? g(x) = if (x > 1e-18, f(x), subst(F,t,x)); \\@com note that $7 \cdot 18 > 105$
 ? intnum(x = 0, [oo,1],  g(x)) - Euler
 %2 = 0.E-115
 @eprog\noindent It is up to the user to determine constants such as the
 $10^{-18}$ and $10$ used above.

 \misctitle{True singularities} With true singularities the result is worse.
 For instance

 \bprog
 ? intnum(x = 0, 1,  x^(-1/2)) - 2
 %1 = -3.5... E-68 \\@com only $68$ correct decimals

 ? intnum(x = [0,-1/2], 1,  x^(-1/2)) - 2
 %2 = 0.E-114 \\@com better
 @eprog

 \misctitle{Oscillating functions}

 \bprog
 ? intnum(x = 0, oo, sin(x) / x) - Pi/2
 %1 = 16.19.. \\@com nonsense
 ? intnum(x = 0, [oo,1], sin(x)/x) - Pi/2
 %2 = -0.006.. \\@com bad
 ? intnum(x = 0, [oo,-I], sin(x)/x) - Pi/2
 %3 = 0.E-115 \\@com perfect
 ? intnum(x = 0, [oo,-I], sin(2*x)/x) - Pi/2  \\@com oops, wrong $k$
 %4 = 0.06...
 ? intnum(x = 0, [oo,-2*I], sin(2*x)/x) - Pi/2
 %5 = 0.E-115 \\@com perfect

 ? intnum(x = 0, [oo,-I], sin(x)^3/x) - Pi/4
 %6 = -0.0008... \\@com bad
 ? sin(x)^3 - (3*sin(x)-sin(3*x))/4
 %7 = O(x^17)
 @eprog\noindent
 We may use the above linearization and compute two oscillating integrals with
 endpoints \kbd{[oo, -I]} and \kbd{[oo, -3*I]} respectively, or
 notice the obvious change of variable, and reduce to the single integral
 ${1\over 2}\int_0^\infty \sin(x)/x\,dx$. We finish with some more complicated
 examples:

 \bprog
 ? intnum(x = 0, [oo,-I], (1-cos(x))/x^2) - Pi/2
 %1 = -0.0003... \\@com bad
 ? intnum(x = 0, 1, (1-cos(x))/x^2) \
 + intnum(x = 1, oo, 1/x^2) - intnum(x = 1, [oo,I], cos(x)/x^2) - Pi/2
 %2 = 0.E-115 \\@com perfect

 ? intnum(x = 0, [oo, 1], sin(x)^3*exp(-x)) - 0.3
 %3 = -7.34... E-55 \\@com bad
 ? intnum(x = 0, [oo,-I], sin(x)^3*exp(-x)) - 0.3
 %4 = 8.9... E-103 \\@com better. Try higher $m$
 ? tab = intnuminit(0,[oo,-I], 1); \\@com double number of sampling points
 ? intnum(x = 0, oo, sin(x)^3*exp(-x), tab) - 0.3
 %6 = 0.E-115 \\@com perfect
 @eprog

 \misctitle{Warning} Like \tet{sumalt}, \kbd{intnum} often assigns a
 reasonable value to diverging integrals. Use these values at your own risk!
 For example:

 \bprog
 ? intnum(x = 0, [oo, -I], x^2*sin(x))
 %1 = -2.0000000000...
 @eprog\noindent
 Note the formula
 $$ \int_0^\infty \sin(x)/x^s\,dx = \cos(\pi s/2) \Gamma(1-s)\;, $$
 a priori valid only for $0 < \Re(s) < 2$, but the right hand side provides an
 analytic continuation which may be evaluated at $s = -2$\dots

 \misctitle{Multivariate integration}
 Using successive univariate integration with respect to different formal
 parameters, it is immediate to do naive multivariate integration. But it is
 important to use a suitable \kbd{intnuminit} to precompute data for the
 \emph{internal} integrations at least!

 For example, to compute the double integral on the unit disc $x^2+y^2\le1$
 of the function $x^2+y^2$, we can write
 \bprog
 ? tab = intnuminit(-1,1);
 ? intnum(x=-1,1, intnum(y=-sqrt(1-x^2),sqrt(1-x^2), x^2+y^2, tab),tab) - Pi/2
 %2 = -7.1... E-115 \\@com OK

 @eprog\noindent
 The first \var{tab} is essential, the second optional. Compare:

 \bprog
 ? tab = intnuminit(-1,1);
 time = 4 ms.
 ? intnum(x=-1,1, intnum(y=-sqrt(1-x^2),sqrt(1-x^2), x^2+y^2));
 time = 3,092 ms. \\@com slow
 ? intnum(x=-1,1, intnum(y=-sqrt(1-x^2),sqrt(1-x^2), x^2+y^2, tab), tab);
 time = 252 ms.  \\@com faster
 ? intnum(x=-1,1, intnum(y=-sqrt(1-x^2),sqrt(1-x^2), x^2+y^2, tab));
 time = 261 ms.  \\@com the \emph{internal} integral matters most
 @eprog

 \synt{intnum}{void *E, GEN (*eval)(void*,GEN), GEN a,GEN b,GEN tab, long prec},
 where an omitted \var{tab} is coded as \kbd{NULL}.