2
0
mirror of https://github.com/boostorg/math.git synced 2026-01-19 04:22:09 +00:00

Updated hypot with simpler formula.

Added sinh and cosh to ntl.hpp.
Fixed FreeBSD test failures (no real long long support).


[SVN r3598]
This commit is contained in:
John Maddock
2007-01-04 16:20:49 +00:00
parent 2e94601868
commit 27f5e4d59e
16 changed files with 73 additions and 51 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 283 B

After

Width:  |  Height:  |  Size: 426 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 415 B

After

Width:  |  Height:  |  Size: 532 B

View File

@@ -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]

View File

@@ -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<T>()) / 2;
T safe_lower = sqrt(tools::min_value<T>());
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<T>() /a < b)
return tools::overflow_error<T>(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<T>() >= y)
return x;
T rat = y / x;
return x * sqrt(1 + rat*rat);
} // template <class T> T hypot(T x, T y)

View File

@@ -325,6 +325,16 @@ namespace NTL{
boost::math::tools::digits<NTL::RR>());
}
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

View File

@@ -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 << "<note>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.</note>" << std::cout;
#endif
return 0;
} // int test_main(int, char* [])

View File

@@ -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 << "<note>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.</note>" << std::cout;
#endif
return 0;
}

View File

@@ -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 << "<note>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.</note>" << std::cout;
#endif
return 0;
}

View File

@@ -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 << "<note>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.</note>" << std::cout;
#endif
return 0;
}

View File

@@ -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 << "<note>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.</note>" << std::cout;
#endif
return 0;
}

View File

@@ -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:
//

View File

@@ -66,6 +66,7 @@ void expected_results()
if((std::numeric_limits<long double>::digits <= 64)
&& (std::numeric_limits<long double>::digits != std::numeric_limits<double>::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

View File

@@ -64,6 +64,7 @@ void expected_results()
if((std::numeric_limits<long double>::digits <= 64)
&& (std::numeric_limits<long double>::digits != std::numeric_limits<double>::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

View File

@@ -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 << "<note>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.</note>" << std::cout;
#endif
return 0;
} // int test_main(int, char* [])

View File

@@ -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<long double>::digits <= 64) &&
(std::numeric_limits<long double>::digits != std::numeric_limits<double>::digits))
{
@@ -68,6 +69,7 @@ void expected_results()
".*", // test data group
".*", 10, 5); // test function
}
#endif
//
// Catch all cases come last:
//

View File

@@ -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