test_lambert_w_derivative.cpp 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  1. // Copyright Paul A. Bristow 2016, 2017, 2018.
  2. // Copyright John Maddock 2016.
  3. // Use, modification and distribution are subject to the
  4. // Boost Software License, Version 1.0.
  5. // (See accompanying file LICENSE_1_0.txt
  6. // or copy at http://www.boost.org/LICENSE_1_0.txt)
  7. // test_lambert_w.cpp
  8. //! \brief Basic sanity tests for Lambert W derivative.
  9. #ifdef BOOST_MATH_TEST_FLOAT128
  10. #include <boost/cstdfloat.hpp> // For float_64_t, float128_t. Must be first include!
  11. #endif // #ifdef #ifdef BOOST_MATH_TEST_FLOAT128
  12. // Needs gnu++17 for BOOST_HAS_FLOAT128
  13. #include <boost/config.hpp> // for BOOST_MSVC definition etc.
  14. #include <boost/version.hpp> // for BOOST_MSVC versions.
  15. // Boost macros
  16. #define BOOST_TEST_MAIN
  17. #define BOOST_LIB_DIAGNOSTIC "on" // Report library file details.
  18. #include <boost/test/included/unit_test.hpp> // Boost.Test
  19. // #include <boost/test/unit_test.hpp> // Boost.Test
  20. #include <boost/test/tools/floating_point_comparison.hpp>
  21. #include <boost/array.hpp>
  22. #include <boost/lexical_cast.hpp>
  23. #include <boost/type_traits/is_constructible.hpp>
  24. #ifdef BOOST_MATH_TEST_MULTIPRECISION
  25. #include <boost/multiprecision/cpp_dec_float.hpp> // boost::multiprecision::cpp_dec_float_50
  26. using boost::multiprecision::cpp_dec_float_50;
  27. #include <boost/multiprecision/cpp_bin_float.hpp>
  28. using boost::multiprecision::cpp_bin_float_quad;
  29. #ifdef BOOST_MATH_TEST_FLOAT128
  30. #ifdef BOOST_HAS_FLOAT128
  31. // Including this header below without float128 triggers:
  32. // fatal error C1189: #error: "Sorry compiler is neither GCC, not Intel, don't know how to configure this header."
  33. #include <boost/multiprecision/float128.hpp>
  34. using boost::multiprecision::float128;
  35. #endif // ifdef BOOST_HAS_FLOAT128
  36. #endif // #ifdef #ifdef BOOST_MATH_TEST_FLOAT128
  37. #endif // #ifdef BOOST_MATH_TEST_MULTIPRECISION
  38. //#include <boost/fixed_point/fixed_point.hpp> // If available.
  39. #include <boost/math/concepts/real_concept.hpp> // for real_concept tests.
  40. #include <boost/math/special_functions/fpclassify.hpp> // isnan, ifinite.
  41. #include <boost/math/special_functions/next.hpp> // float_next, float_prior
  42. using boost::math::float_next;
  43. using boost::math::float_prior;
  44. #include <boost/math/special_functions/ulp.hpp> // ulp
  45. #include <boost/math/tools/test_value.hpp> // for create_test_value and macro BOOST_MATH_TEST_VALUE.
  46. #include <boost/math/policies/policy.hpp>
  47. using boost::math::policies::digits2;
  48. using boost::math::policies::digits10;
  49. #include <boost/math/special_functions/lambert_w.hpp> // For Lambert W lambert_w function.
  50. using boost::math::lambert_wm1;
  51. using boost::math::lambert_w0;
  52. #include <limits>
  53. #include <cmath>
  54. #include <typeinfo>
  55. #include <iostream>
  56. #include <exception>
  57. std::string show_versions(void);
  58. BOOST_AUTO_TEST_CASE( Derivatives_of_lambert_w )
  59. {
  60. std::cout << "Macro BOOST_MATH_LAMBERT_W_DERIVATIVES to test 1st derivatives is defined." << std::endl;
  61. BOOST_TEST_MESSAGE("\nTest Lambert W function 1st differentials.");
  62. using boost::math::constants::exp_minus_one;
  63. using boost::math::lambert_w0_prime;
  64. using boost::math::lambert_wm1_prime;
  65. // Derivatives
  66. // https://www.wolframalpha.com/input/?i=derivative+of+productlog(0,+x)
  67. // d/dx(W_0(x)) = W(x)/(x W(x) + x)
  68. // https://www.wolframalpha.com/input/?i=derivative+of+productlog(-1,+x)
  69. // d/dx(W_(-1)(x)) = (W_(-1)(x))/(x W_(-1)(x) + x)
  70. // 55 decimal digit values added to allow future testing using multiprecision.
  71. typedef double RealType;
  72. int epsilons = 1;
  73. RealType tolerance = boost::math::tools::epsilon<RealType>() * epsilons; // 2 eps as a fraction.
  74. // derivative of productlog(-1, x) at x = -0.1 == -13.8803
  75. // (derivative of productlog(-1, x) ) at x = N[-0.1, 55] - but the result disappears!
  76. // (derivative of N[productlog(-1, x), 55] ) at x = N[-0.1, 55]
  77. // W0 branch
  78. BOOST_CHECK_CLOSE_FRACTION(lambert_w0_prime(BOOST_MATH_TEST_VALUE(RealType, -0.2)),
  79. // BOOST_MATH_TEST_VALUE(RealType, 1.7491967609218355),
  80. BOOST_MATH_TEST_VALUE(RealType, 1.7491967609218358355273514903396335693828167746571404),
  81. tolerance); // 1.7491967609218358355273514903396335693828167746571404
  82. BOOST_CHECK_CLOSE_FRACTION(lambert_w0_prime(BOOST_MATH_TEST_VALUE(RealType, 10.)),
  83. BOOST_MATH_TEST_VALUE(RealType, 0.063577133469345105142021311010780887641928338458371618),
  84. tolerance);
  85. // W-1 branch
  86. BOOST_CHECK_CLOSE_FRACTION(lambert_wm1_prime(BOOST_MATH_TEST_VALUE(RealType, -0.1)),
  87. BOOST_MATH_TEST_VALUE(RealType, -13.880252213229780748699361486619519025203815492277715),
  88. tolerance);
  89. // Lambert W_prime -13.880252213229780748699361486619519025203815492277715, double -13.880252213229781
  90. BOOST_CHECK_CLOSE_FRACTION(lambert_wm1_prime(BOOST_MATH_TEST_VALUE(RealType, -0.2)),
  91. BOOST_MATH_TEST_VALUE(RealType, -8.2411940564179044961885598641955579728547896392013239),
  92. tolerance);
  93. // Lambert W_prime -8.2411940564179044961885598641955579728547896392013239, double -8.2411940564179051
  94. // Lambert W_prime 0.063577133469345105142021311010780887641928338458371618, double 0.063577133469345098
  95. }; // BOOST_AUTO_TEST_CASE("Derivatives of lambert_w")