/* 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; }