lambert_w_high_reference_values.cpp 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  1. // \modular-boost\libs\math\test\lambert_w_high_reference_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 \lambert_w_mp_hi_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. // These cover the range from 0.5 to (std::numeric_limits<>::max)();
  11. // The Fukushima algorithm changes from a series function for all z > 0.5.
  12. // Multiprecision types:
  13. //#include <boost/multiprecision/cpp_bin_float.hpp>
  14. #include <boost/multiprecision/cpp_dec_float.hpp> // boost::multiprecision::cpp_dec_float_100
  15. using boost::multiprecision::cpp_dec_float_100;
  16. #include <boost/math/special_functions/lambert_w.hpp> //
  17. using boost::math::lambert_w0;
  18. using boost::math::lambert_wm1;
  19. #include <iostream>
  20. // using std::cout; using std::std::endl; using std::ios; using std::std::cerr;
  21. #include <iomanip>
  22. using std::setprecision;
  23. using std::showpoint;
  24. #include <fstream>
  25. using std::ofstream;
  26. #include <cassert>
  27. #include <cfloat> // for DBL_EPS etc
  28. #include <limits> // for numeric limits.
  29. //#include <ctype>
  30. #include <string>
  31. const long double eps = std::numeric_limits<long double>::epsilon();
  32. // Creates if no file exists, & uses default overwrite/ ios::replace.
  33. const char filename[] = "lambert_w_high_reference_values.ipp"; //
  34. std::ofstream fout(filename, std::ios::out);
  35. typedef cpp_dec_float_100 RealType; // 100 decimal digits for the value fed to macro BOOST_MATH_TEST_VALUE.
  36. // Could also use cpp_dec_float_50 or cpp_bin_float types.
  37. const int no_of_tests = 450; // 500 overflows float.
  38. static const float min_z = 0.5F; // for element[0]
  39. int main()
  40. { // Make C++ file containing Lambert W test values.
  41. std::cout << filename << " ";
  42. std::cout << std::endl;
  43. std::cout << "Lambert W0 decimal digit precision values for high z argument values." << std::endl;
  44. if (!fout.is_open())
  45. { // File failed to open OK.
  46. std::cerr << "Open file " << filename << " failed!" << std::endl;
  47. std::cerr << "errno " << errno << std::endl;
  48. return -1;
  49. }
  50. try
  51. {
  52. int output_precision = std::numeric_limits<RealType>::digits10;
  53. // cpp_dec_float_100 is ample precision and
  54. // has several extra bits internally so max_digits10 are not needed.
  55. fout.precision(output_precision);
  56. fout << std::showpoint << std::endl; // Do show trailing zeros.
  57. // Intro for RealType values.
  58. std::cout << "Lambert W test values written to file " << filename << std::endl;
  59. fout <<
  60. "\n"
  61. "// A collection of big Lambert W test values computed using "
  62. << output_precision << " decimal digits precision.\n"
  63. "// C++ floating-point type is " << "RealType." "\n"
  64. "\n"
  65. "// Written by " << __FILE__ << " " << __TIMESTAMP__ << "\n"
  66. "\n"
  67. "// Copyright Paul A. Bristow 2017." "\n"
  68. "// Distributed under the Boost Software License, Version 1.0." "\n"
  69. "// (See accompanying file LICENSE_1_0.txt" "\n"
  70. "// or copy at http://www.boost.org/LICENSE_1_0.txt)" "\n"
  71. << std::endl;
  72. fout << "// Size of arrays of arguments z and Lambert W" << std::endl;
  73. fout << "static const unsigned int noof_tests = " << no_of_tests << ";" << std::endl;
  74. // Declare arrays of z and Lambert W.
  75. fout << "\n// Declare arrays of arguments z and Lambert W(z)" << std::endl;
  76. fout <<
  77. "\n"
  78. "template <typename RealType>""\n"
  79. "static RealType zs[" << no_of_tests << "];"
  80. << std::endl;
  81. fout <<
  82. "\n"
  83. "template <typename RealType>""\n"
  84. "static RealType ws[" << no_of_tests << "];"
  85. << std::endl;
  86. fout << "// The values are defined using the macro BOOST_MATH_TEST_VALUE to ensure\n"
  87. "// that both built-in and multiprecision types are correctly initialiased with full precision.\n"
  88. "// built-in types like float, double require a floating-point literal like 3.14,\n"
  89. "// but multiprecision types require a decimal digit string like \"3.14\".\n"
  90. "// Numerical values are chosen to avoid exactly representable values."
  91. << std::endl;
  92. static const RealType min_z = 0.6; // for element[0]
  93. const RealType max_z = (std::numeric_limits<float>::max)() / 10; // (std::numeric_limits<float>::max)() to make sure is OK for all floating-point types.
  94. // Less a bit as lambert_w0(max) may be inaccurate.
  95. const RealType step_size = 0.5F; // Increment step size.
  96. const RealType step_factor = 2.f; // Multiple factor, typically 2, 5 or 10.
  97. const int step_modulo = 5;
  98. RealType z = min_z;
  99. // Output function to initialize array of arguments z and Lambert W.
  100. fout <<
  101. "\n"
  102. << "template <typename RealType>\n"
  103. "void init_zws()\n"
  104. "{\n";
  105. for (size_t index = 0; (index != no_of_tests); index++)
  106. {
  107. fout
  108. << " zs<RealType>[" << index << "] = BOOST_MATH_TEST_VALUE(RealType, "
  109. << z // Since start with converting a float may get lots of usefully random digits.
  110. << ");"
  111. << std::endl;
  112. fout
  113. << " ws<RealType>[" << index << "] = BOOST_MATH_TEST_VALUE(RealType, "
  114. << lambert_w0(z)
  115. << ");"
  116. << std::endl;
  117. if ((index % step_modulo) == 0)
  118. {
  119. z *= step_factor; //
  120. }
  121. z += step_size;
  122. if (z >= max_z)
  123. { // Don't go over max for float.
  124. std::cout << "too big z" << std::endl;
  125. break;
  126. }
  127. } // for index
  128. fout << "};" << std::endl;
  129. fout << "// End of lambert_w_mp_high_values.ipp " << std::endl;
  130. }
  131. catch (std::exception& ex)
  132. {
  133. std::cout << "Exception " << ex.what() << std::endl;
  134. }
  135. fout.close();
  136. std::cout << no_of_tests << " Lambert_w0 values written to files " << __TIMESTAMP__ << std::endl;
  137. return 0;
  138. } // main
  139. /*
  140. A few spot checks again Wolfram:
  141. zs<RealType>[1] = BOOST_MATH_TEST_VALUE(RealType, 1.6999999999999999555910790149937383830547332763671875);
  142. ws<RealType>[1] = BOOST_MATH_TEST_VALUE(RealType, 0.7796011225311008662356536916883580556792500749037209859530390902424444585607630246126725241921761054);
  143. Wolfram 0.7796011225311008662356536916883580556792500749037209859530390902424444585607630246126725241921761054
  144. zs<RealType>[99] = BOOST_MATH_TEST_VALUE(RealType, 3250582.599999999976716935634613037109375);
  145. ws<RealType>[99] = BOOST_MATH_TEST_VALUE(RealType, 12.47094339016839065212822905567651460418204106065566910956134121802725695306834966790193342511971825);
  146. Wolfram 12.47094339016839065212822905567651460418204106065566910956134121802725695306834966790193342511971825
  147. */