File: test_lambert_w_derivative.cpp

package info (click to toggle)
boost1.74 1.74.0%2Bds1-21
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 463,588 kB
  • sloc: cpp: 3,338,117; xml: 131,293; python: 33,088; ansic: 14,292; asm: 4,038; sh: 3,353; makefile: 1,193; perl: 1,036; yacc: 478; php: 212; ruby: 102; lisp: 24; sql: 13; csh: 6
file content (124 lines) | stat: -rw-r--r-- 5,110 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
// Copyright Paul A. Bristow 2016, 2017, 2018.
// Copyright John Maddock 2016.

// Use, modification and distribution are subject to the
// Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt
// or copy at http://www.boost.org/LICENSE_1_0.txt)

// test_lambert_w.cpp
//! \brief Basic sanity tests for Lambert W derivative.

#ifdef BOOST_MATH_TEST_FLOAT128
#include <boost/cstdfloat.hpp> // For float_64_t, float128_t. Must be first include!
#endif // #ifdef #ifdef BOOST_MATH_TEST_FLOAT128
// Needs gnu++17 for BOOST_HAS_FLOAT128
#include <boost/config.hpp>   // for BOOST_MSVC definition etc.
#include <boost/version.hpp>   // for BOOST_MSVC versions.

// Boost macros
#define BOOST_TEST_MAIN
#define BOOST_LIB_DIAGNOSTIC "on" // Report library file details.
#include <boost/test/included/unit_test.hpp> // Boost.Test
// #include <boost/test/unit_test.hpp> // Boost.Test
#include <boost/test/tools/floating_point_comparison.hpp>

#include <boost/array.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/type_traits/is_constructible.hpp>

#ifdef BOOST_MATH_TEST_MULTIPRECISION
#include <boost/multiprecision/cpp_dec_float.hpp> // boost::multiprecision::cpp_dec_float_50
using boost::multiprecision::cpp_dec_float_50;

#include <boost/multiprecision/cpp_bin_float.hpp>
using boost::multiprecision::cpp_bin_float_quad;

#ifdef BOOST_MATH_TEST_FLOAT128

#ifdef BOOST_HAS_FLOAT128
// Including this header below without float128 triggers:
// fatal error C1189: #error:  "Sorry compiler is neither GCC, not Intel, don't know how to configure this header."
#include <boost/multiprecision/float128.hpp>
using boost::multiprecision::float128;
#endif // ifdef BOOST_HAS_FLOAT128
#endif // #ifdef #ifdef BOOST_MATH_TEST_FLOAT128

#endif //   #ifdef BOOST_MATH_TEST_MULTIPRECISION

//#include <boost/fixed_point/fixed_point.hpp> // If available.

#include <boost/math/concepts/real_concept.hpp> // for real_concept tests.
#include <boost/math/special_functions/fpclassify.hpp> // isnan, isfinite.
#include <boost/math/special_functions/next.hpp> // float_next, float_prior
using boost::math::float_next;
using boost::math::float_prior;
#include <boost/math/special_functions/ulp.hpp>  // ulp

#include <boost/math/tools/test_value.hpp>  // for create_test_value and macro BOOST_MATH_TEST_VALUE.
#include <boost/math/policies/policy.hpp>
using boost::math::policies::digits2;
using boost::math::policies::digits10;
#include <boost/math/special_functions/lambert_w.hpp> // For Lambert W lambert_w function.
using boost::math::lambert_wm1;
using boost::math::lambert_w0;

#include <limits>
#include <cmath>
#include <typeinfo>
#include <iostream>
#include <exception>

std::string show_versions(void);

BOOST_AUTO_TEST_CASE( Derivatives_of_lambert_w )
{
  std::cout << "Macro BOOST_MATH_LAMBERT_W_DERIVATIVES to test 1st derivatives is defined." << std::endl;
  BOOST_TEST_MESSAGE("\nTest Lambert W function 1st differentials.");

  using boost::math::constants::exp_minus_one;
  using boost::math::lambert_w0_prime;
  using boost::math::lambert_wm1_prime;

  // Derivatives
  // https://www.wolframalpha.com/input/?i=derivative+of+productlog(0,+x)
  //  d/dx(W_0(x)) = W(x)/(x W(x) + x)
  // https://www.wolframalpha.com/input/?i=derivative+of+productlog(-1,+x)
  // d/dx(W_(-1)(x)) = (W_(-1)(x))/(x W_(-1)(x) + x)

  // 55 decimal digit values added to allow future testing using multiprecision.

  typedef double RealType;

  int epsilons = 1;
  RealType tolerance = boost::math::tools::epsilon<RealType>() * epsilons; // 2 eps as a fraction.

  // derivative of productlog(-1, x)   at x = -0.1 == -13.8803
  // (derivative of productlog(-1, x) ) at x = N[-0.1, 55] - but the result disappears!
  // (derivative of N[productlog(-1, x), 55] ) at x = N[-0.1, 55]

  // W0 branch
  BOOST_CHECK_CLOSE_FRACTION(lambert_w0_prime(BOOST_MATH_TEST_VALUE(RealType, -0.2)),
   // BOOST_MATH_TEST_VALUE(RealType, 1.7491967609218355),
    BOOST_MATH_TEST_VALUE(RealType, 1.7491967609218358355273514903396335693828167746571404),
    tolerance); //                  1.7491967609218358355273514903396335693828167746571404

    BOOST_CHECK_CLOSE_FRACTION(lambert_w0_prime(BOOST_MATH_TEST_VALUE(RealType, 10.)),
    BOOST_MATH_TEST_VALUE(RealType, 0.063577133469345105142021311010780887641928338458371618),
    tolerance);

// W-1 branch
  BOOST_CHECK_CLOSE_FRACTION(lambert_wm1_prime(BOOST_MATH_TEST_VALUE(RealType, -0.1)),
    BOOST_MATH_TEST_VALUE(RealType, -13.880252213229780748699361486619519025203815492277715),
    tolerance);
  // Lambert W_prime -13.880252213229780748699361486619519025203815492277715, double -13.880252213229781

  BOOST_CHECK_CLOSE_FRACTION(lambert_wm1_prime(BOOST_MATH_TEST_VALUE(RealType, -0.2)),
    BOOST_MATH_TEST_VALUE(RealType, -8.2411940564179044961885598641955579728547896392013239),
    tolerance);
  // Lambert W_prime -8.2411940564179044961885598641955579728547896392013239, double -8.2411940564179051

  // Lambert W_prime 0.063577133469345105142021311010780887641928338458371618, double 0.063577133469345098
}; // BOOST_AUTO_TEST_CASE("Derivatives of lambert_w")