Skip to content

LogIntegral

Status: Stable

documented, exercised by the test suite and/or worked examples, with no known limitations recorded.

Description

LogIntegral[z]

gives the logarithmic integral li(z), the principal value of Integral_0^z dt/ln t, equal to ExpIntegralEi[Log[z]], with a branch cut on (-Infinity, 1). LogIntegral[0] = 0, LogIntegral[1] = -Infinity,

LogIntegral[Infinity] = Infinity. Real and complex inputs evaluate

Notes numerically at machine or arbitrary (MPFR) precision; D\[LogIntegral\[z\], z\] = 1/Log\[z\]. Listable.

Examples (4)

Every input below was run against the current Mathilda build and its output recorded.

Applications (4)

In[1]:= N[LogIntegral[2], 40]
Out[1]= 1.0451637801174927848445888891946131365227

In[2]:= D[LogIntegral[z], z]
Out[2]= 1/Log[z]

In[3]:= N[LogIntegral[10^6], 30]
Out[3]= 78627.5491594621819198629107479

In[4]:= N[LogIntegral[1000], 20]
Out[4]= 177.609657990152226688

Algorithm

Mathilda -- the logarithmic integral li.

  LogIntegral[z]   li(z) = PV Int_0^z dt / ln t

li has a branch cut along (-Infinity, +1); the principal value is taken on the cut. The implementation rests on the identity

  li(z) = Ei(Log z),

where Ei is ExpIntegralEi and Log is the principal logarithm. This lets us reuse ExpIntegralEi's fully-tested numeric stack (mpfr_eint / the real and complex convergent series with cancellation guard bits) without duplicating any of it, and the principal Log automatically supplies the +-i Pi jump that places the branch cut on (-Infinity, +1).

Evaluation is layered so each kind of argument takes the cheapest route:

  exact special values     ->  0, -Infinity, Infinity, Indeterminate
  machine real / complex z ->  the double kernels sf_machine_li(_c)
                               (sf_machine_expint.c, shared with NDArray
                               and Compile[]), no expression is built
  arbitrary-precision z    ->  evaluate ExpIntegralEi[Log[z]]
  everything else           ->  stays symbolic (return NULL)

Exact non-special numbers (e.g. LogIntegral[2], LogIntegral[1/2]) stay symbolic, matching the Wolfram Language; only inexact input or an explicit N[...] (which rewrites the argument to an MPFR number) evaluates numerically.

Attributes: Listable, NumericFunction, Protected.

Implementation notes

Algorithm. builtin_logintegral evaluates li(z) through the identity li(z) = Ei(Log z), reusing ExpIntegralEi's numeric stack rather than duplicating it; the principal Log supplies the ±i Pi jump that places the branch cut on (-Infinity, +1). Exact special values: 0 -> 0, 1 -> -Infinity, Infinity -> Infinity, ComplexInfinity/Indeterminate -> Indeterminate. Exact non-special numbers (li[2], li[1/2]) stay symbolic, matching the Wolfram Language; only an inexact argument (or explicit N[...]) evaluates, by building ExpIntegralEi[Log[z]] and evaluating it — a defensive check drops the result and stays symbolic if the composition did not reduce. The machine kernel logintegral_machine_complex is Ei(clog z), declining at z = 0 (Indeterminate) and z = 1 (pole).

Data structures. Expr; reuses the ExpIntegralEi kernels (mpfr_eint / the real and complex convergent series); double complex machine kernel. ND: unary kernel NDKU_LogIntegral = { logintegral_machine_complex, ndk_LogIntegral_r, ... } (the real kernel is sf_machine_li), registered REG_U, so packed_aware. Attributes: Listable, NumericFunction, Protected.

Complexity / limits. Cost is one ExpIntegralEi evaluation. The principal Log puts the cut on the negative real axis, so li[-1.] is complex (Ei(i Pi)). Exact rationals stay symbolic. Compile[] lowers at both scalar and rank-1 array shapes (Compiled -> True).

  • Exact special values: LogIntegral[0] = 0, LogIntegral[1] = -Infinity, LogIntegral[Infinity] = Infinity; ComplexInfinity and Indeterminate map to Indeterminate.
  • Exact non-special arguments stay symbolic (LogIntegral[2], LogIntegral[1/2]); numeric values follow from a Real/MPFR argument or from N.
  • Numeric evaluation (machine and arbitrary precision) routes through ExpIntegralEi[Log[z]]:
  • Real z > 1 (Log z > 0) → MPFR mpfr_eint, correctly rounded and fast even at very high precision: LogIntegral[20.] = 9.9053, LogIntegral[2.] = 1.04516, N[LogIntegral[2], 50] = 1.0451637801174927848445888891946131365226155781512.
  • Real 0 < z < 1 (Log z < 0) → the on-cut convergent series, returning a real principal value: LogIntegral[0.5] = -0.378671, LogIntegral[1.2] = -0.933787.
  • Complex (and real z < 0, whose principal Log is complex) → the complex series with guard bits, so machine-precision complex results are fully accurate, e.g. LogIntegral[2. + I] = 1.41126 + 1.22471 I, N[Re[LogIntegral[2 + I]], 30] = 1.41125904201780100568439320706.
  • Machine precision (real and complex) no longer builds and evaluates ExpIntegralEi[Log[z]]: double kernels shared bit-for-bit with the packed/NDArray kernels and Compile[] (src/special_functions/sf_machine_expint.c; the scalar builtin calls the same function, so scalar == List == packed == NDArray == Compile). A decline (pole, overflow, an underflow to a subnormal) falls through to the MPFR path unchanged, and arbitrary precision is untouched. The real kernel evaluates Ei(log x) with e^(log x) replaced by x itself in the large-argument forms, so the rounding of log x is not amplified by an exponential; a real x < 0 returns the complex value directly. The rounding of log x would otherwise cost ~log x ulps (9 at x = 1e4) through the e^y in Ei(y); it is recovered as dy = (x − e^y)/x and added back as (x/y)·dy. Accuracy vs mpmath: median 0.4 ulp, max 1.9 ulp (real, off the zero μ = 1.4513); max 2.7 ulp (complex).
  • Derivative: D[LogIntegral[z], z] = 1/Log[z] (chain rule applies, e.g. D[LogIntegral[x^2], x] = (2 x)/Log[x^2]); the Taylor series at a regular point follows from the generic D-based fallback.
  • Wrong arity emits LogIntegral::argx and stays unevaluated.

Attributes: Listable, NumericFunction, Protected.

References

See also: ExpIntegralEi, Log, Real, N, D

Notes & additional examples

Notes

LogIntegral[z] is the logarithmic integral li(z), the principal value of Integral_0^z dt/Log[t], equal to ExpIntegralEi[Log[z]], with a branch cut on (-Infinity, 1). Its derivative is 1/Log[z]. li(x) is the leading term of the prime-counting approximation PrimePi[x] ~ li(x); for example li(10^6) is about 78627.5, close to PrimePi[10^6] = 78498. Real and complex inputs evaluate numerically at machine or arbitrary (MPFR) precision. LogIntegral[1] = -Infinity. Listable.