You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

140 lines
3.2KB

  1. /*
  2. Command-line interface to the Lambert W function
  3. Copyright (C) 2011 Darko Veberic, darko.veberic@ijs.si
  4. This program is free software: you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation, either version 3 of the License, or
  7. (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with this program. If not, see <http://www.gnu.org/licenses/>.
  14. */
  15. /*
  16. This source implements an utility "lambertw" so that the
  17. numerical implementation of the Lambert W function can be
  18. easily obtained from the command line or be used in shell
  19. scripts.
  20. Usage:
  21. lambertw [branch] x
  22. - "branch" value is optional (default 0 is assumed) and can
  23. be only 0 or -1
  24. - x value for W(x); note that the definition range for
  25. branch 0 is [-1/e, infinity] and for branch -1 it is
  26. [-1/e, 0) where 1/e is approx. 0.367879
  27. Examples:
  28. ./lambertw 3.14 --> 1.073395661239825
  29. ./lambertw -0.2 --> -0.2591711018190738
  30. ./lambertw 0 1 --> 0.5671432904097838
  31. ./lambertw 0 0 --> 0
  32. ./lambertw -1 -0.2 --> -2.542641357773526
  33. ./lambertw -1 -0.3 --> -1.781337023421628
  34. */
  35. #include <LambertW.h>
  36. #include <FukushimaLambertW.h>
  37. #include <iostream>
  38. #include <iomanip>
  39. #include <cmath>
  40. #include <unistd.h>
  41. #include <stdlib.h>
  42. using namespace std;
  43. void
  44. Usage(const char* const argv[], const int argc = 0, const int index = -1)
  45. {
  46. cout << "Usage: " << argv[0] << " [-f] [-p #] [-b #] -x #" << endl;
  47. if (argc) {
  48. int len = 0;
  49. string line;
  50. for (int i = 0; i < argc; ++i) {
  51. line += argv[i];
  52. if (i == index-1)
  53. len = line.length();
  54. line += ' ';
  55. }
  56. if (argc == index)
  57. len = line.length() - 1;
  58. cout << "Your input:\n"
  59. << line << '\n'
  60. << string(len, ' ') << '^' << endl;
  61. }
  62. exit(1);
  63. }
  64. int
  65. main(int argc, char* argv[])
  66. {
  67. enum EVariant {
  68. eVeberic = 0,
  69. eFukushima
  70. };
  71. EVariant variant = eVeberic;
  72. int precision = 20;
  73. int branch = 0;
  74. double x = -1;
  75. opterr = 0;
  76. int c;
  77. while ((c = getopt(argc, argv, "fp:b:x:")) != -1) {
  78. switch (c) {
  79. case 'f':
  80. if (variant == eVeberic)
  81. variant = eFukushima;
  82. else
  83. Usage(argv, argc, optind);
  84. break;
  85. case 'p':
  86. precision = atoi(optarg);
  87. if (precision < 1 || precision > 30)
  88. Usage(argv, argc, optind);
  89. break;
  90. case 'b':
  91. branch = atoi(optarg);
  92. if (!(branch == -1 || branch == 0))
  93. Usage(argv, argc, optind);
  94. break;
  95. case 'x':
  96. x = atof(optarg);
  97. break;
  98. default:
  99. Usage(argv, argc, optind);
  100. break;
  101. }
  102. }
  103. if (x < -1/M_E || (branch == -1 && x > 0))
  104. Usage(argv, argc, argc);
  105. cout << setprecision(precision);
  106. switch (variant) {
  107. case eVeberic:
  108. cout << utl::LambertW(branch, x);
  109. break;
  110. case eFukushima:
  111. cout << Fukushima::LambertW(branch, x);
  112. break;
  113. }
  114. cout << endl;
  115. return EXIT_SUCCESS;
  116. }