lambertw
  by Pascal Getreuer

The MATLAB function lambertw included in this package is a self-contained M-function implementing the Lambert W function, also known as the W function or "product log." It is equivalent to the numerical mode of the Symbolic Math Toolbox's lambertw, however, no toolboxes are required to use this function.

Contents

Function Usage

w = lambertw(z) computes the principal value of the Lambert W function, W0. The input z may be a complex scalar or array. For real z, the result is real on the principal branch for z &ge -1/e.

w = lambertw(b,z) specifies which branch of the Lambert W function to compute. If z is an array, b may be either an integer array of the same size as z or an integer scalar. If z is a scalar, b may be an array of any size.

Background

The Lambert W function is defined as the function W(z) such that

W(z) eW(z) = z

for all complex values z. As log z is the inverse of ez, W(z) is the inverse of z ez. Like the complex logarithm, the Lambert W function is multivalued with a countably infinite number of branches. The branches are enumerated by the integers and are conventionally denoted by Wk for the kth branch.

The principal branch, W0(z), is real-valued for -1/e ≤ z. If -1/e ≤ z < 0, then the branch W-1(z) is also real-valued. In the complex plane, a surface plot of |W0(z)| is

x = linspace(-6,6,51);
y = linspace(-6,6,51);
[x,y] = meshgrid(x,y);
w = lambertw(x + i*y);

surf(x,y,abs(w));
axis([-6,6,-6,6,0,2.5]);
view(40,32);
xlabel('Re z');
ylabel('Im z');
title('|W_0(z)|');

Algebra with the Lambert W Function

Although the Lambert W function may not be so widely known as the inverse trigonometry functions, it has essentially the same purpose as acos, asin, etc. as a building-block tool for solving equations. The general approach is to manipulate all occurrences of the unknown variable x into an expression of the form f(x)ef(x).

Problem 1. Solve y = (x - 1) e2x for x.

Solution: The right-hand side is close to the necessary form f(x)ef(x), but some manipulation is necessary to change the factor (x - 1) and the exponent 2x into the same expression. Multiplying both sides by 2,

2y = (2x - 2) e2x.

This form is closer yet, the exponent is only missing the -2. Multiplying both sides by e-2 achieves the desired form,

2e-2y = (2x - 2) e2x-2.

At this point, the Lambert W function can be applied to yield

W(2e-2y) = 2x - 2,

which leads to the solution x = W(2e-2y)/2 + 1. Note that since W is multivalued, the solution is multivalued; there are multiple values of x satisfying the equation.

Problem 2. Solve bx = xa for x.

Solution: In this problem, there is initially no visible instance of the exponential function. Rewrite bx as ex log b, revealing

ex log b = xa
ex (log b)/a = x.

Divide the exponential over to the right-hand side, and multiply by -(log b)/a to find

1 = x e-x (log b)/a
-(log b)/a = (-x (log b)/a) e-x (log b)/a.

The right-hand side is now in the form f(x)ef(x) where the Lambert W function can be applied:

W(-(log b)/a) = -x (log b)/a.

The solution is x = -(a / log b) W(-(log b)/a).

Problem 3. An old result [1] is the closed-form expression for iterated exponentiation:

z z z ... =   W(-log z) .

-log z

Find z such that z z z ... = 2.

Solution: Using the formula,

-W(-log z) / log z = 2
W(-log z) = -2 log z
-log z = -2 log z e-2 log z
e2 log z = 2
z = 21/2.

Demos

The following command evaluates Wk(1) for k = -4,... 4:

w = lambertw((-4:4).',1)
w =

  -3.1630 -23.4277i
  -2.8536 -17.1135i
  -2.4016 -10.7763i
  -1.5339 - 4.3752i
   0.5671          
  -1.5339 + 4.3752i
  -2.4016 +10.7763i
  -2.8536 +17.1135i
  -3.1630 +23.4277i

These values are all solutions of w ew = 1. It is easy to verify numerically that they are solutions:

w.*exp(w)
ans =

   1.0000 - 0.0000i
   1.0000 - 0.0000i
   1.0000 + 0.0000i
   1.0000          
   1.0000          
   1.0000          
   1.0000 - 0.0000i
   1.0000 + 0.0000i
   1.0000 + 0.0000i

Problem 3 in the previous section mentioned the formula for evaluating iterated exponentiation:

z z z ... =   W(-log z) .

-log z

For example, set z = 1.3, then its iterated exponentiation is approximately zlim = 1.4710.

zlim = -lambertw(-log(z))/log(z)
zlim =

    1.4710

To verify this, computing z^z^z^...^z through 40 iterations shows that the iterated exponentiation does indeed converge to zlim.

zz(1) = z;
zlim = -lambertw(-log(z))/log(z);

for k = 1:40
   zz(k+1) = z^zz(k);
end

plot(zz,'.-');
  k    zz     zlim-zz
  1  1.4065   0.065
  2  1.4463   0.025
  3  1.4615   0.0095
  4  1.4673   0.0037
  5  1.4696   0.0014
  6  1.4704   0.00055
  7  1.4708   0.00021
  8  1.4709   8.1e-005
  9  1.4710   3.1e-005
 10  1.4710   1.2e-005
 20  1.4710   8.9e-010
 30  1.4710   6.5e-014
 40  1.4710   2.2e-016
 

Test

Ideally, lambertw(b,z)*exp(lambertw(b,z)) = z for any complex z and any integer branch index b, but this is limited by machine precision. The inversion error |lambertw(b,z)*exp(lambertw(b,z)) - z| is small but worth minding.

Experimentation finds that the error is usually on the order of |z|´10-16 on the principal branch. This test computes the inversion error over the square [-10,10]´[-10,10] in the complex plane, large enough to characterize the error away from the branch points at z = 0 and -1/e.

N = 81;    % Use NxN points to sample the complex plane
R = 10;    % Sample in the square [-R,R]x[-R,R]
x = linspace(-R,R,N);
y = linspace(-R,R,N);
[xx,yy] = meshgrid(x,y);
z = xx + 1i*yy;

for b = -4:4
   w = lambertw(b,z);
   InvError = abs(w.*exp(w) - z);   
   fprintf('Largest error for b = %2d:  %.2e\n',b,max(InvError(:)));
end
Largest error for b = -4:  2.51e-014
Largest error for b = -3:  2.39e-014
Largest error for b = -2:  1.39e-014
Largest error for b = -1:  7.94e-015
Largest error for b =  0:  5.40e-015
Largest error for b =  1:  7.94e-015
Largest error for b =  2:  1.39e-014
Largest error for b =  3:  2.39e-014
Largest error for b =  4:  2.51e-014

Implementation

The Lambert W function is implemented numerically with approximations from series expansions followed by root-finding. Depending on the desired branch and the proximity to the branch points at z = 0 and -1/e, different series expansions are used as initializations to the root-finder.

As developed in [2], lambertw uses Halley's method, a fourth-order extension of Newton's root-finding method. Convergence is very fast, usually requiring fewer than 5 iterations to reach machine accuracy.

References

[1] G. Eisenstein, "Entwicklung von aa...." J. reine angewandte Math., vol. 28, 1844.
[2] R.M. Corless, G.H. Gonnet, D.E.G. Hare, G.J. Jeffery, and D.E. Knuth. "On the Lambert W Function." Advances in Computational Mathematics, vol. 5, 1996.