Logarithmic functions#

AUTHORS:

  • Yoora Yi Tenen (2012-11-16): Add documentation for log() (Issue #12113)

  • Tomas Kalvoda (2015-04-01): Add exp_polar() (Issue #18085)

class sage.functions.log.Function_dilog[source]#

Bases: GinacFunction

The dilogarithm function \(\text{Li}_2(z) = \sum_{k=1}^{\infty} z^k / k^2\).

This is simply an alias for polylog(2, z).

EXAMPLES:

sage: # needs sage.symbolic
sage: dilog(1)
1/6*pi^2
sage: dilog(1/2)
1/12*pi^2 - 1/2*log(2)^2
sage: dilog(x^2+1)
dilog(x^2 + 1)
sage: dilog(-1)
-1/12*pi^2
sage: dilog(-1.0)
-0.822467033424113
sage: dilog(-1.1)
-0.890838090262283
sage: dilog(1/2)
1/12*pi^2 - 1/2*log(2)^2
sage: dilog(.5)
0.582240526465012
sage: dilog(1/2).n()
0.582240526465012
sage: var('z')
z
sage: dilog(z).diff(z, 2)
log(-z + 1)/z^2 - 1/((z - 1)*z)
sage: dilog(z).series(z==1/2, 3)
(1/12*pi^2 - 1/2*log(2)^2) + (-2*log(1/2))*(z - 1/2)
 + (2*log(1/2) + 2)*(z - 1/2)^2 + Order(1/8*(2*z - 1)^3)

sage: latex(dilog(z))                                                       # needs sage.symbolic
{\rm Li}_2\left(z\right)
>>> from sage.all import *
>>> # needs sage.symbolic
>>> dilog(Integer(1))
1/6*pi^2
>>> dilog(Integer(1)/Integer(2))
1/12*pi^2 - 1/2*log(2)^2
>>> dilog(x**Integer(2)+Integer(1))
dilog(x^2 + 1)
>>> dilog(-Integer(1))
-1/12*pi^2
>>> dilog(-RealNumber('1.0'))
-0.822467033424113
>>> dilog(-RealNumber('1.1'))
-0.890838090262283
>>> dilog(Integer(1)/Integer(2))
1/12*pi^2 - 1/2*log(2)^2
>>> dilog(RealNumber('.5'))
0.582240526465012
>>> dilog(Integer(1)/Integer(2)).n()
0.582240526465012
>>> var('z')
z
>>> dilog(z).diff(z, Integer(2))
log(-z + 1)/z^2 - 1/((z - 1)*z)
>>> dilog(z).series(z==Integer(1)/Integer(2), Integer(3))
(1/12*pi^2 - 1/2*log(2)^2) + (-2*log(1/2))*(z - 1/2)
 + (2*log(1/2) + 2)*(z - 1/2)^2 + Order(1/8*(2*z - 1)^3)

>>> latex(dilog(z))                                                       # needs sage.symbolic
{\rm Li}_2\left(z\right)

Dilog has a branch point at \(1\). Sage’s floating point libraries may handle this differently from the symbolic package:

sage: # needs sage.symbolic
sage: dilog(1)
1/6*pi^2
sage: dilog(1.)
1.64493406684823
sage: dilog(1).n()
1.64493406684823
sage: float(dilog(1))
1.6449340668482262
>>> from sage.all import *
>>> # needs sage.symbolic
>>> dilog(Integer(1))
1/6*pi^2
>>> dilog(RealNumber('1.'))
1.64493406684823
>>> dilog(Integer(1)).n()
1.64493406684823
>>> float(dilog(Integer(1)))
1.6449340668482262
class sage.functions.log.Function_exp[source]#

Bases: GinacFunction

The exponential function, \(\exp(x) = e^x\).

EXAMPLES:

sage: # needs sage.symbolic
sage: exp(-1)
e^(-1)
sage: exp(2)
e^2
sage: exp(2).n(100)
7.3890560989306502272304274606
sage: exp(x^2 + log(x))
e^(x^2 + log(x))
sage: exp(x^2 + log(x)).simplify()
x*e^(x^2)
sage: exp(2.5)
12.1824939607035
sage: exp(I*pi/12)
(1/4*I + 1/4)*sqrt(6) - (1/4*I - 1/4)*sqrt(2)

sage: exp(float(2.5))
12.182493960703473
sage: exp(RDF('2.5'))                                                           # needs sage.symbolic
12.182493960703473
>>> from sage.all import *
>>> # needs sage.symbolic
>>> exp(-Integer(1))
e^(-1)
>>> exp(Integer(2))
e^2
>>> exp(Integer(2)).n(Integer(100))
7.3890560989306502272304274606
>>> exp(x**Integer(2) + log(x))
e^(x^2 + log(x))
>>> exp(x**Integer(2) + log(x)).simplify()
x*e^(x^2)
>>> exp(RealNumber('2.5'))
12.1824939607035
>>> exp(I*pi/Integer(12))
(1/4*I + 1/4)*sqrt(6) - (1/4*I - 1/4)*sqrt(2)

>>> exp(float(RealNumber('2.5')))
12.182493960703473
>>> exp(RDF('2.5'))                                                           # needs sage.symbolic
12.182493960703473

To prevent automatic evaluation, use the hold parameter:

sage: exp(I*pi, hold=True)                                                      # needs sage.symbolic
e^(I*pi)
sage: exp(0, hold=True)                                                         # needs sage.symbolic
e^0
>>> from sage.all import *
>>> exp(I*pi, hold=True)                                                      # needs sage.symbolic
e^(I*pi)
>>> exp(Integer(0), hold=True)                                                         # needs sage.symbolic
e^0

To then evaluate again, we currently must use Maxima via sage.symbolic.expression.Expression.simplify():

sage: exp(0, hold=True).simplify()                                              # needs sage.symbolic
1
>>> from sage.all import *
>>> exp(Integer(0), hold=True).simplify()                                              # needs sage.symbolic
1
sage: # needs sage.symbolic
sage: exp(pi*I/2)
I
sage: exp(pi*I)
-1
sage: exp(8*pi*I)
1
sage: exp(7*pi*I/2)
-I
>>> from sage.all import *
>>> # needs sage.symbolic
>>> exp(pi*I/Integer(2))
I
>>> exp(pi*I)
-1
>>> exp(Integer(8)*pi*I)
1
>>> exp(Integer(7)*pi*I/Integer(2))
-I

For the sake of simplification, the argument is reduced modulo the period of the complex exponential function, \(2\pi i\):

sage: k = var('k', domain='integer')                                            # needs sage.symbolic
sage: exp(2*k*pi*I)                                                             # needs sage.symbolic
1
sage: exp(log(2) + 2*k*pi*I)                                                    # needs sage.symbolic
2
>>> from sage.all import *
>>> k = var('k', domain='integer')                                            # needs sage.symbolic
>>> exp(Integer(2)*k*pi*I)                                                             # needs sage.symbolic
1
>>> exp(log(Integer(2)) + Integer(2)*k*pi*I)                                                    # needs sage.symbolic
2

The precision for the result is deduced from the precision of the input. Convert the input to a higher precision explicitly if a result with higher precision is desired:

sage: t = exp(RealField(100)(2)); t                                             # needs sage.rings.real_mpfr
7.3890560989306502272304274606
sage: t.prec()                                                                  # needs sage.rings.real_mpfr
100
sage: exp(2).n(100)                                                             # needs sage.symbolic
7.3890560989306502272304274606
>>> from sage.all import *
>>> t = exp(RealField(Integer(100))(Integer(2))); t                                             # needs sage.rings.real_mpfr
7.3890560989306502272304274606
>>> t.prec()                                                                  # needs sage.rings.real_mpfr
100
>>> exp(Integer(2)).n(Integer(100))                                                             # needs sage.symbolic
7.3890560989306502272304274606
class sage.functions.log.Function_exp_polar[source]#

Bases: BuiltinFunction

Representation of a complex number in a polar form.

INPUT:

  • z – a complex number \(z = a + ib\).

OUTPUT:

A complex number with modulus \(\exp(a)\) and argument \(b\).

If \(-\pi < b \leq \pi\) then \(\operatorname{exp\_polar}(z)=\exp(z)\). For other values of \(b\) the function is left unevaluated.

EXAMPLES:

The following expressions are evaluated using the exponential function:

sage: exp_polar(pi*I/2)                                                     # needs sage.symbolic
I
sage: x = var('x', domain='real')                                           # needs sage.symbolic
sage: exp_polar(-1/2*I*pi + x)                                              # needs sage.symbolic
e^(-1/2*I*pi + x)
>>> from sage.all import *
>>> exp_polar(pi*I/Integer(2))                                                     # needs sage.symbolic
I
>>> x = var('x', domain='real')                                           # needs sage.symbolic
>>> exp_polar(-Integer(1)/Integer(2)*I*pi + x)                                              # needs sage.symbolic
e^(-1/2*I*pi + x)

The function is left unevaluated when the imaginary part of the input \(z\) does not satisfy \(-\pi < \Im(z) \leq \pi\):

sage: exp_polar(2*pi*I)                                                     # needs sage.symbolic
exp_polar(2*I*pi)
sage: exp_polar(-4*pi*I)                                                    # needs sage.symbolic
exp_polar(-4*I*pi)
>>> from sage.all import *
>>> exp_polar(Integer(2)*pi*I)                                                     # needs sage.symbolic
exp_polar(2*I*pi)
>>> exp_polar(-Integer(4)*pi*I)                                                    # needs sage.symbolic
exp_polar(-4*I*pi)

This fixes Issue #18085:

sage: integrate(1/sqrt(1+x^3), x, algorithm='sympy')                        # needs sage.symbolic
1/3*x*gamma(1/3)*hypergeometric((1/3, 1/2), (4/3,), -x^3)/gamma(4/3)
>>> from sage.all import *
>>> integrate(Integer(1)/sqrt(Integer(1)+x**Integer(3)), x, algorithm='sympy')                        # needs sage.symbolic
1/3*x*gamma(1/3)*hypergeometric((1/3, 1/2), (4/3,), -x^3)/gamma(4/3)

REFERENCES:

class sage.functions.log.Function_harmonic_number[source]#

Bases: BuiltinFunction

Harmonic number function, defined by:

\[ \begin{align}\begin{aligned}H_{n}=H_{n,1}=\sum_{k=1}^n\frac1k\\H_{s}=\int_0^1\frac{1-x^s}{1-x}\end{aligned}\end{align} \]

See the docstring for Function_harmonic_number_generalized().

This class exists as callback for harmonic_number returned by Maxima.

class sage.functions.log.Function_harmonic_number_generalized[source]#

Bases: BuiltinFunction

Harmonic and generalized harmonic number functions, defined by:

\[ \begin{align}\begin{aligned}H_{n}=H_{n,1}=\sum_{k=1}^n\frac{1}{k}\\H_{n,m}=\sum_{k=1}^n\frac{1}{k^m}\end{aligned}\end{align} \]

They are also well-defined for complex argument, through:

\[ \begin{align}\begin{aligned}H_{s}=\int_0^1\frac{1-x^s}{1-x}\\H_{s,m}=\zeta(m)-\zeta(m,s-1)\end{aligned}\end{align} \]

If called with a single argument, that argument is s and m is assumed to be 1 (the normal harmonic numbers \(H_s\)).

ALGORITHM:

Numerical evaluation is handled using the mpmath and FLINT libraries.

REFERENCES:

EXAMPLES:

Evaluation of integer, rational, or complex argument:

sage: harmonic_number(5)                                                        # needs mpmath
137/60

sage: # needs sage.symbolic
sage: harmonic_number(3, 3)
251/216
sage: harmonic_number(5/2)
-2*log(2) + 46/15
sage: harmonic_number(3., 3)
zeta(3) - 0.0400198661225573
sage: harmonic_number(3., 3.)
1.16203703703704
sage: harmonic_number(3, 3).n(200)
1.16203703703703703703703...
sage: harmonic_number(1 + I, 5)
harmonic_number(I + 1, 5)
sage: harmonic_number(5, 1. + I)
1.57436810798989 - 1.06194728851357*I
>>> from sage.all import *
>>> harmonic_number(Integer(5))                                                        # needs mpmath
137/60

>>> # needs sage.symbolic
>>> harmonic_number(Integer(3), Integer(3))
251/216
>>> harmonic_number(Integer(5)/Integer(2))
-2*log(2) + 46/15
>>> harmonic_number(RealNumber('3.'), Integer(3))
zeta(3) - 0.0400198661225573
>>> harmonic_number(RealNumber('3.'), RealNumber('3.'))
1.16203703703704
>>> harmonic_number(Integer(3), Integer(3)).n(Integer(200))
1.16203703703703703703703...
>>> harmonic_number(Integer(1) + I, Integer(5))
harmonic_number(I + 1, 5)
>>> harmonic_number(Integer(5), RealNumber('1.') + I)
1.57436810798989 - 1.06194728851357*I

Solutions to certain sums are returned in terms of harmonic numbers:

sage: k = var('k')                                                              # needs sage.symbolic
sage: sum(1/k^7,k,1,x)                                                          # needs sage.symbolic
harmonic_number(x, 7)
>>> from sage.all import *
>>> k = var('k')                                                              # needs sage.symbolic
>>> sum(Integer(1)/k**Integer(7),k,Integer(1),x)                                                          # needs sage.symbolic
harmonic_number(x, 7)

Check the defining integral at a random integer:

sage: n = randint(10,100)
sage: bool(SR(integrate((1-x^n)/(1-x),x,0,1)) == harmonic_number(n))            # needs sage.symbolic
True
>>> from sage.all import *
>>> n = randint(Integer(10),Integer(100))
>>> bool(SR(integrate((Integer(1)-x**n)/(Integer(1)-x),x,Integer(0),Integer(1))) == harmonic_number(n))            # needs sage.symbolic
True

There are several special values which are automatically simplified:

sage: harmonic_number(0)                                                        # needs mpmath
0
sage: harmonic_number(1)                                                        # needs mpmath
1
sage: harmonic_number(x, 1)                                                     # needs sage.symbolic
harmonic_number(x)
>>> from sage.all import *
>>> harmonic_number(Integer(0))                                                        # needs mpmath
0
>>> harmonic_number(Integer(1))                                                        # needs mpmath
1
>>> harmonic_number(x, Integer(1))                                                     # needs sage.symbolic
harmonic_number(x)
class sage.functions.log.Function_lambert_w[source]#

Bases: BuiltinFunction

The integral branches of the Lambert W function \(W_n(z)\).

This function satisfies the equation

\[z = W_n(z) e^{W_n(z)}\]

INPUT:

  • n – an integer. \(n=0\) corresponds to the principal branch.

  • z – a complex number

If called with a single argument, that argument is z and the branch n is assumed to be 0 (the principal branch).

ALGORITHM:

Numerical evaluation is handled using the mpmath and SciPy libraries.

REFERENCES:

EXAMPLES:

Evaluation of the principal branch:

sage: lambert_w(1.0)                                                            # needs scipy
0.567143290409784
sage: lambert_w(-1).n()                                                         # needs mpmath
-0.318131505204764 + 1.33723570143069*I
sage: lambert_w(-1.5 + 5*I)                                                     # needs mpmath sage.symbolic
1.17418016254171 + 1.10651494102011*I
>>> from sage.all import *
>>> lambert_w(RealNumber('1.0'))                                                            # needs scipy
0.567143290409784
>>> lambert_w(-Integer(1)).n()                                                         # needs mpmath
-0.318131505204764 + 1.33723570143069*I
>>> lambert_w(-RealNumber('1.5') + Integer(5)*I)                                                     # needs mpmath sage.symbolic
1.17418016254171 + 1.10651494102011*I

Evaluation of other branches:

sage: lambert_w(2, 1.0)                                                         # needs scipy
-2.40158510486800 + 10.7762995161151*I
>>> from sage.all import *
>>> lambert_w(Integer(2), RealNumber('1.0'))                                                         # needs scipy
-2.40158510486800 + 10.7762995161151*I

Solutions to certain exponential equations are returned in terms of lambert_w:

sage: S = solve(e^(5*x)+x==0, x, to_poly_solve=True)                            # needs sage.symbolic
sage: z = S[0].rhs(); z                                                         # needs sage.symbolic
-1/5*lambert_w(5)
sage: N(z)                                                                      # needs sage.symbolic
-0.265344933048440
>>> from sage.all import *
>>> S = solve(e**(Integer(5)*x)+x==Integer(0), x, to_poly_solve=True)                            # needs sage.symbolic
>>> z = S[Integer(0)].rhs(); z                                                         # needs sage.symbolic
-1/5*lambert_w(5)
>>> N(z)                                                                      # needs sage.symbolic
-0.265344933048440

Check the defining equation numerically at \(z=5\):

sage: N(lambert_w(5)*exp(lambert_w(5)) - 5)                                     # needs mpmath
0.000000000000000
>>> from sage.all import *
>>> N(lambert_w(Integer(5))*exp(lambert_w(Integer(5))) - Integer(5))                                     # needs mpmath
0.000000000000000

There are several special values of the principal branch which are automatically simplified:

sage: lambert_w(0)                                                              # needs mpmath
0
sage: lambert_w(e)                                                              # needs sage.symbolic
1
sage: lambert_w(-1/e)                                                           # needs sage.symbolic
-1
>>> from sage.all import *
>>> lambert_w(Integer(0))                                                              # needs mpmath
0
>>> lambert_w(e)                                                              # needs sage.symbolic
1
>>> lambert_w(-Integer(1)/e)                                                           # needs sage.symbolic
-1

Integration (of the principal branch) is evaluated using Maxima:

sage: integrate(lambert_w(x), x)                                                # needs sage.symbolic
(lambert_w(x)^2 - lambert_w(x) + 1)*x/lambert_w(x)
sage: integrate(lambert_w(x), x, 0, 1)                                          # needs sage.symbolic
(lambert_w(1)^2 - lambert_w(1) + 1)/lambert_w(1) - 1
sage: integrate(lambert_w(x), x, 0, 1.0)                                        # needs sage.symbolic
0.3303661247616807
>>> from sage.all import *
>>> integrate(lambert_w(x), x)                                                # needs sage.symbolic
(lambert_w(x)^2 - lambert_w(x) + 1)*x/lambert_w(x)
>>> integrate(lambert_w(x), x, Integer(0), Integer(1))                                          # needs sage.symbolic
(lambert_w(1)^2 - lambert_w(1) + 1)/lambert_w(1) - 1
>>> integrate(lambert_w(x), x, Integer(0), RealNumber('1.0'))                                        # needs sage.symbolic
0.3303661247616807

Warning: The integral of a non-principal branch is not implemented, neither is numerical integration using GSL. The numerical_integral() function does work if you pass a lambda function:

sage: numerical_integral(lambda x: lambert_w(x), 0, 1)                          # needs sage.modules
(0.33036612476168054, 3.667800782666048e-15)
>>> from sage.all import *
>>> numerical_integral(lambda x: lambert_w(x), Integer(0), Integer(1))                          # needs sage.modules
(0.33036612476168054, 3.667800782666048e-15)
class sage.functions.log.Function_log1[source]#

Bases: GinacFunction

The natural logarithm of x.

See log() for extensive documentation.

EXAMPLES:

sage: ln(e^2)                                                                   # needs sage.symbolic
2
sage: ln(2)                                                                     # needs sage.symbolic
log(2)
sage: ln(10)                                                                    # needs sage.symbolic
log(10)
>>> from sage.all import *
>>> ln(e**Integer(2))                                                                   # needs sage.symbolic
2
>>> ln(Integer(2))                                                                     # needs sage.symbolic
log(2)
>>> ln(Integer(10))                                                                    # needs sage.symbolic
log(10)
class sage.functions.log.Function_log2[source]#

Bases: GinacFunction

Return the logarithm of x to the given base.

See log() for extensive documentation.

EXAMPLES:

sage: from sage.functions.log import logb
sage: logb(1000, 10)                                                            # needs sage.symbolic
3
>>> from sage.all import *
>>> from sage.functions.log import logb
>>> logb(Integer(1000), Integer(10))                                                            # needs sage.symbolic
3
class sage.functions.log.Function_polylog[source]#

Bases: GinacFunction

The polylog function \(\text{Li}_s(z) = \sum_{k=1}^{\infty} z^k / k^s\).

The first argument is \(s\) (usually an integer called the weight) and the second argument is \(z\): polylog(s, z).

This definition is valid for arbitrary complex numbers \(s\) and \(z\) with \(|z| < 1\). It can be extended to \(|z| \ge 1\) by the process of analytic continuation, with a branch cut along the positive real axis from \(1\) to \(+\infty\). A NaN value may be returned for floating point arguments that are on the branch cut.

EXAMPLES:

sage: # needs sage.symbolic
sage: polylog(2.7, 0)
0.000000000000000
sage: polylog(2, 1)
1/6*pi^2
sage: polylog(2, -1)
-1/12*pi^2
sage: polylog(3, -1)
-3/4*zeta(3)
sage: polylog(2, I)
I*catalan - 1/48*pi^2
sage: polylog(4, 1/2)
polylog(4, 1/2)
sage: polylog(4, 0.5)
0.517479061673899

sage: # needs sage.symbolic
sage: polylog(1, x)
-log(-x + 1)
sage: polylog(2, x^2 + 1)
dilog(x^2 + 1)
sage: f = polylog(4, 1); f
1/90*pi^4
sage: f.n()
1.08232323371114
sage: polylog(4, 2).n()
2.42786280675470 - 0.174371300025453*I
sage: complex(polylog(4, 2))
(2.4278628067547032-0.17437130002545306j)
sage: float(polylog(4, 0.5))
0.5174790616738993
sage: z = var('z')
sage: polylog(2, z).series(z==0, 5)
1*z + 1/4*z^2 + 1/9*z^3 + 1/16*z^4 + Order(z^5)

sage: loads(dumps(polylog))
polylog

sage: latex(polylog(5, x))                                                  # needs sage.symbolic
{\rm Li}_{5}(x)
sage: polylog(x, x)._sympy_()                                               # needs sympy sage.symbolic
polylog(x, x)
>>> from sage.all import *
>>> # needs sage.symbolic
>>> polylog(RealNumber('2.7'), Integer(0))
0.000000000000000
>>> polylog(Integer(2), Integer(1))
1/6*pi^2
>>> polylog(Integer(2), -Integer(1))
-1/12*pi^2
>>> polylog(Integer(3), -Integer(1))
-3/4*zeta(3)
>>> polylog(Integer(2), I)
I*catalan - 1/48*pi^2
>>> polylog(Integer(4), Integer(1)/Integer(2))
polylog(4, 1/2)
>>> polylog(Integer(4), RealNumber('0.5'))
0.517479061673899

>>> # needs sage.symbolic
>>> polylog(Integer(1), x)
-log(-x + 1)
>>> polylog(Integer(2), x**Integer(2) + Integer(1))
dilog(x^2 + 1)
>>> f = polylog(Integer(4), Integer(1)); f
1/90*pi^4
>>> f.n()
1.08232323371114
>>> polylog(Integer(4), Integer(2)).n()
2.42786280675470 - 0.174371300025453*I
>>> complex(polylog(Integer(4), Integer(2)))
(2.4278628067547032-0.17437130002545306j)
>>> float(polylog(Integer(4), RealNumber('0.5')))
0.5174790616738993
>>> z = var('z')
>>> polylog(Integer(2), z).series(z==Integer(0), Integer(5))
1*z + 1/4*z^2 + 1/9*z^3 + 1/16*z^4 + Order(z^5)

>>> loads(dumps(polylog))
polylog

>>> latex(polylog(Integer(5), x))                                                  # needs sage.symbolic
{\rm Li}_{5}(x)
>>> polylog(x, x)._sympy_()                                               # needs sympy sage.symbolic
polylog(x, x)