/*
Command-line interface to the Lambert W function
Copyright (C) 2011 Darko Veberic, darko.veberic@ijs.si
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see .
*/
/*
This source implements an utility "lambertw" so that the
numerical implementation of the Lambert W function can be
easily obtained from the command line or be used in shell
scripts.
Usage:
lambertw [branch] x
- "branch" value is optional (default 0 is assumed) and can
be only 0 or -1
- x value for W(x); note that the definition range for
branch 0 is [-1/e, infinity] and for branch -1 it is
[-1/e, 0) where 1/e is approx. 0.367879
Examples:
./lambertw 3.14 --> 1.073395661239825
./lambertw -0.2 --> -0.2591711018190738
./lambertw 0 1 --> 0.5671432904097838
./lambertw 0 0 --> 0
./lambertw -1 -0.2 --> -2.542641357773526
./lambertw -1 -0.3 --> -1.781337023421628
*/
#include
#include
#include
#include
#include
#include
#include
using namespace std;
void
Usage(const char* const argv[], const int argc = 0, const int index = -1)
{
cout << "Usage: " << argv[0] << " [-f] [-p #] [-b #] -x #" << endl;
if (argc) {
int len = 0;
string line;
for (int i = 0; i < argc; ++i) {
line += argv[i];
if (i == index-1)
len = line.length();
line += ' ';
}
if (argc == index)
len = line.length() - 1;
cout << "Your input:\n"
<< line << '\n'
<< string(len, ' ') << '^' << endl;
}
exit(1);
}
int
main(int argc, char* argv[])
{
enum EVariant {
eVeberic = 0,
eFukushima
};
EVariant variant = eVeberic;
int precision = 20;
int branch = 0;
double x = -1;
opterr = 0;
int c;
while ((c = getopt(argc, argv, "fp:b:x:")) != -1) {
switch (c) {
case 'f':
if (variant == eVeberic)
variant = eFukushima;
else
Usage(argv, argc, optind);
break;
case 'p':
precision = atoi(optarg);
if (precision < 1 || precision > 30)
Usage(argv, argc, optind);
break;
case 'b':
branch = atoi(optarg);
if (!(branch == -1 || branch == 0))
Usage(argv, argc, optind);
break;
case 'x':
x = atof(optarg);
break;
default:
Usage(argv, argc, optind);
break;
}
}
if (x < -1/M_E || (branch == -1 && x > 0))
Usage(argv, argc, argc);
cout << setprecision(precision);
switch (variant) {
case eVeberic:
cout << utl::LambertW(branch, x);
break;
case eFukushima:
cout << Fukushima::LambertW(branch, x);
break;
}
cout << endl;
return EXIT_SUCCESS;
}