Commit a3c8d7fb by Jonathan Wakely Committed by Jonathan Wakely

Fix std::midpoint for denormal values

	* include/std/numeric (midpoint(T, T)): Change implementation for
	floating-point types to avoid incorrect rounding of denormals.
	* testsuite/26_numerics/midpoint/floating.cc: Add check for correct
	rounding with denormals.
	* testsuite/26_numerics/gcd/gcd_neg.cc: Adjust dg-error line numbers.
	* testsuite/26_numerics/lcm/lcm_neg.cc: Likewise.

From-SVN: r272616
parent ff164b60
2019-06-24 Jonathan Wakely <jwakely@redhat.com> 2019-06-24 Jonathan Wakely <jwakely@redhat.com>
* include/std/numeric (midpoint(T, T)): Change implementation for
floating-point types to avoid incorrect rounding of denormals.
* testsuite/26_numerics/midpoint/floating.cc: Add check for correct
rounding with denormals.
* testsuite/26_numerics/gcd/gcd_neg.cc: Adjust dg-error line numbers.
* testsuite/26_numerics/lcm/lcm_neg.cc: Likewise.
* testsuite/18_support/headers/cfloat/values_c++17.cc: New test. * testsuite/18_support/headers/cfloat/values_c++17.cc: New test.
2019-06-20 Jonathan Wakely <jwakely@redhat.com> 2019-06-20 Jonathan Wakely <jwakely@redhat.com>
......
...@@ -69,9 +69,8 @@ ...@@ -69,9 +69,8 @@
* @defgroup numerics Numerics * @defgroup numerics Numerics
* *
* Components for performing numeric operations. Includes support for * Components for performing numeric operations. Includes support for
* for complex number types, random number generation, numeric * complex number types, random number generation, numeric (n-at-a-time)
* (n-at-a-time) arrays, generalized numeric algorithms, and special * arrays, generalized numeric algorithms, and mathematical special functions.
* math functions.
*/ */
#if __cplusplus >= 201402L #if __cplusplus >= 201402L
...@@ -156,11 +155,22 @@ namespace __detail ...@@ -156,11 +155,22 @@ namespace __detail
#endif // C++17 #endif // C++17
_GLIBCXX_END_NAMESPACE_VERSION
} // namespace std
#endif // C++14
#if __cplusplus > 201703L #if __cplusplus > 201703L
#include <limits>
#include <bits/std_abs.h>
namespace std _GLIBCXX_VISIBILITY(default)
{
_GLIBCXX_BEGIN_NAMESPACE_VERSION
// midpoint // midpoint
# define __cpp_lib_interpolate 201902L # define __cpp_lib_interpolate 201902L
template<typename _Tp> template<typename _Tp>
constexpr constexpr
enable_if_t<__and_v<is_arithmetic<_Tp>, is_same<remove_cv_t<_Tp>, _Tp>, enable_if_t<__and_v<is_arithmetic<_Tp>, is_same<remove_cv_t<_Tp>, _Tp>,
__not_<is_same<_Tp, bool>>>, __not_<is_same<_Tp, bool>>>,
...@@ -182,11 +192,17 @@ template<typename _Tp> ...@@ -182,11 +192,17 @@ template<typename _Tp>
} }
return __a + __k * _Tp(_Up(__M - __m) / 2); return __a + __k * _Tp(_Up(__M - __m) / 2);
} }
else else // is_floating
{ {
return __builtin_isnormal(__a) && __builtin_isnormal(__b) constexpr _Tp __lo = numeric_limits<_Tp>::min() * 2;
? __a / 2 + __b / 2 constexpr _Tp __hi = numeric_limits<_Tp>::max() / 2;
: (__a + __b) / 2; if (std::abs(__a) <= __hi && std::abs(__b) <= __hi) [[likely]]
return (__a + __b) / 2; // always correctly rounded
if (std::abs(__a) < __lo) // not safe to halve __a
return __a + __b/2;
if (std::abs(__b) < __lo) // not safe to halve __b
return __a/2 + __b;
return __a/2 + __b/2; // otherwise correctly rounded
} }
} }
...@@ -197,12 +213,10 @@ template<typename _Tp> ...@@ -197,12 +213,10 @@ template<typename _Tp>
{ {
return __a + (__b - __a) / 2; return __a + (__b - __a) / 2;
} }
#endif // C++20
_GLIBCXX_END_NAMESPACE_VERSION _GLIBCXX_END_NAMESPACE_VERSION
} // namespace std } // namespace std
#endif // C++14 #endif // C++20
#if __cplusplus > 201402L #if __cplusplus > 201402L
#include <bits/stl_function.h> #include <bits/stl_function.h>
......
...@@ -46,9 +46,9 @@ test01() ...@@ -46,9 +46,9 @@ test01()
std::gcd<const int&, const int&>(0.1, 0.1); // { dg-error "from here" } std::gcd<const int&, const int&>(0.1, 0.1); // { dg-error "from here" }
} }
// { dg-error "integers" "" { target *-*-* } 133 }
// { dg-error "integers" "" { target *-*-* } 134 } // { dg-error "integers" "" { target *-*-* } 134 }
// { dg-error "integers" "" { target *-*-* } 135 } // { dg-error "not bools" "" { target *-*-* } 135 }
// { dg-error "not bools" "" { target *-*-* } 136 } // { dg-error "not bools" "" { target *-*-* } 137 }
// { dg-error "not bools" "" { target *-*-* } 138 }
// { dg-prune-output "deleted function" } // { dg-prune-output "deleted function" }
// { dg-prune-output "invalid operands" } // { dg-prune-output "invalid operands" }
...@@ -46,9 +46,9 @@ test01() ...@@ -46,9 +46,9 @@ test01()
std::lcm<const int&, const int&>(0.1, 0.1); // { dg-error "from here" } std::lcm<const int&, const int&>(0.1, 0.1); // { dg-error "from here" }
} }
// { dg-error "integers" "" { target *-*-* } 147 }
// { dg-error "integers" "" { target *-*-* } 148 } // { dg-error "integers" "" { target *-*-* } 148 }
// { dg-error "integers" "" { target *-*-* } 149 } // { dg-error "not bools" "" { target *-*-* } 149 }
// { dg-error "not bools" "" { target *-*-* } 150 } // { dg-error "not bools" "" { target *-*-* } 151 }
// { dg-error "not bools" "" { target *-*-* } 152 }
// { dg-prune-output "deleted function" } // { dg-prune-output "deleted function" }
// { dg-prune-output "invalid operands" } // { dg-prune-output "invalid operands" }
...@@ -20,6 +20,7 @@ ...@@ -20,6 +20,7 @@
#include <numeric> #include <numeric>
#include <limits> #include <limits>
#include <cfloat>
#include <testsuite_hooks.h> #include <testsuite_hooks.h>
void void
...@@ -57,6 +58,19 @@ test03() ...@@ -57,6 +58,19 @@ test03()
VERIFY( std::midpoint(9e9l, -9e9l) == 0.0l ); VERIFY( std::midpoint(9e9l, -9e9l) == 0.0l );
} }
namespace test04
{
// https://gcc.gnu.org/ml/libstdc++/2019-03/msg00065.html
constexpr double d = DBL_MIN + DBL_TRUE_MIN;
static_assert( std::midpoint(d, d) == d );
constexpr float f = FLT_MIN + FLT_TRUE_MIN;
static_assert( std::midpoint(f, f) == f );
constexpr long double l = LDBL_MIN + LDBL_TRUE_MIN;
static_assert( std::midpoint(l, l) == l );
}
int main() int main()
{ {
test01(); test01();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment