https://gcc.gnu.org/g:377f81a60ba78dde6c59bc40af46ef8ad3569693

commit r14-10873-g377f81a60ba78dde6c59bc40af46ef8ad3569693
Author: Jakub Jelinek <ja...@redhat.com>
Date:   Sat Nov 2 18:48:54 2024 +0100

    libstdc++: Fix up std::{,b}float16_t std::{ilogb,l{,l}r{ound,int}} 
[PR117406]
    
    These overloads incorrectly cast the result of the float __builtin_*
    to _Float or __gnu_cxx::__bfloat16_t.  For std::ilogb that changes
    behavior for the INT_MAX return because that isn't representable in
    either of the floating point formats, for the others it is I think
    just a very inefficient hop from int/long/long long to std::{,b}float16_t
    and back.  I mean for the round/rint cases, either the argument is small
    and then the return value should be representable in the floating point
    format too, or it is too large that the argument is already integral
    and then it should just return the argument with the round trips.
    Too large value is unspecified unlike ilogb.
    
    2024-11-02  Jakub Jelinek  <ja...@redhat.com>
    
            PR libstdc++/117406
            * include/c_global/cmath (std::ilogb(_Float16), 
std::llrint(_Float16),
            std::llround(_Float16), std::lrint(_Float16), 
std::lround(_Float16)):
            Don't cast __builtin_* return to _Float16.
            (std::ilogb(__gnu_cxx::__bfloat16_t),
            std::llrint(__gnu_cxx::__bfloat16_t),
            std::llround(__gnu_cxx::__bfloat16_t),
            std::lrint(__gnu_cxx::__bfloat16_t),
            std::lround(__gnu_cxx::__bfloat16_t)): Don't cast __builtin_* 
return to
            __gnu_cxx::__bfloat16_t.
            * testsuite/26_numerics/headers/cmath/117406.cc: New test.
    
    (cherry picked from commit 36a9e2b22596711455e702ea5a5a3f26e145321c)

Diff:
---
 libstdc++-v3/include/c_global/cmath                | 20 ++++----
 .../testsuite/26_numerics/headers/cmath/117406.cc  | 59 ++++++++++++++++++++++
 2 files changed, 69 insertions(+), 10 deletions(-)

diff --git a/libstdc++-v3/include/c_global/cmath 
b/libstdc++-v3/include/c_global/cmath
index c5ebebd6b861..114b0693151e 100644
--- a/libstdc++-v3/include/c_global/cmath
+++ b/libstdc++-v3/include/c_global/cmath
@@ -2831,7 +2831,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
   constexpr int
   ilogb(_Float16 __x)
-  { return _Float16(__builtin_ilogbf(__x)); }
+  { return __builtin_ilogbf(__x); }
 
   constexpr _Float16
   lgamma(_Float16 __x)
@@ -2839,11 +2839,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
   constexpr long long
   llrint(_Float16 __x)
-  { return _Float16(__builtin_llrintf(__x)); }
+  { return __builtin_llrintf(__x); }
 
   constexpr long long
   llround(_Float16 __x)
-  { return _Float16(__builtin_llroundf(__x)); }
+  { return __builtin_llroundf(__x); }
 
   constexpr _Float16
   log1p(_Float16 __x)
@@ -2860,11 +2860,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
   constexpr long
   lrint(_Float16 __x)
-  { return _Float16(__builtin_lrintf(__x)); }
+  { return __builtin_lrintf(__x); }
 
   constexpr long
   lround(_Float16 __x)
-  { return _Float16(__builtin_lroundf(__x)); }
+  { return __builtin_lroundf(__x); }
 
   constexpr _Float16
   nearbyint(_Float16 __x)
@@ -3553,7 +3553,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
   constexpr int
   ilogb(__gnu_cxx::__bfloat16_t __x)
-  { return __gnu_cxx::__bfloat16_t(__builtin_ilogbf(__x)); }
+  { return __builtin_ilogbf(__x); }
 
   constexpr __gnu_cxx::__bfloat16_t
   lgamma(__gnu_cxx::__bfloat16_t __x)
@@ -3561,11 +3561,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
   constexpr long long
   llrint(__gnu_cxx::__bfloat16_t __x)
-  { return __gnu_cxx::__bfloat16_t(__builtin_llrintf(__x)); }
+  { return __builtin_llrintf(__x); }
 
   constexpr long long
   llround(__gnu_cxx::__bfloat16_t __x)
-  { return __gnu_cxx::__bfloat16_t(__builtin_llroundf(__x)); }
+  { return __builtin_llroundf(__x); }
 
   constexpr __gnu_cxx::__bfloat16_t
   log1p(__gnu_cxx::__bfloat16_t __x)
@@ -3582,11 +3582,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
   constexpr long
   lrint(__gnu_cxx::__bfloat16_t __x)
-  { return __gnu_cxx::__bfloat16_t(__builtin_lrintf(__x)); }
+  { return __builtin_lrintf(__x); }
 
   constexpr long
   lround(__gnu_cxx::__bfloat16_t __x)
-  { return __gnu_cxx::__bfloat16_t(__builtin_lroundf(__x)); }
+  { return __builtin_lroundf(__x); }
 
   constexpr __gnu_cxx::__bfloat16_t
   nearbyint(__gnu_cxx::__bfloat16_t __x)
diff --git a/libstdc++-v3/testsuite/26_numerics/headers/cmath/117406.cc 
b/libstdc++-v3/testsuite/26_numerics/headers/cmath/117406.cc
new file mode 100644
index 000000000000..8966c71ecdcb
--- /dev/null
+++ b/libstdc++-v3/testsuite/26_numerics/headers/cmath/117406.cc
@@ -0,0 +1,59 @@
+// Copyright (C) 2024 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-do run { target c++23 } }
+// { dg-require-cmath "" }
+
+#include <stdfloat>
+#include <cmath>
+#include <limits>
+#include <testsuite_hooks.h>
+
+template <typename T>
+void
+test ()
+{
+  using lim = std::numeric_limits<T>;
+  int t0 = std::ilogb(T(4.0));
+  VERIFY( t0 == 2 );
+  int t1 = std::ilogb(lim::infinity());
+  VERIFY( t1 == INT_MAX );
+  int t2 = std::ilogb(-lim::infinity());
+  VERIFY( t2 == INT_MAX );
+}
+
+int
+main ()
+{
+#if defined(__STDCPP_FLOAT16_T__) && defined(_GLIBCXX_FLOAT_IS_IEEE_BINARY32)
+  test <std::float16_t>();
+#endif
+#if defined(__STDCPP_FLOAT32_T__) && defined(_GLIBCXX_FLOAT_IS_IEEE_BINARY32)
+  test <std::float32_t>();
+#endif
+#if defined(__STDCPP_FLOAT64_T__) && defined(_GLIBCXX_DOUBLE_IS_IEEE_BINARY64)
+  test <std::float64_t>();
+#endif
+#if defined(__STDCPP_FLOAT128_T__) \
+    && (defined(_GLIBCXX_LDOUBLE_IS_IEEE_BINARY128) \
+       || defined(_GLIBCXX_HAVE_FLOAT128_MATH))
+  test <std::float128_t>();
+#endif
+#if defined(__STDCPP_BFLOAT16_T__) && defined(_GLIBCXX_FLOAT_IS_IEEE_BINARY32)
+  test <std::bfloat16_t>();
+#endif
+}

Reply via email to