lambert_w_low_reference_values.cpp 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237
  1. // lambert_w_test_values.cpp
  2. // Copyright Paul A. Bristow 2017.
  3. // Distributed under the Boost Software License, Version 1.0.
  4. // (See accompanying file LICENSE_1_0.txt
  5. // or copy at http://www.boost.org/LICENSE_1_0.txt)
  6. // Write a C++ file J:\Cpp\Misc\lambert_w_1000_test_values\lambert_w_mp_values.ipp
  7. // containing arrays of z arguments and 100 decimal digit precision lambert_w0(z) reference values.
  8. // These can be used in tests of precision of less-precise types like
  9. // built-in float, double, long double and quad and cpp_dec_float_50.
  10. // Multiprecision types:
  11. //#include <boost/multiprecision/cpp_bin_float.hpp>
  12. #include <boost/multiprecision/cpp_dec_float.hpp> // boost::multiprecision::cpp_dec_float_100
  13. using boost::multiprecision::cpp_dec_float_100;
  14. #include <boost/math/special_functions/lambert_w.hpp> //
  15. using boost::math::lambert_w0;
  16. #include <iostream>
  17. // using std::cout; using std::std::endl; using std::ios; using std::std::cerr;
  18. #include <iomanip>
  19. using std::setprecision;
  20. using std::showpoint;
  21. #include <fstream>
  22. using std::ofstream;
  23. #include <cassert>
  24. #include <cfloat> // for DBL_EPS etc
  25. #include <limits> // for numeric limits.
  26. //#include <ctype>
  27. #include <string>
  28. #include <algorithm>
  29. using std::transform;
  30. const char* prefix = "static "; // "static const" or "static constexpr" or just "const "" or "" even?
  31. // But problems with VS2017 and GCC not accepting same format mean only static at present.
  32. const long double eps = std::numeric_limits<long double>::epsilon();
  33. /*
  34. // Sample test values from Wolfram.
  35. template <typename RealType>
  36. static RealType zs[noof_tests];
  37. template <typename RealType>
  38. void init_zs()
  39. {
  40. zs<RealType>[0] = BOOST_MATH_TEST_VALUE(RealType, -0.35);
  41. zs<RealType>[1] = BOOST_MATH_TEST_VALUE(RealType, -0.3);
  42. zs<RealType>[2] = BOOST_MATH_TEST_VALUE(RealType, -0.01);
  43. zs<RealType>[3] = BOOST_MATH_TEST_VALUE(RealType, +0.01);
  44. zs<RealType>[4] = BOOST_MATH_TEST_VALUE(RealType, 0.1);
  45. zs<RealType>[5] = BOOST_MATH_TEST_VALUE(RealType, 0.5);
  46. zs<RealType>[6] = BOOST_MATH_TEST_VALUE(RealType, 1.);
  47. zs<RealType>[7] = BOOST_MATH_TEST_VALUE(RealType, 2.);
  48. zs<RealType>[8] = BOOST_MATH_TEST_VALUE(RealType, 5.);
  49. zs<RealType>[9] = BOOST_MATH_TEST_VALUE(RealType, 10.);
  50. zs<RealType>[10] = BOOST_MATH_TEST_VALUE(RealType, 100.);
  51. zs<RealType>[11] = BOOST_MATH_TEST_VALUE(RealType, 1e+6);
  52. };
  53. // 'Known good' Lambert w values using N[productlog(-0.3), 50]
  54. // evaluated to full precision of RealType (up to 50 decimal digits).
  55. template <typename RealType>
  56. static RealType ws[noof_tests];
  57. template <typename RealType>
  58. void init_ws()
  59. {
  60. ws<RealType>[0] = BOOST_MATH_TEST_VALUE(RealType, -0.7166388164560738505881698000038650406110575701385055261614344530078353170171071547711151137001759321);
  61. ws<RealType>[1] = BOOST_MATH_TEST_VALUE(RealType, -0.4894022271802149690362312519962933689234100060163590345114659679736814083816206187318524147462752111);
  62. ws<RealType>[2] = BOOST_MATH_TEST_VALUE(RealType, -0.01010152719853875327292018767138623973670903993475235877290726369225412969738704722202330440072213641);
  63. ws<RealType>[3] = BOOST_MATH_TEST_VALUE(RealType, 0.009901473843595011885336326816570107953627746494917415482611387085655068978243229360100010886171970918);
  64. ws<RealType>[4] = BOOST_MATH_TEST_VALUE(RealType, 0.09127652716086226429989572142317956865311922405147203264830839460717224625441755165020664592995606710);
  65. ws<RealType>[5] = BOOST_MATH_TEST_VALUE(RealType, 0.3517337112491958260249093009299510651714642155171118040466438461099606107203387108968323038321915693);
  66. ws<RealType>[6] = BOOST_MATH_TEST_VALUE(RealType, 0.5671432904097838729999686622103555497538157871865125081351310792230457930866845666932194469617522946); // Output from https://www.wolframalpha.com/input/?i=lambert_w0(1)
  67. ws<RealType>[7] = BOOST_MATH_TEST_VALUE(RealType, 0.8526055020137254913464724146953174668984533001514035087721073946525150656742630448965773783502494847);
  68. ws<RealType>[8] = BOOST_MATH_TEST_VALUE(RealType, 1.326724665242200223635099297758079660128793554638047479789290393025342679920536226774469916608426789); // https://www.wolframalpha.com/input/?i=N%5Bproductlog(5),+100%5D
  69. ws<RealType>[9] = BOOST_MATH_TEST_VALUE(RealType, 1.745528002740699383074301264875389911535288129080941331322206048555557259941551704989523510778883075);
  70. ws<RealType>[10] = BOOST_MATH_TEST_VALUE(RealType, 3.385630140290050184888244364529726867491694170157806680386174654885206544913039277686735236213650781);
  71. ws<RealType>[11] = BOOST_MATH_TEST_VALUE(RealType, 11.38335808614005262200015678158500428903377470601886512143238610626898610768018867797709315493717650);
  72. ////W(1e35) = 76.256377207295812974093508663841808129811690961764 too big for float.
  73. };
  74. */
  75. // Global so accessible from output_value.
  76. // Creates if no file exists, & uses default overwrite/ ios::replace.
  77. const char filename[] = "lambert_w_low_reference values.ipp"; //
  78. std::ofstream fout(filename, std::ios::out); ; //
  79. // 100 decimal digits for the value fed to macro BOOST_MATH_TEST_VALUE
  80. typedef cpp_dec_float_100 RealType;
  81. void output_value(size_t index, RealType value)
  82. {
  83. fout
  84. << " zs<RealType>[" << index << "] = BOOST_MATH_TEST_VALUE(RealType, "
  85. << value
  86. << ");"
  87. << std::endl;
  88. return;
  89. }
  90. void output_lambert_w0(size_t index, RealType value)
  91. {
  92. fout
  93. << " ws<RealType>[" << index << "] = BOOST_MATH_TEST_VALUE(RealType, "
  94. << lambert_w0(value)
  95. << ");"
  96. << std::endl;
  97. return;
  98. }
  99. int main()
  100. { // Make C++ file containing Lambert W test values.
  101. std::cout << filename << " ";
  102. #ifdef __TIMESTAMP__
  103. std::cout << __TIMESTAMP__;
  104. #endif
  105. std::cout << std::endl;
  106. std::cout << "Lambert W0 decimal digit precision values." << std::endl;
  107. // Note __FILE__ & __TIMESTAMP__ are ANSI standard C & thus Std C++?
  108. if (!fout.is_open())
  109. { // File failed to open OK.
  110. std::cerr << "Open file " << filename << " failed!" << std::endl;
  111. std::cerr << "errno " << errno << std::endl;
  112. return -1;
  113. }
  114. int output_precision = std::numeric_limits<cpp_dec_float_100>::digits10;
  115. // cpp_dec_float_100 is ample precision and
  116. // has several extra bits internally so max_digits10 are not needed.
  117. fout.precision(output_precision);
  118. int no_of_tests = 100;
  119. // Intro for RealType values.
  120. std::cout << "Lambert W test values written to file " << filename << std::endl;
  121. fout <<
  122. "\n"
  123. "// A collection of Lambert W test values computed using "
  124. << output_precision << " decimal digits precision.\n"
  125. "// C++ floating-point type is " << "RealType." "\n"
  126. "\n"
  127. "// Written by " << __FILE__ << " " << __TIMESTAMP__ << "\n"
  128. "\n"
  129. "// Copyright Paul A. Bristow 2017." "\n"
  130. "// Distributed under the Boost Software License, Version 1.0." "\n"
  131. "// (See accompanying file LICENSE_1_0.txt" "\n"
  132. "// or copy at http://www.boost.org/LICENSE_1_0.txt)" "\n"
  133. << std::endl;
  134. fout << "// Size of arrays of arguments z and Lambert W" << std::endl;
  135. fout << "static const unsigned int noof_tests = " << no_of_tests << ";" << std::endl;
  136. // Declare arrays of z and Lambert W.
  137. fout << "// Declare arrays of arguments z and Lambert W(z)" << std::endl;
  138. fout << "// The values are defined using the macro BOOST_MATH_TEST_VALUE to ensure\n"
  139. "// that both built-in and multiprecision types are correctly initialiased with full precision.\n"
  140. "// built-in types like double require a floating-point literal like 3.14,\n"
  141. "// but multiprecision types require a decimal digit string like \"3.14\".\n"
  142. << std::endl;
  143. fout <<
  144. "\n"
  145. "template <typename RealType>""\n"
  146. "static RealType zs[" << no_of_tests << "];"
  147. << std::endl;
  148. fout <<
  149. "\n"
  150. "template <typename RealType>""\n"
  151. "static RealType ws[" << no_of_tests << "];"
  152. << std::endl;
  153. RealType max_z("10");
  154. RealType min_z("-0.35");
  155. RealType step_size("0.01");
  156. size_t step_count = no_of_tests;
  157. // Output to initialize array of arguments z for Lambert W.
  158. fout <<
  159. "\n"
  160. << "template <typename RealType>\n"
  161. "void init_zs()\n"
  162. "{\n";
  163. RealType z = min_z;
  164. for (size_t i = 0; (i < no_of_tests); i++)
  165. {
  166. output_value(i, z);
  167. z += step_size;
  168. }
  169. fout << "};" << std::endl;
  170. // Output array of Lambert W values.
  171. fout <<
  172. "\n"
  173. << "template <typename RealType>\n"
  174. "void init_ws()\n"
  175. "{\n";
  176. z = min_z;
  177. for (size_t i = 0; (i < step_count); i++)
  178. {
  179. output_lambert_w0(i, z);
  180. z += step_size;
  181. }
  182. fout << "};" << std::endl;
  183. fout << "// End of lambert_w_mp_values.ipp " << std::endl;
  184. fout.close();
  185. std::cout << "Lambert_w0 values written to files " << __TIMESTAMP__ << std::endl;
  186. return 0;
  187. } // main
  188. /*
  189. start and finish checks again Wolfram Alpha:
  190. ws<RealType>[0] = BOOST_MATH_TEST_VALUE(RealType, -0.7166388164560738505881698000038650406110575701385055261614344530078353170171071547711151137001759321);
  191. Wolfram N[productlog(-0.35), 100] -0.7166388164560738505881698000038650406110575701385055261614344530078353170171071547711151137001759321
  192. ws<RealType>[19] = BOOST_MATH_TEST_VALUE(RealType, 0.7397278549447991214587608743391115983469848985053641692586810406118264600667862543570373167046626221);
  193. Wolfram N[productlog(1.55), 100] 0.7397278549447991214587608743391115983469848985053641692586810406118264600667862543570373167046626221
  194. */