summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2023-05-17 21:21:23 +0200
committerJakub Jelinek <jakub@redhat.com>2023-05-17 21:21:23 +0200
commit883f1e25dc7907c9bb37f480b900336a050218f1 (patch)
tree14939b4ffaed5874697a71fc26d7ecba22b339f6
parent5e1e16d58ec10393eb8aa805e398f30144afbee6 (diff)
downloadgcc-883f1e25dc7907c9bb37f480b900336a050218f1.tar.gz
libstdc++: Fix up some <cmath> templates [PR109883]
As can be seen on the following testcase, for std::{atan2,fmod,pow,copysign,fdim,fmax,fmin,hypot,nextafter,remainder,remquo,fma} if one operand type is std::float{16,32,64,128}_t or std::bfloat16_t and another one some integral type or some other floating point type which promotes to the other operand's type, we can end up with endless recursion. This is because of a declaration ordering problem in <cmath>, where the float, double and long double overloads of those functions come before the templates which use __gnu_cxx::__promote_{2,3}, but the std::float{16,32,64,128}_t and std::bfloat16_t overloads come later in the file. If the result of those promotions is _Float{16,32,64,128} or __gnu_cxx::__bfloat16_t, say std::pow(_Float64, int) calls std::pow(_Float64, _Float64) and the latter calls itself. The following patch fixes that by moving those templates later in the file, so that the calls from those templates see also the other overloads. I think other templates in the file like e.g. isgreater etc. shouldn't be a problem, because those just use __builtin_isgreater etc. in their bodies. 2023-05-17 Jakub Jelinek <jakub@redhat.com> PR libstdc++/109883 * include/c_global/cmath (atan2, fmod, pow): Move __gnu_cxx::__promote_2 using templates after _Float{16,32,64,128} and __gnu_cxx::__bfloat16_t overloads. (copysign, fdim, fmax, fmin, hypot, nextafter, remainder, remquo): Likewise. (fma): Move __gnu_cxx::__promote_3 using template after _Float{16,32,64,128} and __gnu_cxx::__bfloat16_t overloads. * testsuite/26_numerics/headers/cmath/constexpr_std_c++23.cc: New test.
-rw-r--r--libstdc++-v3/include/c_global/cmath217
-rw-r--r--libstdc++-v3/testsuite/26_numerics/headers/cmath/constexpr_std_c++23.cc129
2 files changed, 229 insertions, 117 deletions
diff --git a/libstdc++-v3/include/c_global/cmath b/libstdc++-v3/include/c_global/cmath
index 568eb354c2d..4dc029e4e26 100644
--- a/libstdc++-v3/include/c_global/cmath
+++ b/libstdc++-v3/include/c_global/cmath
@@ -151,15 +151,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
{ return __builtin_atan2l(__y, __x); }
#endif
- template<typename _Tp, typename _Up>
- inline _GLIBCXX_CONSTEXPR
- typename __gnu_cxx::__promote_2<_Tp, _Up>::__type
- atan2(_Tp __y, _Up __x)
- {
- typedef typename __gnu_cxx::__promote_2<_Tp, _Up>::__type __type;
- return atan2(__type(__y), __type(__x));
- }
-
using ::ceil;
#ifndef __CORRECT_ISO_CPP_MATH_H_PROTO
@@ -286,15 +277,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
{ return __builtin_fmodl(__x, __y); }
#endif
- template<typename _Tp, typename _Up>
- inline _GLIBCXX_CONSTEXPR
- typename __gnu_cxx::__promote_2<_Tp, _Up>::__type
- fmod(_Tp __x, _Up __y)
- {
- typedef typename __gnu_cxx::__promote_2<_Tp, _Up>::__type __type;
- return fmod(__type(__x), __type(__y));
- }
-
using ::frexp;
#ifndef __CORRECT_ISO_CPP_MATH_H_PROTO
@@ -411,15 +393,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
#endif
#endif
- template<typename _Tp, typename _Up>
- inline _GLIBCXX_CONSTEXPR
- typename __gnu_cxx::__promote_2<_Tp, _Up>::__type
- pow(_Tp __x, _Up __y)
- {
- typedef typename __gnu_cxx::__promote_2<_Tp, _Up>::__type __type;
- return pow(__type(__x), __type(__y));
- }
-
using ::sin;
#ifndef __CORRECT_ISO_CPP_MATH_H_PROTO
@@ -1073,6 +1046,33 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
{ return __gnu_cxx::__bfloat16_t(__builtin_tanhf(__x)); }
#endif
+ template<typename _Tp, typename _Up>
+ inline _GLIBCXX_CONSTEXPR
+ typename __gnu_cxx::__promote_2<_Tp, _Up>::__type
+ atan2(_Tp __y, _Up __x)
+ {
+ typedef typename __gnu_cxx::__promote_2<_Tp, _Up>::__type __type;
+ return atan2(__type(__y), __type(__x));
+ }
+
+ template<typename _Tp, typename _Up>
+ inline _GLIBCXX_CONSTEXPR
+ typename __gnu_cxx::__promote_2<_Tp, _Up>::__type
+ fmod(_Tp __x, _Up __y)
+ {
+ typedef typename __gnu_cxx::__promote_2<_Tp, _Up>::__type __type;
+ return fmod(__type(__x), __type(__y));
+ }
+
+ template<typename _Tp, typename _Up>
+ inline _GLIBCXX_CONSTEXPR
+ typename __gnu_cxx::__promote_2<_Tp, _Up>::__type
+ pow(_Tp __x, _Up __y)
+ {
+ typedef typename __gnu_cxx::__promote_2<_Tp, _Up>::__type __type;
+ return pow(__type(__x), __type(__y));
+ }
+
#if _GLIBCXX_USE_C99_MATH
#if !_GLIBCXX_USE_C99_FP_MACROS_DYNAMIC
@@ -2107,16 +2107,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
{ return __builtin_copysignl(__x, __y); }
#endif
-#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_INT
- template<typename _Tp, typename _Up>
- constexpr typename __gnu_cxx::__promote_2<_Tp, _Up>::__type
- copysign(_Tp __x, _Up __y)
- {
- typedef typename __gnu_cxx::__promote_2<_Tp, _Up>::__type __type;
- return copysign(__type(__x), __type(__y));
- }
-#endif
-
#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_FP
constexpr float
erf(float __x)
@@ -2199,16 +2189,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
{ return __builtin_fdiml(__x, __y); }
#endif
-#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_INT
- template<typename _Tp, typename _Up>
- constexpr typename __gnu_cxx::__promote_2<_Tp, _Up>::__type
- fdim(_Tp __x, _Up __y)
- {
- typedef typename __gnu_cxx::__promote_2<_Tp, _Up>::__type __type;
- return fdim(__type(__x), __type(__y));
- }
-#endif
-
#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_FP
constexpr float
fma(float __x, float __y, float __z)
@@ -2219,16 +2199,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
{ return __builtin_fmal(__x, __y, __z); }
#endif
-#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_INT
- template<typename _Tp, typename _Up, typename _Vp>
- constexpr typename __gnu_cxx::__promote_3<_Tp, _Up, _Vp>::__type
- fma(_Tp __x, _Up __y, _Vp __z)
- {
- typedef typename __gnu_cxx::__promote_3<_Tp, _Up, _Vp>::__type __type;
- return fma(__type(__x), __type(__y), __type(__z));
- }
-#endif
-
#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_FP
constexpr float
fmax(float __x, float __y)
@@ -2239,16 +2209,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
{ return __builtin_fmaxl(__x, __y); }
#endif
-#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_INT
- template<typename _Tp, typename _Up>
- constexpr typename __gnu_cxx::__promote_2<_Tp, _Up>::__type
- fmax(_Tp __x, _Up __y)
- {
- typedef typename __gnu_cxx::__promote_2<_Tp, _Up>::__type __type;
- return fmax(__type(__x), __type(__y));
- }
-#endif
-
#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_FP
constexpr float
fmin(float __x, float __y)
@@ -2259,16 +2219,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
{ return __builtin_fminl(__x, __y); }
#endif
-#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_INT
- template<typename _Tp, typename _Up>
- constexpr typename __gnu_cxx::__promote_2<_Tp, _Up>::__type
- fmin(_Tp __x, _Up __y)
- {
- typedef typename __gnu_cxx::__promote_2<_Tp, _Up>::__type __type;
- return fmin(__type(__x), __type(__y));
- }
-#endif
-
#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_FP
constexpr float
hypot(float __x, float __y)
@@ -2279,16 +2229,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
{ return __builtin_hypotl(__x, __y); }
#endif
-#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_INT
- template<typename _Tp, typename _Up>
- constexpr typename __gnu_cxx::__promote_2<_Tp, _Up>::__type
- hypot(_Tp __x, _Up __y)
- {
- typedef typename __gnu_cxx::__promote_2<_Tp, _Up>::__type __type;
- return hypot(__type(__x), __type(__y));
- }
-#endif
-
#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_FP
constexpr int
ilogb(float __x)
@@ -2481,16 +2421,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
{ return __builtin_nextafterl(__x, __y); }
#endif
-#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_INT
- template<typename _Tp, typename _Up>
- constexpr typename __gnu_cxx::__promote_2<_Tp, _Up>::__type
- nextafter(_Tp __x, _Up __y)
- {
- typedef typename __gnu_cxx::__promote_2<_Tp, _Up>::__type __type;
- return nextafter(__type(__x), __type(__y));
- }
-#endif
-
#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_FP
constexpr float
nexttoward(float __x, long double __y)
@@ -2519,16 +2449,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
{ return __builtin_remainderl(__x, __y); }
#endif
-#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_INT
- template<typename _Tp, typename _Up>
- constexpr typename __gnu_cxx::__promote_2<_Tp, _Up>::__type
- remainder(_Tp __x, _Up __y)
- {
- typedef typename __gnu_cxx::__promote_2<_Tp, _Up>::__type __type;
- return remainder(__type(__x), __type(__y));
- }
-#endif
-
#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_FP
inline float
remquo(float __x, float __y, int* __pquo)
@@ -2539,16 +2459,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
{ return __builtin_remquol(__x, __y, __pquo); }
#endif
-#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_INT
- template<typename _Tp, typename _Up>
- inline typename __gnu_cxx::__promote_2<_Tp, _Up>::__type
- remquo(_Tp __x, _Up __y, int* __pquo)
- {
- typedef typename __gnu_cxx::__promote_2<_Tp, _Up>::__type __type;
- return remquo(__type(__x), __type(__y), __pquo);
- }
-#endif
-
#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_FP
constexpr float
rint(float __x)
@@ -3555,6 +3465,79 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
{ return __gnu_cxx::__bfloat16_t(__builtin_truncf(__x)); }
#endif
+#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_INT
+ template<typename _Tp, typename _Up>
+ constexpr typename __gnu_cxx::__promote_2<_Tp, _Up>::__type
+ copysign(_Tp __x, _Up __y)
+ {
+ typedef typename __gnu_cxx::__promote_2<_Tp, _Up>::__type __type;
+ return copysign(__type(__x), __type(__y));
+ }
+
+ template<typename _Tp, typename _Up>
+ constexpr typename __gnu_cxx::__promote_2<_Tp, _Up>::__type
+ fdim(_Tp __x, _Up __y)
+ {
+ typedef typename __gnu_cxx::__promote_2<_Tp, _Up>::__type __type;
+ return fdim(__type(__x), __type(__y));
+ }
+
+ template<typename _Tp, typename _Up>
+ constexpr typename __gnu_cxx::__promote_2<_Tp, _Up>::__type
+ fmax(_Tp __x, _Up __y)
+ {
+ typedef typename __gnu_cxx::__promote_2<_Tp, _Up>::__type __type;
+ return fmax(__type(__x), __type(__y));
+ }
+
+ template<typename _Tp, typename _Up>
+ constexpr typename __gnu_cxx::__promote_2<_Tp, _Up>::__type
+ fmin(_Tp __x, _Up __y)
+ {
+ typedef typename __gnu_cxx::__promote_2<_Tp, _Up>::__type __type;
+ return fmin(__type(__x), __type(__y));
+ }
+
+ template<typename _Tp, typename _Up>
+ constexpr typename __gnu_cxx::__promote_2<_Tp, _Up>::__type
+ hypot(_Tp __x, _Up __y)
+ {
+ typedef typename __gnu_cxx::__promote_2<_Tp, _Up>::__type __type;
+ return hypot(__type(__x), __type(__y));
+ }
+
+ template<typename _Tp, typename _Up>
+ constexpr typename __gnu_cxx::__promote_2<_Tp, _Up>::__type
+ nextafter(_Tp __x, _Up __y)
+ {
+ typedef typename __gnu_cxx::__promote_2<_Tp, _Up>::__type __type;
+ return nextafter(__type(__x), __type(__y));
+ }
+
+ template<typename _Tp, typename _Up>
+ constexpr typename __gnu_cxx::__promote_2<_Tp, _Up>::__type
+ remainder(_Tp __x, _Up __y)
+ {
+ typedef typename __gnu_cxx::__promote_2<_Tp, _Up>::__type __type;
+ return remainder(__type(__x), __type(__y));
+ }
+
+ template<typename _Tp, typename _Up>
+ inline typename __gnu_cxx::__promote_2<_Tp, _Up>::__type
+ remquo(_Tp __x, _Up __y, int* __pquo)
+ {
+ typedef typename __gnu_cxx::__promote_2<_Tp, _Up>::__type __type;
+ return remquo(__type(__x), __type(__y), __pquo);
+ }
+
+ template<typename _Tp, typename _Up, typename _Vp>
+ constexpr typename __gnu_cxx::__promote_3<_Tp, _Up, _Vp>::__type
+ fma(_Tp __x, _Up __y, _Vp __z)
+ {
+ typedef typename __gnu_cxx::__promote_3<_Tp, _Up, _Vp>::__type __type;
+ return fma(__type(__x), __type(__y), __type(__z));
+ }
+#endif
#endif // _GLIBCXX_USE_C99_MATH_TR1
#endif // C++11
diff --git a/libstdc++-v3/testsuite/26_numerics/headers/cmath/constexpr_std_c++23.cc b/libstdc++-v3/testsuite/26_numerics/headers/cmath/constexpr_std_c++23.cc
new file mode 100644
index 00000000000..5800f3b6a39
--- /dev/null
+++ b/libstdc++-v3/testsuite/26_numerics/headers/cmath/constexpr_std_c++23.cc
@@ -0,0 +1,129 @@
+// Copyright (C) 2023 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library. This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++2b" }
+// { dg-do link { target c++23 } }
+
+#include <stdfloat>
+#include <cmath>
+
+template <typename T>
+void
+test_functions()
+{
+ constexpr T zero = 0;
+ constexpr T one = 1;
+ constexpr auto a = std::acos(one);
+ constexpr auto b = std::asin(zero);
+ constexpr auto c = std::atan(zero);
+ constexpr auto d = std::cos(zero);
+ constexpr auto e = std::sin(zero);
+ constexpr auto f = std::tan(zero);
+ constexpr auto g = std::acosh(one);
+ constexpr auto h = std::asinh(zero);
+ constexpr auto i = std::atanh(zero);
+ constexpr auto j = std::cosh(zero);
+ constexpr auto k = std::sinh(zero);
+ constexpr auto l = std::tanh(zero);
+ constexpr auto m = std::exp(zero);
+ constexpr auto n = std::exp2(zero);
+ constexpr auto o = std::expm1(one);
+ constexpr auto p = std::log(one);
+ constexpr auto q = std::log10(one);
+ constexpr auto r = std::log1p(zero);
+ constexpr auto s = std::log2(one);
+ constexpr auto t = std::logb(one);
+ constexpr auto u = std::cbrt(zero);
+ constexpr auto v = std::fabs(zero);
+ constexpr auto w = std::sqrt(one);
+ constexpr auto x = std::erf(zero);
+ constexpr auto y = std::erfc(zero);
+// constexpr auto z = std::lgamma(one);
+ constexpr auto A = std::tgamma(one);
+ constexpr auto B = std::ceil(zero);
+ constexpr auto C = std::floor(zero);
+// constexpr auto D = std::nearbyint(zero);
+// constexpr auto E = std::rint(zero);
+ constexpr auto F = std::round(zero);
+ constexpr auto G = std::trunc(zero);
+ constexpr auto H = std::atan2(zero, one);
+ constexpr auto I = std::hypot(one, zero);
+ constexpr auto J = std::pow(one, zero);
+ constexpr auto K = std::fmod(zero, one);
+ constexpr auto L = std::remainder(one, one);
+ constexpr auto M = std::copysign(zero, zero);
+ constexpr auto N = std::nextafter(zero, zero);
+ constexpr auto O = std::fdim(zero, zero);
+ constexpr auto P = std::fmax(zero, one);
+ constexpr auto Q = std::fmin(zero, one);
+ constexpr auto R = std::ilogb(one);
+ constexpr auto S = std::ldexp(one, 0);
+ constexpr auto U = std::scalbn(one, 1);
+ constexpr auto V = std::scalbln(one, 1);
+// constexpr auto W = std::lrint(one);
+// constexpr auto X = std::llrint(one);
+ constexpr auto Y = std::lround(one);
+ constexpr auto Z = std::llround(one);
+ constexpr auto a1 = std::fma(one, one, one);
+ constexpr auto b1 = std::atan2(zero, 1);
+ constexpr auto c1 = std::hypot(one, 0);
+ constexpr auto d1 = std::pow(one, 0);
+ constexpr auto e1 = std::fmod(zero, 1);
+ constexpr auto f1 = std::remainder(one, 1);
+ constexpr auto g1 = std::copysign(zero, 0);
+ constexpr auto h1 = std::nextafter(zero, 0);
+ constexpr auto i1 = std::fdim(zero, 0);
+ constexpr auto j1 = std::fmax(zero, 1);
+ constexpr auto k1 = std::fmin(zero, 1);
+ constexpr auto l1 = std::fma(one, one, 1);
+ constexpr auto n1 = std::atan2(0, one);
+ constexpr auto o1 = std::hypot(1, zero);
+ constexpr auto p1 = std::pow(1, zero);
+ constexpr auto q1 = std::fmod(0, one);
+ constexpr auto r1 = std::remainder(1, one);
+ constexpr auto s1 = std::copysign(0, zero);
+ constexpr auto t1 = std::nextafter(0, zero);
+ constexpr auto u1 = std::fdim(0, zero);
+ constexpr auto v1 = std::fmax(0, one);
+ constexpr auto w1 = std::fmin(0, one);
+ constexpr auto x1 = std::fma(one, 1, one);
+ constexpr auto y1 = std::fma(1, one, one);
+ constexpr auto z1 = std::fma(1, 1, one);
+ constexpr auto A1 = std::fma(1, one, 1);
+}
+
+int
+main()
+{
+#if defined(__STDCPP_FLOAT16_T__) && defined(_GLIBCXX_FLOAT_IS_IEEE_BINARY32)
+ test_functions<std::float16_t>();
+#endif
+#if defined(__STDCPP_FLOAT32_T__) && defined(_GLIBCXX_FLOAT_IS_IEEE_BINARY32)
+ test_functions<std::float32_t>();
+#endif
+#if defined(__STDCPP_FLOAT64_T__) && defined(_GLIBCXX_DOUBLE_IS_IEEE_BINARY64)
+ test_functions<std::float64_t>();
+#endif
+#if defined(__STDCPP_FLOAT128_T__) \
+ && (defined(_GLIBCXX_DOUBLE_IS_IEEE_BINARY128) \
+ || defined(_GLIBCXX_HAVE_FLOAT128_MATH))
+ test_functions<std::float128_t>();
+#endif
+#if defined(__STDCPP_BFLOAT16_T__) && defined(_GLIBCXX_FLOAT_IS_IEEE_BINARY32)
+ test_functions<std::bfloat16_t>();
+#endif
+}