2
0
mirror of https://github.com/boostorg/math.git synced 2026-01-30 20:12:09 +00:00
Files
math/test/test_lambert_w.cpp
2017-08-10 17:49:17 +01:00

497 lines
22 KiB
C++

// Copyright Paul A. Bristow 2016, 2017.
// 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_lambertw.cpp
//! \brief Basic sanity tests for Lambert W function plog or lambert_w using algorithm from Thomas Luu.
#include <boost/math/concepts/real_concept.hpp> // for real_concept
#define BOOST_TEST_MAIN
#define BOOST_LIB_DIAGNOSTIC
#include <boost/test/unit_test.hpp> // Boost.Test
#include <boost/test/floating_point_comparison.hpp>
#include "test_value.hpp" // for create_test_value
#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>
#ifdef BOOST_HAS_FLOAT128
#include <boost/multiprecision/float128.hpp> // Not available for MSVC.
#endif
#include <boost/fixed_point/fixed_point.hpp>
fine BOOST_MATH_INSTRUMENT_LAMBERT_W // #define only for Lambert_w diagnostic output.
#include <boost/math/special_functions/lambert_w.hpp> // For Lambert W lambert_w function.
using boost::math::lambert_w;
#include <boost/math/special_functions/fpclassify.hpp> // isnan, ifinite.
#include <boost/array.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/type_traits/is_constructible.hpp>
#include <limits>
#include <cmath>
#include <typeinfo>
#include <iostream>
#include <type_traits>
#include <exception>
static const unsigned int noof_tests = 2;
static const boost::array<const char*, noof_tests> test_data =
{{
"1",
"6"
}}; // array test_data
//static const boost::array<const char*, noof_tests> test_expected =
//{ {
// BOOST_MATH_TEST_VALUE(T, 0.56714329040978387299996866221035554975381578718651), // Output from https://www.wolframalpha.com/input/?i=lambert_w(1)
// BOOST_MATH_TEST_VALUE(T, 1.432404775898300311234078007212058694786434608804302025655) // Output from https://www.wolframalpha.com/input/?i=lambert_w(6)
// } }; // array test_data
//! Build a message of information about build, architecture, address model, platform, ...
std::string show_versions()
{
// Some of this information can also be obtained from running with a Custom Post-build step
// adding the option --build_info=yes
// "$(TargetDir)$(TargetName).exe" --build_info=yes
std::ostringstream message;
message << "Program: " << __FILE__ << "\n";
#ifdef __TIMESTAMP__
message << __TIMESTAMP__;
#endif
message << "\nBuildInfo:\n" " Platform " << BOOST_PLATFORM;
// http://stackoverflow.com/questions/1505582/determining-32-vs-64-bit-in-c
#if defined(__LP64__) || defined(_WIN64) || (defined(__x86_64__) && !defined(__ILP32__) ) || defined(_M_X64) || defined(__ia64) || defined (_M_IA64) || defined(__aarch64__) || defined(__powerpc64__)
#define IS64BIT 1
message << ", 64-bit.";
#else
#define IS32BIT 1
message << ", 32-bit.";
#endif
message << "\n Compiler " BOOST_COMPILER;
#ifdef BOOST_MSC_VER
#ifdef _MSC_FULL_VER
message << "\n MSVC version " << BOOST_STRINGIZE(_MSC_FULL_VER) << ".";
#endif
#ifdef __WIN64
mess age << "\n WIN64" << std::endl;
#endif // __WIN64
#ifdef _WIN32
message << "\n WIN32" << std::endl;
#endif // __WIN32
#endif
#ifdef __GNUC__
//PRINT_MACRO(__GNUC__);
//PRINT_MACRO(__GNUC_MINOR__);
//PRINT_MACRO(__GNUC_PATCH__);
std::cout << "GCC " << __VERSION__ << std::endl;
//PRINT_MACRO(LONG_MAX);
#endif // __GNUC__
message << "\n STL " << BOOST_STDLIB;
message << "\n Boost version " << BOOST_VERSION / 100000 << "." << BOOST_VERSION / 100 % 1000 << "." << BOOST_VERSION % 100;
#ifdef BOOST_HAS_FLOAT128
message << ", BOOST_HAS_FLOAT128" << std::endl;
#endif
message << std::endl;
return message.str();
} // std::string versions()
template <class RealType>
void test_spots(RealType)
{
// (Unused Parameter value, arbitrarily zero, only communicates the floating point type).
// test_spots(0.F); test_spots(0.); test_spots(0.L);
using boost::math::lambert_w;
using boost::math::constants::exp_minus_one;
using boost::math::policies::policy;
typedef policy <
boost::math::policies::domain_error<boost::math::policies::ignore_error>,
boost::math::policies::overflow_error<boost::math::policies::ignore_error>,
boost::math::policies::underflow_error<boost::math::policies::ignore_error>,
boost::math::policies::denorm_error<boost::math::policies::ignore_error>,
boost::math::policies::pole_error<boost::math::policies::ignore_error>,
boost::math::policies::evaluation_error<boost::math::policies::ignore_error>
> ignore_all_policy;
// // Test some bad parameters to the function, with default policy and with ignore_all policy.
#ifndef BOOST_NO_EXCEPTIONS
BOOST_CHECK_THROW(boost::math::lambert_w<RealType>(-1.), std::domain_error);
BOOST_CHECK_THROW(lambert_w<RealType>(std::numeric_limits<RealType>::quiet_NaN()), std::domain_error); // Would be NaN.
BOOST_CHECK_THROW(lambert_w<RealType>(std::numeric_limits<RealType>::infinity()), std::domain_error); // Would be infinite.
BOOST_CHECK_THROW(lambert_w<RealType>(-static_cast<RealType>(0.4)), std::domain_error); // Would be complex.
#else
BOOST_MATH_CHECK_EQUAL(boost::math::lambert_w<RealType>(std::numeric_limits<RealType>::quiet_NaN(), ignore_all_policy), std::numeric_limits<RealType::quiet_NaN()); // nan
BOOST_MATH_CHECK_EQUAL(boost::math::lambert_w<RealType>(std::numeric_limits<RealType>::infinity(), ignore_all_policy), std::numeric_limits<RealType::quiet_NaN()); // infinity
#endif
std::cout << "\nTesting type " << typeid(RealType).name() << std::endl;
int epsilons = 2;
RealType tolerance = boost::math::tools::epsilon<RealType>() * epsilons; // 2 eps as a fraction.
std::cout << "Tolerance " << epsilons << " * epsilon == " << tolerance << std::endl;
std::cout << "Precision " << std::numeric_limits<RealType>::digits10 << " decimal digits." << std::endl;
// std::cout.precision(std::numeric_limits<RealType>::digits10);
std::cout.precision(std::numeric_limits <RealType>::max_digits10);
std::cout.setf(std::ios_base::showpoint); // show trailing significant zeros.
std::cout << "-exp(-1) = " << -exp_minus_one<RealType>() << std::endl;
// Test at singularity. Three tests because some failed previously - bug now gone?
//RealType test_value = BOOST_MATH_TEST_VALUE(RealType, -0.36787944117144232159552377016146086744581113103176783450783680169746149574489980335714727434591964374662732527);
RealType singular_value = -exp_minus_one<RealType>();
// -exp(-1) = -0.36787944117144232159552377016146086744581113103176783450783680169746149574489980335714727434591964374662732527
// lambert_w[-0.367879441171442321595523770161460867445811131031767834] == -1
// -0.36787945032119751
RealType minus_one_value = BOOST_MATH_TEST_VALUE(RealType, -1.);
//std::cout << "singular_value " << singular_value << ", expected Lambert W = " << minus_one_value << std::endl;
BOOST_CHECK_CLOSE_FRACTION( // Check -exp(-1) = -0.367879450 = -1
lambert_w(singular_value),
minus_one_value,
tolerance); // OK
BOOST_CHECK_CLOSE_FRACTION( // Check -exp(-1) ~= -0.367879450 == -1
lambert_w(BOOST_MATH_TEST_VALUE(RealType, -0.36787944117144232159552377016146086744581113103176783450783680169746149574489980335714727434591964374662732527)),
BOOST_MATH_TEST_VALUE(RealType, -1.),
tolerance);
BOOST_CHECK_CLOSE_FRACTION( // Check -exp(-1) ~= -0.367879450 == -1
lambert_w<RealType>(-exp_minus_one<RealType>()),
BOOST_MATH_TEST_VALUE(RealType, -1.),
tolerance);
// Tests with some spot values computed using
// https://www.wolframalpha.com/input
// For example: N[lambert_w[1], 50] outputs:
// 0.56714329040978387299996866221035554975381578718651
BOOST_CHECK_CLOSE_FRACTION(lambert_w(BOOST_MATH_TEST_VALUE(RealType, 0.1)),
BOOST_MATH_TEST_VALUE(RealType, 0.091276527160862264299895721423179568653119224051472),
// Output from https://www.wolframalpha.com/input/?i=lambert_w(0.2)
tolerance);
BOOST_CHECK_CLOSE_FRACTION(lambert_w(BOOST_MATH_TEST_VALUE(RealType, 0.2)),
BOOST_MATH_TEST_VALUE(RealType, 0.16891597349910956511647490370581839872844691351073),
// Output from https://www.wolframalpha.com/input/?i=lambert_w(0.2)
tolerance);
BOOST_CHECK_CLOSE_FRACTION(lambert_w(BOOST_MATH_TEST_VALUE(RealType, 0.5)),
BOOST_MATH_TEST_VALUE(RealType, 0.351733711249195826024909300929951065171464215517111804046),
// Output from https://www.wolframalpha.com/input/?i=lambert_w(0.5)
tolerance);
BOOST_CHECK_CLOSE_FRACTION(
lambert_w(BOOST_MATH_TEST_VALUE(RealType, 1.)),
BOOST_MATH_TEST_VALUE(RealType, 0.56714329040978387299996866221035554975381578718651),
// Output from https://www.wolframalpha.com/input/?i=lambert_w(1)
tolerance);
BOOST_CHECK_CLOSE_FRACTION(lambert_w(BOOST_MATH_TEST_VALUE(RealType, 2.)),
BOOST_MATH_TEST_VALUE(RealType, 0.852605502013725491346472414695317466898453300151403508772),
// Output from https://www.wolframalpha.com/input/?i=lambert_w(2.)
tolerance);
BOOST_CHECK_CLOSE_FRACTION(lambert_w(BOOST_MATH_TEST_VALUE(RealType, 3.)),
BOOST_MATH_TEST_VALUE(RealType, 1.049908894964039959988697070552897904589466943706341452932),
// Output from https://www.wolframalpha.com/input/?i=lambert_w(3.)
tolerance);
BOOST_CHECK_CLOSE_FRACTION(lambert_w(BOOST_MATH_TEST_VALUE(RealType, 5.)),
BOOST_MATH_TEST_VALUE(RealType, 1.326724665242200223635099297758079660128793554638047479789),
// Output from https://www.wolframalpha.com/input/?i=lambert_w(0.5)
tolerance);
BOOST_CHECK_CLOSE_FRACTION(lambert_w(BOOST_MATH_TEST_VALUE(RealType, 6.)),
BOOST_MATH_TEST_VALUE(RealType, 1.432404775898300311234078007212058694786434608804302025655),
// Output from https://www.wolframalpha.com/input/?i=lambert_w(6)
tolerance);
BOOST_CHECK_CLOSE_FRACTION(lambert_w(BOOST_MATH_TEST_VALUE(RealType, 100.)),
BOOST_MATH_TEST_VALUE(RealType, 3.3856301402900501848882443645297268674916941701578),
// Output from https://www.wolframalpha.com/input/?i=lambert_w(100)
tolerance);
// This fails for fixed_point type used for other tests because out of range?
//BOOST_CHECK_CLOSE_FRACTION(lambert_w(BOOST_MATH_TEST_VALUE(RealType, 1.0e6)),
//BOOST_MATH_TEST_VALUE(RealType, 11.383358086140052622000156781585004289033774706019),
//// Output from https://www.wolframalpha.com/input/?i=lambert_w(1e6)
//// tolerance * 1000); // fails for fixed_point type exceeds 0.00015258789063
// // 15.258789063
// // 11.383346558
// tolerance * 100000);
// So need to use some spot tests for specific types, or use a bigger fixed_point type.
// Check zero.
BOOST_CHECK_CLOSE_FRACTION(lambert_w(BOOST_MATH_TEST_VALUE(RealType, 0.0)),
BOOST_MATH_TEST_VALUE(RealType, 0.0),
tolerance);
// these fail for cpp_dec_float_50
// 'boost::multiprecision::detail::expression<boost::multiprecision::detail::negate,boost::multiprecision::number<boost::multiprecision::backends::cpp_dec_float<50,int32_t,void>,boost::multiprecision::et_on>,void,void,void>'
// : no appropriate default constructor available
// TODO ???????????
/*
if (std::numeric_limits<RealType>::is_specialized)
{ // Check +/- values near to zero.
BOOST_CHECK_CLOSE_FRACTION(lambert_w(std::numeric_limits<RealType>::epsilon()),
BOOST_MATH_TEST_VALUE(RealType, 0.0),
tolerance);
BOOST_CHECK_CLOSE_FRACTION(lambert_w(-std::numeric_limits<RealType>::epsilon()),
BOOST_MATH_TEST_VALUE(RealType, 0.0),
tolerance);
} // is_specialized
// Check infinite if possible.
if (std::numeric_limits<RealType>::has_infinity)
{
BOOST_CHECK_CLOSE_FRACTION(lambert_w(+std::numeric_limits<RealType>::infinity()),
BOOST_MATH_TEST_VALUE(RealType, 0.0),
tolerance);
BOOST_CHECK_CLOSE_FRACTION(lambert_w(-std::numeric_limits<RealType>::infinity()),
BOOST_MATH_TEST_VALUE(RealType, 0.0),
tolerance);
}
// Check NaN if possible.
if (std::numeric_limits<RealType>::has_quiet_NaN)
{
BOOST_CHECK_CLOSE_FRACTION(lambert_w(+std::numeric_limits<RealType>::quiet_NaN()),
BOOST_MATH_TEST_VALUE(RealType, 0.0),
tolerance);
BOOST_CHECK_CLOSE_FRACTION(lambert_w(-std::numeric_limits<RealType>::quiet_NaN()),
BOOST_MATH_TEST_VALUE(RealType, 0.0),
tolerance);
}
*/
// Checks on input that should throw.
/* This should throw when implemented.
BOOST_CHECK_CLOSE_FRACTION(lambert_w(-0.5),
BOOST_MATH_TEST_VALUE(RealType, ),
// Output from https://www.wolframalpha.com/input/?i=lambert_w(-0.5)
tolerance);
*/
} //template <class RealType>void test_spots(RealType)
BOOST_AUTO_TEST_CASE(test_types)
{
BOOST_MATH_CONTROL_FP;
// BOOST_TEST_MESSAGE( output only appears if command line has --log_level="message"
// or call set_threshold_level function:
boost::unit_test_framework::unit_test_log.set_threshold_level(boost::unit_test_framework::log_messages);
BOOST_TEST_MESSAGE("Test Lambert W function for several types.");
BOOST_TEST_MESSAGE(show_versions()); // Full version of Boost, STL and compiler info.
// Fundamental built-in types:
test_spots(0.0F); // float
test_spots(0.0); // double
//if (sizeof(long double) > sizeof (double))
//{ // Avoid pointless re-testing if double and long double are identical (for example, MSVC).
// test_spots(0.0L); // long double
//}
// Built-in/fundamental Quad 128-bit type, if available.
#ifdef BOOST_HAS_FLOAT128
test_spots(static_cast<boost::multiprecision::float128>(0));
#endif
// Multiprecision types:
test_spots(static_cast<boost::multiprecision::cpp_dec_float_50>(0));
test_spots(static_cast<boost::multiprecision::cpp_bin_float_double_extended>(0));
test_spots(static_cast<boost::multiprecision::cpp_bin_float_quad>(0));
// Fixed-point types:
// Some fail 0.1 to 1.0 ???
//test_spots(static_cast<boost::fixed_point::negatable<15,-16> >(0));
// fixed_point::negatable<15,-16> has range 1.52587891e-05 to 32768, epsilon 3.05175781e-05
//test_spots(boost::math::concepts::real_concept(0.1)); // "real_concept" - was OK.
} // BOOST_AUTO_TEST_CASE( test_types )
BOOST_AUTO_TEST_CASE(test_range_of_values)
{
using boost::math::lambert_w;
using boost::math::constants::exp_minus_one;
BOOST_TEST_MESSAGE("Test Lambert W function type double for range of values.");
// Want to test almost largest value.
// test_value = (std::numeric_limits<RealType>::max)() / 4;
// std::cout << std::setprecision(std::numeric_limits<RealType>::max_digits10) << "Max value = " << test_value << std::endl;
// Can't use a test like this for all types because max_value depends on RealType and thus the expected result of lambert_w does too.
//BOOST_CHECK_CLOSE_FRACTION(lambert_w<RealType>(test_value),
// BOOST_MATH_TEST_VALUE(RealType, ???),
// tolerance);
// So this section just tests a single type, say IEEE 64-bit double, for a range of spot values.
typedef double RealType;
int epsilons = 2;
RealType tolerance = boost::math::tools::epsilon<RealType>() * epsilons; // 2 eps as a fraction.
std::cout << "Tolerance " << epsilons << " * epsilon == " << tolerance << std::endl;
BOOST_CHECK_CLOSE_FRACTION(lambert_w(BOOST_MATH_TEST_VALUE(RealType, 1.0e-6)),
BOOST_MATH_TEST_VALUE(RealType, 9.9999900000149999733333854165586669000967020964243e-7),
// Output from https://www.wolframalpha.com/input/ N[lambert_w[1e-6],50])
tolerance);
BOOST_CHECK_CLOSE_FRACTION(lambert_w(BOOST_MATH_TEST_VALUE(RealType, 0.0001)),
BOOST_MATH_TEST_VALUE(RealType, 0.000099990001499733385405869000452213835767629477903460),
// Output from https://www.wolframalpha.com/input/ N[lambert_w[0.001],50])
tolerance);
BOOST_CHECK_CLOSE_FRACTION(lambert_w(BOOST_MATH_TEST_VALUE(RealType, 0.001)),
BOOST_MATH_TEST_VALUE(RealType, 0.00099900149733853088995782787410778559957065467928884),
// Output from https://www.wolframalpha.com/input/ N[lambert_w[0.001],50])
tolerance);
BOOST_CHECK_CLOSE_FRACTION(lambert_w(BOOST_MATH_TEST_VALUE(RealType, 0.01)),
BOOST_MATH_TEST_VALUE(RealType, 0.0099014738435950118853363268165701079536277464949174),
// Output from https://www.wolframalpha.com/input/ N[lambert_w[0.01],50])
tolerance * 25); // <<< Needs a much bigger tolerance???
// 0.0099014738435951096 this test max_digits10
// 0.00990147384359511 digits10
// 0.0099014738435950118 wolfram
// 0.00990147384359501 wolfram digits10
// 0.0099014738435950119 N[lambert_w[0.01],17]
// 0.00990147384359501 N[lambert_w[0.01],15] which really is more different than expected.
// 0.00990728209160670 approx
// 0.00990147384359511 previous
BOOST_CHECK_CLOSE_FRACTION(lambert_w(BOOST_MATH_TEST_VALUE(RealType, 0.05)),
BOOST_MATH_TEST_VALUE(RealType, 0.047672308600129374726388900514160870747062965933891),
// Output from https://www.wolframalpha.com/input/ N[lambert_w[0.01],50])
tolerance);
BOOST_CHECK_CLOSE_FRACTION(lambert_w(BOOST_MATH_TEST_VALUE(RealType, 0.1)),
BOOST_MATH_TEST_VALUE(RealType, 0.091276527160862264299895721423179568653119224051472),
// Output from https://www.wolframalpha.com/input/ N[lambert_w[1],50])
tolerance);
BOOST_CHECK_CLOSE_FRACTION(lambert_w(BOOST_MATH_TEST_VALUE(RealType, 1.)),
BOOST_MATH_TEST_VALUE(RealType, 0.56714329040978387299996866221035554975381578718651),
// Output from https://www.wolframalpha.com/input/ N[lambert_w[1],50])
tolerance);
BOOST_CHECK_CLOSE_FRACTION(lambert_w(BOOST_MATH_TEST_VALUE(RealType, 2.)),
BOOST_MATH_TEST_VALUE(RealType, 0.852605502013725491346472414695317466898453300151403508772),
// Output from https://www.wolframalpha.com/input/?i=lambert_w(2.)
tolerance);
BOOST_CHECK_CLOSE_FRACTION(lambert_w(BOOST_MATH_TEST_VALUE(RealType, 3.)),
BOOST_MATH_TEST_VALUE(RealType, 1.049908894964039959988697070552897904589466943706341452932),
// Output from https://www.wolframalpha.com/input/?i=lambert_w(3.)
tolerance);
BOOST_CHECK_CLOSE_FRACTION(lambert_w(BOOST_MATH_TEST_VALUE(RealType, 5.)),
BOOST_MATH_TEST_VALUE(RealType, 1.326724665242200223635099297758079660128793554638047479789),
// Output from https://www.wolframalpha.com/input/?i=lambert_w(0.5)
tolerance);
BOOST_CHECK_CLOSE_FRACTION(lambert_w(BOOST_MATH_TEST_VALUE(RealType, 6.)),
BOOST_MATH_TEST_VALUE(RealType, 1.432404775898300311234078007212058694786434608804302025655),
// Output from https://www.wolframalpha.com/input/?i=lambert_w(6)
tolerance);
BOOST_CHECK_CLOSE_FRACTION(lambert_w(BOOST_MATH_TEST_VALUE(RealType, 10.)),
BOOST_MATH_TEST_VALUE(RealType, 1.7455280027406993830743012648753899115352881290809),
// Output from https://www.wolframalpha.com/input/ N[lambert_w[10],50])
tolerance);
BOOST_CHECK_CLOSE_FRACTION(lambert_w(BOOST_MATH_TEST_VALUE(RealType, 100.)),
BOOST_MATH_TEST_VALUE(RealType, 3.3856301402900501848882443645297268674916941701578),
// Output from https://www.wolframalpha.com/input/?i=lambert_w(100)
tolerance);
BOOST_CHECK_CLOSE_FRACTION(lambert_w(BOOST_MATH_TEST_VALUE(RealType, 1000.)),
BOOST_MATH_TEST_VALUE(RealType, 5.2496028524015962271260563196973062825214723860596),
// Output from https://www.wolframalpha.com/input/?i=lambert_w(1000)
tolerance);
// This fails for fixed_point type used for other tests because out of range of the type?
BOOST_CHECK_CLOSE_FRACTION(lambert_w(BOOST_MATH_TEST_VALUE(RealType, 1.0e6)),
BOOST_MATH_TEST_VALUE(RealType, 11.383358086140052622000156781585004289033774706019),
// Output from https://www.wolframalpha.com/input/?i=lambert_w(1e6)
tolerance); //
// Tests for double only near the max and the singularity where Lambert_w estimates are less precise.
//
if (std::numeric_limits<RealType>::is_specialized)
{
// Check near std::numeric_limits<>::max() for type.
//std::cout << std::setprecision(std::numeric_limits<RealType>::max_digits10)
// << (std::numeric_limits<double>::max)() // == 1.7976931348623157e+308
// << " " << (std::numeric_limits<double>::max)() / 4 // == 4.4942328371557893e+307
// << std::endl;
BOOST_CHECK_CLOSE_FRACTION(boost::math::lambert_w(4.4942328371557893e+307), // max_value/4 for IEEE 64-bit double.
static_cast<double>(702.02379914670587),
// N[lambert_w[4.4942328371557893e+307], 35] == 701.84270921429200143342782556643059
// as a double == 701.83341468208209
// Lambert computed 702.02379914670587
// std::numeric_limits<double>::epsilon() * 256);
0.0003); // Much less precise near the max edge.
BOOST_CHECK_CLOSE_FRACTION(boost::math::lambert_w(4.4942328371557893e+307/2), // near max_value for IEEE 64-bit double.
static_cast<double>(701.15054872492476914094824907722937),
// N[lambert_w[4.4942328371557893e+307], 35] == 701.84270921429200143342782556643059
// as a double == 701.83341468208209
// Lambert computed 702.02379914670587
std::numeric_limits<double>::epsilon());
BOOST_CHECK_CLOSE_FRACTION(boost::math::lambert_w(4.4942328371557893e+307/4), // near max_value for IEEE 64-bit double.
static_cast<double>(700.45838920868939857588606393559517),
// N[lambert_w[4.4942328371557893e+307], 35] == 701.84270921429200143342782556643059
// as a double == 701.83341468208209
// Lambert computed 702.02379914670587
std::numeric_limits<double>::epsilon());
// This test value is one epsilon close to the singularity at -exp(1) * x
// (below which the result has a non-zero imaginary part).
RealType test_value = -exp_minus_one<RealType>();
test_value += (std::numeric_limits<RealType>::epsilon() * 1);
BOOST_CHECK_CLOSE_FRACTION(lambert_w(test_value),
BOOST_MATH_TEST_VALUE(RealType, -0.99999996349975895),
tolerance * 1000000000);
// -0.99999996788201051
// -0.99999996349975895
// Would not expect to get a result closer than sqrt(epsilon)?
} // if (std::numeric_limits<RealType>::is_specialized)
} // BOOST_AUTO_TEST_CASE( test_main )
/*
Output:
*/