diff --git a/doc/equations/hypot.png b/doc/equations/hypot.png index fa88d6b21..1f46aa80f 100644 Binary files a/doc/equations/hypot.png and b/doc/equations/hypot.png differ diff --git a/doc/equations/hypot2.png b/doc/equations/hypot2.png index 6413c966a..46bd544e2 100644 Binary files a/doc/equations/hypot2.png and b/doc/equations/hypot2.png differ diff --git a/doc/powers.qbk b/doc/powers.qbk index 252826783..ad756990a 100644 --- a/doc/powers.qbk +++ b/doc/powers.qbk @@ -193,16 +193,11 @@ overflow or underflow, even though the result is in fact perfectly representable The function is even and symmetric in x and y, so first take assume ['x,y > 0] and ['x > y] (we can permute the arguments if this is not the case). -Then if ['x > HIGH] return [$../equations/hypot2.png] for ['y > 1] or /x/ otherwise. +Then if ['x * [epsilon][space] >= y] we can simply return /x/. -Otherwise if ['y < LOW] return x if ['x > 1 || y == 0] otherwise [$../equations/hypot2.png]. +Otherwise the result is given by: -All other cases are free from overflow or underflow problems and so can be dealt -with via the usual formula [$../equations/hypot.png]. - -The constant HIGH is the square root of half the largest -representable value. The constant LOW is the square root of the -smallest representable value. +[$../equations/hypot2.png] [endsect] diff --git a/include/boost/math/special_functions/hypot.hpp b/include/boost/math/special_functions/hypot.hpp index cc7577e0e..d251e98fd 100644 --- a/include/boost/math/special_functions/hypot.hpp +++ b/include/boost/math/special_functions/hypot.hpp @@ -43,45 +43,12 @@ T hypot(T x, T y) if(y > x) (std::swap)(x, y); - // - // Figure out overflow and underflow limits, - // we could make these constants static to save - // a few cycles, but the code would then not be - // thread safe :-( - // - T safe_upper = sqrt(tools::max_value()) / 2; - T safe_lower = sqrt(tools::min_value()); - static const T one = 1; - // - // Now handle special cases: - // - if(x >= safe_upper) - { - if(y <= one) - { - // y is negligible: - return x; - } - T a = sqrt(x) * sqrt(y); - T b = sqrt(x/y + y/x); - // We may have overflow: - if(tools::max_value() /a < b) - return tools::overflow_error(BOOST_CURRENT_FUNCTION, 0); - return a * b; - } - else if(y <= safe_lower) - { - if((x >= one) || (y == 0)) - { - // y is negligible: - return x; - } - return sqrt(x) * sqrt(y) * sqrt(x/y + y/x); - } - // - // If we get here then x^2+y^2 will not overflow or underflow: - // - return sqrt(x*x + y*y); + + if(x * tools::epsilon() >= y) + return x; + + T rat = y / x; + return x * sqrt(1 + rat*rat); } // template T hypot(T x, T y) diff --git a/include/boost/math/tools/ntl.hpp b/include/boost/math/tools/ntl.hpp index d57e37072..601d26da6 100644 --- a/include/boost/math/tools/ntl.hpp +++ b/include/boost/math/tools/ntl.hpp @@ -325,6 +325,16 @@ namespace NTL{ boost::math::tools::digits()); } + inline NTL::RR sinh(NTL::RR z) + { + return (expm1(z) - expm1(-z)) / 2; + } + + inline NTL::RR cosh(NTL::RR z) + { + return (exp(z) + exp(-z)) / 2; + } + inline NTL::RR fmod(NTL::RR x, NTL::RR y) { // This is a really crummy version of fmod, we rely on lots diff --git a/test/test_binomial.cpp b/test/test_binomial.cpp index df90b5357..df577b2d1 100644 --- a/test/test_binomial.cpp +++ b/test/test_binomial.cpp @@ -640,10 +640,17 @@ int test_main(int, char* []) // (Parameter value, arbitrarily zero, only communicates the floating point type). test_spots(0.0F); // Test float. test_spots(0.0); // Test double. +#ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS test_spots(0.0L); // Test long double. #if !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x582)) test_spots(boost::math::concepts::real_concept(0.)); // Test real concept. #endif +#else + std::cout << "The long double tests have been disabled on this platform " + "either because the long double overloads of the usual math functions are " + "not available at all, or because they are too inaccurate for these tests " + "to pass." << std::cout; +#endif return 0; } // int test_main(int, char* []) diff --git a/test/test_carlson.cpp b/test/test_carlson.cpp index 056e09a7f..f35be894d 100644 --- a/test/test_carlson.cpp +++ b/test/test_carlson.cpp @@ -321,8 +321,15 @@ int test_main(int, char* []) expected_results(); test_spots(0.0F, "float"); test_spots(0.0, "double"); +#ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS test_spots(0.0L, "long double"); test_spots(boost::math::concepts::real_concept(0), "real_concept"); +#else + std::cout << "The long double tests have been disabled on this platform " + "either because the long double overloads of the usual math functions are " + "not available at all, or because they are too inaccurate for these tests " + "to pass." << std::cout; +#endif return 0; } diff --git a/test/test_ellint_1.cpp b/test/test_ellint_1.cpp index 1f62d6ccb..cc3afbcf9 100644 --- a/test/test_ellint_1.cpp +++ b/test/test_ellint_1.cpp @@ -193,8 +193,15 @@ int test_main(int, char* []) test_spots(0.0F, "float"); test_spots(0.0, "double"); +#ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS test_spots(0.0L, "long double"); test_spots(boost::math::concepts::real_concept(0), "real_concept"); +#else + std::cout << "The long double tests have been disabled on this platform " + "either because the long double overloads of the usual math functions are " + "not available at all, or because they are too inaccurate for these tests " + "to pass." << std::cout; +#endif return 0; } diff --git a/test/test_ellint_2.cpp b/test/test_ellint_2.cpp index 741cfaac3..837b7b2b4 100644 --- a/test/test_ellint_2.cpp +++ b/test/test_ellint_2.cpp @@ -182,8 +182,15 @@ int test_main(int, char* []) expected_results(); test_spots(0.0F, "float"); test_spots(0.0, "double"); +#ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS test_spots(0.0L, "long double"); test_spots(boost::math::concepts::real_concept(0), "real_concept"); +#else + std::cout << "The long double tests have been disabled on this platform " + "either because the long double overloads of the usual math functions are " + "not available at all, or because they are too inaccurate for these tests " + "to pass." << std::cout; +#endif return 0; } diff --git a/test/test_ellint_3.cpp b/test/test_ellint_3.cpp index 98eb2ef8b..67ccdf677 100644 --- a/test/test_ellint_3.cpp +++ b/test/test_ellint_3.cpp @@ -224,8 +224,15 @@ int test_main(int, char* []) expected_results(); test_spots(0.0F, "float"); test_spots(0.0, "double"); +#ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS test_spots(0.0L, "long double"); test_spots(boost::math::concepts::real_concept(0), "real_concept"); +#else + std::cout << "The long double tests have been disabled on this platform " + "either because the long double overloads of the usual math functions are " + "not available at all, or because they are too inaccurate for these tests " + "to pass." << std::cout; +#endif return 0; } diff --git a/test/test_ibeta.cpp b/test/test_ibeta.cpp index c54d0fd26..10b92eb0b 100644 --- a/test/test_ibeta.cpp +++ b/test/test_ibeta.cpp @@ -122,16 +122,18 @@ void expected_results() largest_type, // test type(s) "(?i).*large.*", // test data group ".*", 200000, 10000); // test function +#ifdef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS // - // Cygwin: + // No long doubles: // add_expected_result( "[^|]*", // compiler "[^|]*", // stdlib - "cygwin", // platform + BOOST_PLATFORM, // platform largest_type, // test type(s) "(?i).*large.*", // test data group - ".*", 10000, 500); // test function + ".*", 13000, 500); // test function +#endif // // Catch all cases come last: // diff --git a/test/test_laguerre.cpp b/test/test_laguerre.cpp index 4838a051f..4299c59e4 100644 --- a/test/test_laguerre.cpp +++ b/test/test_laguerre.cpp @@ -66,6 +66,7 @@ void expected_results() if((std::numeric_limits::digits <= 64) && (std::numeric_limits::digits != std::numeric_limits::digits)) { +#ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS add_expected_result( ".*", // compiler ".*", // stdlib @@ -73,6 +74,7 @@ void expected_results() "double", // test type(s) ".*", // test data group ".*", 10, 5); // test function +#endif } add_expected_result( ".*", // compiler diff --git a/test/test_legendre.cpp b/test/test_legendre.cpp index 48e3f533b..64115d113 100644 --- a/test/test_legendre.cpp +++ b/test/test_legendre.cpp @@ -64,6 +64,7 @@ void expected_results() if((std::numeric_limits::digits <= 64) && (std::numeric_limits::digits != std::numeric_limits::digits)) { +#ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS add_expected_result( ".*", // compiler ".*", // stdlib @@ -71,6 +72,7 @@ void expected_results() "double", // test type(s) ".*", // test data group ".*", 10, 5); // test function +#endif } add_expected_result( ".*", // compiler diff --git a/test/test_negative_binomial.cpp b/test/test_negative_binomial.cpp index 225d7e67c..8442138e3 100644 --- a/test/test_negative_binomial.cpp +++ b/test/test_negative_binomial.cpp @@ -758,10 +758,17 @@ int test_main(int, char* []) // (Parameter value, arbitrarily zero, only communicates the floating point type). test_spots(0.0F); // Test float. test_spots(0.0); // Test double. +#ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS test_spots(0.0L); // Test long double. #if !BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x582)) test_spots(boost::math::concepts::real_concept(0.)); // Test real concept. #endif +#else + std::cout << "The long double tests have been disabled on this platform " + "either because the long double overloads of the usual math functions are " + "not available at all, or because they are too inaccurate for these tests " + "to pass." << std::cout; +#endif return 0; } // int test_main(int, char* []) diff --git a/test/test_spherical_harmonic.cpp b/test/test_spherical_harmonic.cpp index baccb12b6..7f838999b 100644 --- a/test/test_spherical_harmonic.cpp +++ b/test/test_spherical_harmonic.cpp @@ -57,6 +57,7 @@ void expected_results() #else largest_type = "(long\\s+)?double"; #endif +#ifndef BOOST_MATH_NO_LONG_DOUBLE_MATH_FUNCTIONS if((std::numeric_limits::digits <= 64) && (std::numeric_limits::digits != std::numeric_limits::digits)) { @@ -68,6 +69,7 @@ void expected_results() ".*", // test data group ".*", 10, 5); // test function } +#endif // // Catch all cases come last: // diff --git a/test/test_tgamma_ratio.cpp b/test/test_tgamma_ratio.cpp index f96ac3535..0b81b896f 100644 --- a/test/test_tgamma_ratio.cpp +++ b/test/test_tgamma_ratio.cpp @@ -63,7 +63,7 @@ void expected_results() add_expected_result( "[^|]*", // compiler "[^|]*", // stdlib - "HP-UX|linux", // platform + "HP-UX|linux|.*(bsd|BSD).*", // platform "float", // test type(s) "[^|]*", // test data group "boost::math::tgamma_ratio[^|]*", 35, 8); // test function