libstdc++: Fix up some <cmath> templates [PR109883]
Checks
Commit Message
Hi!
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.
Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk/13.2?
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.
Jakub
Comments
On Wed, 17 May 2023 at 19:18, Jakub Jelinek <jakub@redhat.com> wrote:
> Hi!
>
> 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 checked that each set of moved functions is still within the same #if
group, so there's no change in the logic for whether they are defined or
not, only the point of declaration within the file.
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.
>
> Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk/13.2?
>
OK for both, thanks.
>
> 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.
>
> --- libstdc++-v3/include/c_global/cmath.jj 2023-01-16
> 23:19:06.225717615 +0100
> +++ libstdc++-v3/include/c_global/cmath 2023-05-17 15:07:07.823657320 +0200
> @@ -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
> ---
> libstdc++-v3/testsuite/26_numerics/headers/cmath/constexpr_std_c++23.cc.jj
> 2023-05-17 15:23:55.120327327 +0200
> +++
> libstdc++-v3/testsuite/26_numerics/headers/cmath/constexpr_std_c++23.cc
> 2023-05-17 16:19:27.386931508 +0200
> @@ -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
> +}
>
> Jakub
>
>
@@ -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
@@ -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
+}