+2019-07-26 Jonathan Wakely <jwakely@redhat.com>
+
+ Backport from mainline
+ 2019-06-25 Jonathan Wakely <jwakely@redhat.com>
+
+ * include/std/numeric (midpoint(T, T)): Avoid std::abs in constexpr
+ function.
+
+ Backport from mainline
+ 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.
+
2019-07-03 Jonathan Wakely <jwakely@redhat.com>
PR libstdc++/91067
* @defgroup numerics Numerics
*
* Components for performing numeric operations. Includes support for
- * for complex number types, random number generation, numeric
- * (n-at-a-time) arrays, generalized numeric algorithms, and special
- * math functions.
+ * complex number types, random number generation, numeric (n-at-a-time)
+ * arrays, generalized numeric algorithms, and mathematical special functions.
*/
#if __cplusplus >= 201402L
#endif // C++17
+_GLIBCXX_END_NAMESPACE_VERSION
+} // namespace std
+
+#endif // C++14
+
#if __cplusplus > 201703L
+#include <limits>
+
+namespace std _GLIBCXX_VISIBILITY(default)
+{
+_GLIBCXX_BEGIN_NAMESPACE_VERSION
// midpoint
# define __cpp_lib_interpolate 201902L
-template<typename _Tp>
+ template<typename _Tp>
constexpr
enable_if_t<__and_v<is_arithmetic<_Tp>, is_same<remove_cv_t<_Tp>, _Tp>,
__not_<is_same<_Tp, bool>>>,
}
return __a + __k * _Tp(_Up(__M - __m) / 2);
}
- else
+ else // is_floating
{
- return __builtin_isnormal(__a) && __builtin_isnormal(__b)
- ? __a / 2 + __b / 2
- : (__a + __b) / 2;
+ constexpr _Tp __lo = numeric_limits<_Tp>::min() * 2;
+ constexpr _Tp __hi = numeric_limits<_Tp>::max() / 2;
+ const _Tp __abs_a = __a < 0 ? -__a : __a;
+ const _Tp __abs_b = __b < 0 ? -__b : __b;
+ if (__abs_a <= __hi && __abs_b <= __hi) [[likely]]
+ return (__a + __b) / 2; // always correctly rounded
+ if (__abs_a < __lo) // not safe to halve __a
+ return __a + __b/2;
+ if (__abs_b < __lo) // not safe to halve __b
+ return __a/2 + __b;
+ return __a/2 + __b/2; // otherwise correctly rounded
}
}
{
return __a + (__b - __a) / 2;
}
-#endif // C++20
-
_GLIBCXX_END_NAMESPACE_VERSION
} // namespace std
-#endif // C++14
+#endif // C++20
#if __cplusplus > 201402L
// Parallel STL algorithms
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 *-*-* } 135 }
-// { dg-error "not bools" "" { target *-*-* } 136 }
-// { dg-error "not bools" "" { target *-*-* } 138 }
+// { dg-error "not bools" "" { target *-*-* } 135 }
+// { dg-error "not bools" "" { target *-*-* } 137 }
// { dg-prune-output "deleted function" }
// { dg-prune-output "invalid operands" }
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 *-*-* } 149 }
-// { dg-error "not bools" "" { target *-*-* } 150 }
-// { dg-error "not bools" "" { target *-*-* } 152 }
+// { dg-error "not bools" "" { target *-*-* } 149 }
+// { dg-error "not bools" "" { target *-*-* } 151 }
// { dg-prune-output "deleted function" }
// { dg-prune-output "invalid operands" }
#include <numeric>
#include <limits>
+#include <cfloat>
#include <testsuite_hooks.h>
void
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_DENORM_MIN__;
+ static_assert( std::midpoint(d, d) == d );
+
+ constexpr float f = FLT_MIN + __FLT_DENORM_MIN__;
+ static_assert( std::midpoint(f, f) == f );
+
+ constexpr long double l = LDBL_MIN + __LDBL_DENORM_MIN__;
+ static_assert( std::midpoint(l, l) == l );
+}
+
int main()
{
test01();