File: test_lambert_w_derivative.cpp

package info (click to toggle)
scipy 1.16.0-1exp7
  • links: PTS, VCS
  • area: main
  • in suites: experimental
  • size: 234,820 kB
  • sloc: cpp: 503,145; python: 344,611; ansic: 195,638; javascript: 89,566; fortran: 56,210; cs: 3,081; f90: 1,150; sh: 848; makefile: 785; pascal: 284; csh: 135; lisp: 134; xml: 56; perl: 51
file content (134 lines) | stat: -rw-r--r-- 5,415 bytes parent folder | download | duplicates (11)
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
125
126
127
128
129
130
131
132
133
134
// 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.

#include <climits>
#include <cfloat>
#if defined(BOOST_MATH_TEST_FLOAT128) && (LDBL_MANT_DIG > 100)
//
// Mixing __float128 and long double results in:
// error: __float128 and long double cannot be used in the same expression
// whenever long double is a [possibly quasi-] quad precision type.
// 
#undef BOOST_MATH_TEST_FLOAT128
#endif

#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/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")