# 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 .

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:

Gets the value of

`x`in the form of a string;Checks if the string contains more than one decimal mark;

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;

Converts it to the

`arbFloat`

data type, the name I chose for Boost's multiprecision`cpp_dec_float`

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

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:

Convert initial value of

`wnew`

to a string, and set the string's precision;Use the simplified Newton's method to approximate W(x);

Convert the value of

`wnew`

after calculations to a string, and set the strings precision;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:Spaces in the string;

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

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`

);If, when converted to an

`arbFloat`

, it results in a non-runtime error (usually due to the input not being a number);If the user intentionally entered

`NaN`

.

In the Boolean function

`isNumberValid`

, I am now checking the following:If the input is less than 0, which is a complex number;

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

`enum`

s.

#### 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)