 esote.net

# Lambert W function

The Lambert W function W(x), also called the omega function or the product logarithm, is the inverse of the function . It is used as the solution to many problems that cannot be solved using normal methods. While the Lambert W function is actually a set of functions, this program focuses on its principal branch .

Example values of the Lambert W function
W(x) Result
W(0)0
W(1)0.56714
W(-1)-0.31813+1.33723 i
W(i)0.374699+0.576413 i
W(-i)0.374699-0.576413 i
W(e)1
W(-e)0.39497...+1.78818...i

The Lambert W function can be approximated using Newton's method and Halley's method, although methods with faster approximation can be constructed. These methods use successive approximation to converge towards the value of W(x). Newton's method converges quadratically and Halley's method converges cubically.

I do not include imaginary results. I take advantage of Boost to allow for arbitrary precision. You can change the value of const int PRECISION to increase the output precision. Often the last digit is rounded or not precise. This inaccuracy can be counteracted by increasing PRECISION.

### Lambert-W-function-v1.cpp

This first version uses Newton's method to converge towards W(x) using the formula: Breakdown:

1. Gets the value of x in the form of a string;

2. Checks if the string contains more than one decimal mark;

3. Checks if the string is in the format of a decimal fraction (so not the letter "j", for example) by converting it to a double in a try-catch block;

4. Converts it to the arbFloat data type, the name I chose for Boost's multiprecision cpp_dec_float;

5. Number is checked to see if it is less than zero (which would return a complex number);

6. Calculations (explained a few lines down).

In this version, there is a bound on the input of x ≤ 1E9. Inside of the for loop, it is simple:

1. Convert initial value of wnew to a string, and set the string's precision;

2. Use the simplified Newton's method to approximate W(x);

3. Convert the value of wnew after calculations to a string, and set the strings precision;

4. Compare the pre-calculation string and post-calculation string: if they are the same, it means the precision was exceeded.

### Lambert-W-function-v2.cpp

• Originally, I was using Newton's method, which converges quadratically. Now I am using Halley's method, which converges cubically. This is much faster when finding larger values: • I am new using std::getline instead of std::cin;

• In the Boolean function isStringValid, I am now checking the following things:

1. Spaces in the string;

2. Multiple decimal marks in the string, optimized from the previous version;

3. If, when converted to an arbFloat, it results in a runtime error (usually due to an extremely large value like , or an incorrect data type, like null);

4. If, when converted to an arbFloat, it results in a non-runtime error (usually due to the input not being a number);

5. If the user intentionally entered NaN.

• In the Boolean function isNumberValid, I am now checking the following:

1. If the input is less than 0, which is a complex number;

2. If the input is infinity (or at least perceived as infinity), this is the result of either inputs like (which is smaller than the catch for parsing errors, but too large to be computed), or if the value INF is intentionally entered.

• Originally, the starting guess was 0, but now guessing is smarter;

• Replaced for-loop with do-while loop, because the limit i < 1E99 is unnecessary with the other range checks;

• Originally, I used Boost's .convert_to for the string-to-arbFloat conversion, but now I use static_cast. The string-to-arbFloat and string resizing has been abstracted to an inline function resizeArbtoString();

• All of the functions now take constant-referenced arguments, to avoid pointlessly copying the variable.

With the new improvements, the value of W(x) within a computable range can be calculated in seconds with around 5 iterations!

### Lambert-W-function-v3.cpp

• Moved declaration of wnew to its first usage;

• Switched the if-else to the ternary operator ?:;

• Moved the declaration of the preComp and postComp strings closer to their first usage;

• Replaced the do-while loop for a for-loop, which is optimal compared to the original for-loop, and the previous do-while loop.

### Lambert-W-function-v4.cpp

• Removed magic numbers used to return error codes and replaced them with enums.

#### Example

0 <= x < inf
W(x), x = 58491.4859194

Initial Guess: 8.79912818825742701263554005635953367481999598927155403916723877200983598181966539704818806245543085
Convergence:
8.79912818825742701263554005635953367481999598927155403916723877200983598181966539704818806245543085
8.801692453591711067034391690021038727530168930812754421891411409540457859585438570795243845704890877
8.801692455327469805597939732638277031925622767561811681524957334633929913212419954962801678030124737
8.801692455327469805597939733176608343067236688470654778832038917101125243949975035911147451410329376
8.801692455327469805597939733176608343067236688470654778832038917101125243949975035927206894516430969

W(58491.4859194) = 8.801692455327469805597939733176608343067236688470654778832038917101125243949975035927206894516430969
(rounded up to 100 digits, precise after 5 iterations)