[libcxx-commits] [libcxx] 866bec7 - [libc++][math] Provide overloads for cv-unqualified floating point types for `std::isnormal` (#104773)

via libcxx-commits libcxx-commits at lists.llvm.org
Wed Aug 28 01:34:50 PDT 2024


Author: Robin Caloudis
Date: 2024-08-28T10:34:47+02:00
New Revision: 866bec7d3ff8803b68e9972939c1a76ccf5fdc62

URL: https://github.com/llvm/llvm-project/commit/866bec7d3ff8803b68e9972939c1a76ccf5fdc62
DIFF: https://github.com/llvm/llvm-project/commit/866bec7d3ff8803b68e9972939c1a76ccf5fdc62.diff

LOG: [libc++][math] Provide overloads for cv-unqualified floating point types for `std::isnormal` (#104773)

## Why
Currently, the following does not work when compiled with clang:

```c++
#include <cmath>

struct ConvertibleToFloat {
    operator float();
};

bool test(ConvertibleToFloat x) {
    return std::isnormal(x);
}
```
See https://godbolt.org/z/5bos8v67T for differences with respect to
msvc, gcc or icx. It fails for `float`, `double` and `long double` (all
cv-unqualified floating-point types).

## What
Test and provide overloads as expected by the ISO C++ standard. The
classification/comparison function `isnormal` is defined since C++11
until C++23 as
```c++
bool isnormal( float num );
bool isnormal( double num );
bool isnormal( long double num );
```
and since C++23 as
```c++
constexpr bool isnormal( /* floating-point-type */ num );
```
for which "the library provides overloads for all cv-unqualified
floating-point types as the type of the parameter num". See §28.7.1/1 in
the [ISO C++
standard](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2023/n4950.pdf)
or check
[cppreference](https://en.cppreference.com/w/cpp/numeric/math/isnormal).

Added: 
    

Modified: 
    libcxx/include/__math/traits.h
    libcxx/test/std/numerics/c.math/isnormal.pass.cpp

Removed: 
    


################################################################################
diff  --git a/libcxx/include/__math/traits.h b/libcxx/include/__math/traits.h
index 35c283cc9e21ce..2ca231e0428fb9 100644
--- a/libcxx/include/__math/traits.h
+++ b/libcxx/include/__math/traits.h
@@ -127,14 +127,21 @@ _LIBCPP_NODISCARD inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI boo
 
 // isnormal
 
-template <class _A1, __enable_if_t<is_floating_point<_A1>::value, int> = 0>
+template <class _A1, __enable_if_t<is_integral<_A1>::value, int> = 0>
 _LIBCPP_NODISCARD _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool isnormal(_A1 __x) _NOEXCEPT {
+  return __x != 0;
+}
+
+_LIBCPP_NODISCARD inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool isnormal(float __x) _NOEXCEPT {
   return __builtin_isnormal(__x);
 }
 
-template <class _A1, __enable_if_t<is_integral<_A1>::value, int> = 0>
-_LIBCPP_NODISCARD _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool isnormal(_A1 __x) _NOEXCEPT {
-  return __x != 0;
+_LIBCPP_NODISCARD inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool isnormal(double __x) _NOEXCEPT {
+  return __builtin_isnormal(__x);
+}
+
+_LIBCPP_NODISCARD inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool isnormal(long double __x) _NOEXCEPT {
+  return __builtin_isnormal(__x);
 }
 
 // isgreater

diff  --git a/libcxx/test/std/numerics/c.math/isnormal.pass.cpp b/libcxx/test/std/numerics/c.math/isnormal.pass.cpp
index c3b8f31359f988..76c3d13520d996 100644
--- a/libcxx/test/std/numerics/c.math/isnormal.pass.cpp
+++ b/libcxx/test/std/numerics/c.math/isnormal.pass.cpp
@@ -62,9 +62,23 @@ struct TestInt {
   }
 };
 
+template <typename T>
+struct ConvertibleTo {
+  operator T() const { return T(1); }
+};
+
 int main(int, char**) {
   types::for_each(types::floating_point_types(), TestFloat());
   types::for_each(types::integral_types(), TestInt());
 
+  // Make sure we can call `std::isnormal` with convertible types. This checks
+  // whether overloads for all cv-unqualified floating-point types are working
+  // as expected.
+  {
+    assert(std::isnormal(ConvertibleTo<float>()));
+    assert(std::isnormal(ConvertibleTo<double>()));
+    assert(std::isnormal(ConvertibleTo<long double>()));
+  }
+
   return 0;
 }


        


More information about the libcxx-commits mailing list