[libcxx-commits] [libcxx] 52bff45 - [libc++] Implement constexpr {isfinite, isinf, isnan, isnormal}

Nikolas Klauser via libcxx-commits libcxx-commits at lists.llvm.org
Sun Dec 25 11:14:34 PST 2022


Author: Nikolas Klauser
Date: 2022-12-25T20:14:29+01:00
New Revision: 52bff450dd46c28e1b2966c13bf0d603046214a5

URL: https://github.com/llvm/llvm-project/commit/52bff450dd46c28e1b2966c13bf0d603046214a5
DIFF: https://github.com/llvm/llvm-project/commit/52bff450dd46c28e1b2966c13bf0d603046214a5.diff

LOG: [libc++] Implement constexpr {isfinite, isinf, isnan, isnormal}

This starts implementing P0533

Reviewed By: Mordante, #libc

Spies: libcxx-commits

Differential Revision: https://reviews.llvm.org/D140277

Added: 
    libcxx/test/std/numerics/c.math/isfinite.pass.cpp
    libcxx/test/std/numerics/c.math/isinf.pass.cpp
    libcxx/test/std/numerics/c.math/isnan.pass.cpp
    libcxx/test/std/numerics/c.math/isnormal.pass.cpp

Modified: 
    libcxx/docs/Status/Cxx2b.rst
    libcxx/docs/Status/Cxx2bPapers.csv
    libcxx/include/math.h
    libcxx/test/libcxx/numerics/c.math/constexpr-cxx2b-clang.pass.cpp
    libcxx/test/libcxx/numerics/c.math/constexpr-cxx2b-gcc.pass.cpp

Removed: 
    


################################################################################
diff  --git a/libcxx/docs/Status/Cxx2b.rst b/libcxx/docs/Status/Cxx2b.rst
index 15374949d5acf..41b790e8e07e8 100644
--- a/libcxx/docs/Status/Cxx2b.rst
+++ b/libcxx/docs/Status/Cxx2b.rst
@@ -40,6 +40,7 @@ Paper Status
 .. note::
 
    .. [#note-P2273] P2273: ``make_unique_for_overwrite`` isn't done yet since `P1020` hasn't been implemented yet.
+   .. [#note-P0533R9] P0533R9: ``isfinite``, ``isinf``, ``isnan`` and ``isnormal`` are implemented.
 
 .. _issues-status-cxx2b:
 

diff  --git a/libcxx/docs/Status/Cxx2bPapers.csv b/libcxx/docs/Status/Cxx2bPapers.csv
index 9af4bca8be52a..aacdf16a245ea 100644
--- a/libcxx/docs/Status/Cxx2bPapers.csv
+++ b/libcxx/docs/Status/Cxx2bPapers.csv
@@ -39,7 +39,7 @@
 "`P2401R0 <https://wg21.link/P2401R0>`__","LWG","Add a conditional ``noexcept`` specification to ``std::exchange``","October 2021","|Complete|","14.0"
 "","","","","",""
 "`P0323R12 <https://wg21.link/P0323R12>`__","LWG","``std::expected``","February 2022","|Complete|","16.0"
-"`P0533R9 <https://wg21.link/P0533R9>`__","LWG","``constexpr`` for ``<cmath>`` and ``<cstdlib>``","February 2022","",""
+"`P0533R9 <https://wg21.link/P0533R9>`__","LWG","``constexpr`` for ``<cmath>`` and ``<cstdlib>``","February 2022","|In progress| [#note-P0533R9]_",""
 "`P0627R6 <https://wg21.link/P0627R6>`__","LWG","Function to mark unreachable code","February 2022","|Complete|","15.0"
 "`P1206R7 <https://wg21.link/P1206R7>`__","LWG","``ranges::to``: A function to convert any range to a container","February 2022","","","|ranges|"
 "`P1413R3 <https://wg21.link/P1413R3>`__","LWG","Deprecate ``std::aligned_storage`` and ``std::aligned_union``","February 2022","",""

diff  --git a/libcxx/include/math.h b/libcxx/include/math.h
index dd688307b6dd0..14fa9e286ea30 100644
--- a/libcxx/include/math.h
+++ b/libcxx/include/math.h
@@ -400,13 +400,13 @@ inline _LIBCPP_HIDE_FROM_ABI int fpclassify(_A1 __x) _NOEXCEPT {
 
 template <class _A1,
           std::__enable_if_t<std::is_arithmetic<_A1>::value && std::numeric_limits<_A1>::has_infinity, int> = 0>
-inline _LIBCPP_HIDE_FROM_ABI bool isfinite(_A1 __x) _NOEXCEPT {
+_LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool isfinite(_A1 __x) _NOEXCEPT {
   return __builtin_isfinite((typename std::__promote<_A1>::type)__x);
 }
 
 template <class _A1,
           std::__enable_if_t<std::is_arithmetic<_A1>::value && !std::numeric_limits<_A1>::has_infinity, int> = 0>
-inline _LIBCPP_HIDE_FROM_ABI bool isfinite(_A1) _NOEXCEPT {
+_LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool isfinite(_A1) _NOEXCEPT {
   return true;
 }
 
@@ -414,54 +414,66 @@ inline _LIBCPP_HIDE_FROM_ABI bool isfinite(_A1) _NOEXCEPT {
 
 template <class _A1,
           std::__enable_if_t<std::is_arithmetic<_A1>::value && std::numeric_limits<_A1>::has_infinity, int> = 0>
-inline _LIBCPP_HIDE_FROM_ABI bool isinf(_A1 __x) _NOEXCEPT {
+_LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool isinf(_A1 __x) _NOEXCEPT {
   return __builtin_isinf((typename std::__promote<_A1>::type)__x);
 }
 
 template <class _A1>
-inline _LIBCPP_HIDE_FROM_ABI
+_LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI
     typename std::enable_if< std::is_arithmetic<_A1>::value && !std::numeric_limits<_A1>::has_infinity, bool>::type
     isinf(_A1) _NOEXCEPT {
   return false;
 }
 
 #      ifdef _LIBCPP_PREFERRED_OVERLOAD
-inline _LIBCPP_HIDE_FROM_ABI bool isinf(float __x) _NOEXCEPT { return __builtin_isinf(__x); }
+inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool isinf(float __x) _NOEXCEPT {
+  return __builtin_isinf(__x);
+}
 
-inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_PREFERRED_OVERLOAD bool isinf(double __x) _NOEXCEPT { return __builtin_isinf(__x); }
+inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI _LIBCPP_PREFERRED_OVERLOAD bool isinf(double __x) _NOEXCEPT {
+  return __builtin_isinf(__x);
+}
 
-inline _LIBCPP_HIDE_FROM_ABI bool isinf(long double __x) _NOEXCEPT { return __builtin_isinf(__x); }
+inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool isinf(long double __x) _NOEXCEPT {
+  return __builtin_isinf(__x);
+}
 #      endif
 
 // isnan
 
 template <class _A1, std::__enable_if_t<std::is_floating_point<_A1>::value, int> = 0>
-inline _LIBCPP_HIDE_FROM_ABI bool isnan(_A1 __x) _NOEXCEPT {
+_LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool isnan(_A1 __x) _NOEXCEPT {
   return __builtin_isnan(__x);
 }
 
 template <class _A1, std::__enable_if_t<std::is_integral<_A1>::value, int> = 0>
-inline _LIBCPP_HIDE_FROM_ABI bool isnan(_A1) _NOEXCEPT {
+_LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool isnan(_A1) _NOEXCEPT {
   return false;
 }
 
 #      ifdef _LIBCPP_PREFERRED_OVERLOAD
-inline _LIBCPP_HIDE_FROM_ABI bool isnan(float __x) _NOEXCEPT { return __builtin_isnan(__x); }
+inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool isnan(float __x) _NOEXCEPT {
+  return __builtin_isnan(__x);
+}
 
-inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_PREFERRED_OVERLOAD bool isnan(double __x) _NOEXCEPT { return __builtin_isnan(__x); }
+inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI _LIBCPP_PREFERRED_OVERLOAD bool isnan(double __x) _NOEXCEPT {
+  return __builtin_isnan(__x);
+}
 
-inline _LIBCPP_HIDE_FROM_ABI bool isnan(long double __x) _NOEXCEPT { return __builtin_isnan(__x); }
+inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool isnan(long double __x) _NOEXCEPT {
+  return __builtin_isnan(__x);
+}
 #      endif
 
 // isnormal
 
 template <class _A1, std::__enable_if_t<std::is_floating_point<_A1>::value, int> = 0>
-inline _LIBCPP_HIDE_FROM_ABI bool isnormal(_A1 __x) _NOEXCEPT {
+_LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool isnormal(_A1 __x) _NOEXCEPT {
   return __builtin_isnormal(__x);
 }
 
 template <class _A1, std::__enable_if_t<std::is_integral<_A1>::value, int> = 0>
-inline _LIBCPP_HIDE_FROM_ABI bool isnormal(_A1 __x) _NOEXCEPT {
+_LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool isnormal(_A1 __x) _NOEXCEPT {
   return __x != 0;
 }
 

diff  --git a/libcxx/test/libcxx/numerics/c.math/constexpr-cxx2b-clang.pass.cpp b/libcxx/test/libcxx/numerics/c.math/constexpr-cxx2b-clang.pass.cpp
index a64d322f3b76e..269c487de23d2 100644
--- a/libcxx/test/libcxx/numerics/c.math/constexpr-cxx2b-clang.pass.cpp
+++ b/libcxx/test/libcxx/numerics/c.math/constexpr-cxx2b-clang.pass.cpp
@@ -19,6 +19,9 @@
 // REQUIRES: clang
 // UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
 
+// We don't control the implementation of these functions on windows
+// UNSUPPORTED: windows
+
 #include <cmath>
 #include <cstdlib>
 #include <cassert>
@@ -201,21 +204,21 @@ int main(int, char**) {
   ASSERT_NOT_CONSTEXPR_CXX23(std::fpclassify(-1.0) == FP_NORMAL);
   ASSERT_NOT_CONSTEXPR_CXX23(std::fpclassify(-1.0L) == FP_NORMAL);
 
-  ASSERT_NOT_CONSTEXPR_CXX23(std::isfinite(-1.0f) == 1);
-  ASSERT_NOT_CONSTEXPR_CXX23(std::isfinite(-1.0) == 1);
-  ASSERT_NOT_CONSTEXPR_CXX23(std::isfinite(-1.0L) == 1);
+  ASSERT_CONSTEXPR_CXX23(std::isfinite(-1.0f) == 1);
+  ASSERT_CONSTEXPR_CXX23(std::isfinite(-1.0) == 1);
+  ASSERT_CONSTEXPR_CXX23(std::isfinite(-1.0L) == 1);
 
-  ASSERT_NOT_CONSTEXPR_CXX23(std::isinf(-1.0f) == 0);
-  ASSERT_NOT_CONSTEXPR_CXX23(std::isinf(-1.0) == 0);
-  ASSERT_NOT_CONSTEXPR_CXX23(std::isinf(-1.0L) == 0);
+  ASSERT_CONSTEXPR_CXX23(std::isinf(-1.0f) == 0);
+  ASSERT_CONSTEXPR_CXX23(std::isinf(-1.0) == 0);
+  ASSERT_CONSTEXPR_CXX23(std::isinf(-1.0L) == 0);
 
-  ASSERT_NOT_CONSTEXPR_CXX23(std::isnan(-1.0f) == 0);
-  ASSERT_NOT_CONSTEXPR_CXX23(std::isnan(-1.0) == 0);
-  ASSERT_NOT_CONSTEXPR_CXX23(std::isnan(-1.0L) == 0);
+  ASSERT_CONSTEXPR_CXX23(std::isnan(-1.0f) == 0);
+  ASSERT_CONSTEXPR_CXX23(std::isnan(-1.0) == 0);
+  ASSERT_CONSTEXPR_CXX23(std::isnan(-1.0L) == 0);
 
-  ASSERT_NOT_CONSTEXPR_CXX23(std::isnormal(-1.0f) == 1);
-  ASSERT_NOT_CONSTEXPR_CXX23(std::isnormal(-1.0) == 1);
-  ASSERT_NOT_CONSTEXPR_CXX23(std::isnormal(-1.0L) == 1);
+  ASSERT_CONSTEXPR_CXX23(std::isnormal(-1.0f) == 1);
+  ASSERT_CONSTEXPR_CXX23(std::isnormal(-1.0) == 1);
+  ASSERT_CONSTEXPR_CXX23(std::isnormal(-1.0L) == 1);
 
   ASSERT_NOT_CONSTEXPR_CXX23(std::signbit(-1.0f) == 1);
   ASSERT_NOT_CONSTEXPR_CXX23(std::signbit(-1.0) == 1);

diff  --git a/libcxx/test/libcxx/numerics/c.math/constexpr-cxx2b-gcc.pass.cpp b/libcxx/test/libcxx/numerics/c.math/constexpr-cxx2b-gcc.pass.cpp
index f1d9539349c33..b4ff47a0ff74d 100644
--- a/libcxx/test/libcxx/numerics/c.math/constexpr-cxx2b-gcc.pass.cpp
+++ b/libcxx/test/libcxx/numerics/c.math/constexpr-cxx2b-gcc.pass.cpp
@@ -201,21 +201,21 @@ int main(int, char**) {
   ASSERT_NOT_CONSTEXPR_CXX23(std::fpclassify(-1.0) == FP_NORMAL);
   ASSERT_NOT_CONSTEXPR_CXX23(std::fpclassify(-1.0L) == FP_NORMAL);
 
-  ASSERT_NOT_CONSTEXPR_CXX23(std::isfinite(-1.0f) == 1);
-  ASSERT_NOT_CONSTEXPR_CXX23(std::isfinite(-1.0) == 1);
-  ASSERT_NOT_CONSTEXPR_CXX23(std::isfinite(-1.0L) == 1);
+  ASSERT_CONSTEXPR_CXX23(std::isfinite(-1.0f) == 1);
+  ASSERT_CONSTEXPR_CXX23(std::isfinite(-1.0) == 1);
+  ASSERT_CONSTEXPR_CXX23(std::isfinite(-1.0L) == 1);
 
-  ASSERT_NOT_CONSTEXPR_CXX23(std::isinf(-1.0f) == 0);
-  ASSERT_NOT_CONSTEXPR_CXX23(std::isinf(-1.0) == 0);
-  ASSERT_NOT_CONSTEXPR_CXX23(std::isinf(-1.0L) == 0);
+  ASSERT_CONSTEXPR_CXX23(std::isinf(-1.0f) == 0);
+  ASSERT_CONSTEXPR_CXX23(std::isinf(-1.0) == 0);
+  ASSERT_CONSTEXPR_CXX23(std::isinf(-1.0L) == 0);
 
-  ASSERT_NOT_CONSTEXPR_CXX23(std::isnan(-1.0f) == 0);
-  ASSERT_NOT_CONSTEXPR_CXX23(std::isnan(-1.0) == 0);
-  ASSERT_NOT_CONSTEXPR_CXX23(std::isnan(-1.0L) == 0);
+  ASSERT_CONSTEXPR_CXX23(std::isnan(-1.0f) == 0);
+  ASSERT_CONSTEXPR_CXX23(std::isnan(-1.0) == 0);
+  ASSERT_CONSTEXPR_CXX23(std::isnan(-1.0L) == 0);
 
-  ASSERT_NOT_CONSTEXPR_CXX23(std::isnormal(-1.0f) == 1);
-  ASSERT_NOT_CONSTEXPR_CXX23(std::isnormal(-1.0) == 1);
-  ASSERT_NOT_CONSTEXPR_CXX23(std::isnormal(-1.0L) == 1);
+  ASSERT_CONSTEXPR_CXX23(std::isnormal(-1.0f) == 1);
+  ASSERT_CONSTEXPR_CXX23(std::isnormal(-1.0) == 1);
+  ASSERT_CONSTEXPR_CXX23(std::isnormal(-1.0L) == 1);
 
   ASSERT_NOT_CONSTEXPR_CXX23(std::signbit(-1.0f) == 1);
   ASSERT_NOT_CONSTEXPR_CXX23(std::signbit(-1.0) == 1);

diff  --git a/libcxx/test/std/numerics/c.math/isfinite.pass.cpp b/libcxx/test/std/numerics/c.math/isfinite.pass.cpp
new file mode 100644
index 0000000000000..fd2ad11523b30
--- /dev/null
+++ b/libcxx/test/std/numerics/c.math/isfinite.pass.cpp
@@ -0,0 +1,70 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// bool isfinite(floating-point-type x); // constexpr since C++23
+
+// We don't control the implementation on windows
+// UNSUPPORTED: windows
+
+#include <cassert>
+#include <cmath>
+#include <limits>
+
+#include "test_macros.h"
+#include "type_algorithms.h"
+
+struct TestFloat {
+  template <class T>
+  static TEST_CONSTEXPR_CXX23 bool test() {
+    assert(std::isfinite(std::numeric_limits<T>::max()));
+    assert(!std::isfinite(std::numeric_limits<T>::infinity()));
+    assert(std::isfinite(std::numeric_limits<T>::min()));
+    assert(std::isfinite(std::numeric_limits<T>::denorm_min()));
+    assert(std::isfinite(std::numeric_limits<T>::lowest()));
+    assert(!std::isfinite(-std::numeric_limits<T>::infinity()));
+    assert(std::isfinite(T(0)));
+    assert(!std::isfinite(std::numeric_limits<T>::quiet_NaN()));
+    assert(!std::isfinite(std::numeric_limits<T>::signaling_NaN()));
+
+    return true;
+  }
+
+  template <class T>
+  TEST_CONSTEXPR_CXX23 void operator()() {
+    test<T>();
+#if TEST_STD_VER >= 23
+    static_assert(test<T>());
+#endif
+  }
+};
+
+struct TestInt {
+  template <class T>
+  static TEST_CONSTEXPR_CXX23 bool test() {
+    assert(std::isfinite(std::numeric_limits<T>::max()));
+    assert(std::isfinite(std::numeric_limits<T>::lowest()));
+    assert(std::isfinite(T(0)));
+
+    return true;
+  }
+
+  template <class T>
+  TEST_CONSTEXPR_CXX23 void operator()() {
+    test<T>();
+#if TEST_STD_VER >= 23
+    static_assert(test<T>());
+#endif
+  }
+};
+
+int main(int, char**) {
+  meta::for_each(meta::floating_point_types(), TestFloat());
+  meta::for_each(meta::integral_types(), TestInt());
+
+  return 0;
+}

diff  --git a/libcxx/test/std/numerics/c.math/isinf.pass.cpp b/libcxx/test/std/numerics/c.math/isinf.pass.cpp
new file mode 100644
index 0000000000000..3b1e54fa08223
--- /dev/null
+++ b/libcxx/test/std/numerics/c.math/isinf.pass.cpp
@@ -0,0 +1,70 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// bool isfinite(floating-point-type x); // constexpr since C++23
+
+// We don't control the implementation on windows
+// UNSUPPORTED: windows
+
+#include <cassert>
+#include <cmath>
+#include <limits>
+
+#include "test_macros.h"
+#include "type_algorithms.h"
+
+struct TestFloat {
+  template <class T>
+  static TEST_CONSTEXPR_CXX23 bool test() {
+    assert(!std::isinf(std::numeric_limits<T>::max()));
+    assert(std::isinf(std::numeric_limits<T>::infinity()));
+    assert(!std::isinf(std::numeric_limits<T>::min()));
+    assert(!std::isinf(std::numeric_limits<T>::denorm_min()));
+    assert(!std::isinf(std::numeric_limits<T>::lowest()));
+    assert(std::isinf(-std::numeric_limits<T>::infinity()));
+    assert(!std::isinf(T(0)));
+    assert(!std::isinf(std::numeric_limits<T>::quiet_NaN()));
+    assert(!std::isinf(std::numeric_limits<T>::signaling_NaN()));
+
+    return true;
+  }
+
+  template <class T>
+  TEST_CONSTEXPR_CXX23 void operator()() {
+    test<T>();
+#if TEST_STD_VER >= 23
+    static_assert(test<T>());
+#endif
+  }
+};
+
+struct TestInt {
+  template <class T>
+  static TEST_CONSTEXPR_CXX23 bool test() {
+    assert(!std::isinf(std::numeric_limits<T>::max()));
+    assert(!std::isinf(std::numeric_limits<T>::lowest()));
+    assert(!std::isinf(T(0)));
+
+    return true;
+  }
+
+  template <class T>
+  TEST_CONSTEXPR_CXX23 void operator()() {
+    test<T>();
+#if TEST_STD_VER >= 23
+    static_assert(test<T>());
+#endif
+  }
+};
+
+int main(int, char**) {
+  meta::for_each(meta::floating_point_types(), TestFloat());
+  meta::for_each(meta::integral_types(), TestInt());
+
+  return 0;
+}

diff  --git a/libcxx/test/std/numerics/c.math/isnan.pass.cpp b/libcxx/test/std/numerics/c.math/isnan.pass.cpp
new file mode 100644
index 0000000000000..c8ac0551c997e
--- /dev/null
+++ b/libcxx/test/std/numerics/c.math/isnan.pass.cpp
@@ -0,0 +1,70 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// bool isfinite(floating-point-type x); // constexpr since C++23
+
+// We don't control the implementation on windows
+// UNSUPPORTED: windows
+
+#include <cassert>
+#include <cmath>
+#include <limits>
+
+#include "test_macros.h"
+#include "type_algorithms.h"
+
+struct TestFloat {
+  template <class T>
+  static TEST_CONSTEXPR_CXX23 bool test() {
+    assert(!std::isnan(std::numeric_limits<T>::max()));
+    assert(!std::isnan(std::numeric_limits<T>::infinity()));
+    assert(!std::isnan(std::numeric_limits<T>::min()));
+    assert(!std::isnan(std::numeric_limits<T>::denorm_min()));
+    assert(!std::isnan(std::numeric_limits<T>::lowest()));
+    assert(!std::isnan(-std::numeric_limits<T>::infinity()));
+    assert(!std::isnan(T(0)));
+    assert(std::isnan(std::numeric_limits<T>::quiet_NaN()));
+    assert(std::isnan(std::numeric_limits<T>::signaling_NaN()));
+
+    return true;
+  }
+
+  template <class T>
+  TEST_CONSTEXPR_CXX23 void operator()() {
+    test<T>();
+#if TEST_STD_VER >= 23
+    static_assert(test<T>());
+#endif
+  }
+};
+
+struct TestInt {
+  template <class T>
+  static TEST_CONSTEXPR_CXX23 bool test() {
+    assert(!std::isnan(std::numeric_limits<T>::max()));
+    assert(!std::isnan(std::numeric_limits<T>::lowest()));
+    assert(!std::isnan(T(0)));
+
+    return true;
+  }
+
+  template <class T>
+  TEST_CONSTEXPR_CXX23 void operator()() {
+    test<T>();
+#if TEST_STD_VER >= 23
+    static_assert(test<T>());
+#endif
+  }
+};
+
+int main(int, char**) {
+  meta::for_each(meta::floating_point_types(), TestFloat());
+  meta::for_each(meta::integral_types(), TestInt());
+
+  return 0;
+}

diff  --git a/libcxx/test/std/numerics/c.math/isnormal.pass.cpp b/libcxx/test/std/numerics/c.math/isnormal.pass.cpp
new file mode 100644
index 0000000000000..681438efe2281
--- /dev/null
+++ b/libcxx/test/std/numerics/c.math/isnormal.pass.cpp
@@ -0,0 +1,70 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// bool isfinite(floating-point-type x); // constexpr since C++23
+
+// We don't control the implementation on windows
+// UNSUPPORTED: windows
+
+#include <cassert>
+#include <cmath>
+#include <limits>
+
+#include "test_macros.h"
+#include "type_algorithms.h"
+
+struct TestFloat {
+  template <class T>
+  static TEST_CONSTEXPR_CXX23 bool test() {
+    assert(std::isnormal(std::numeric_limits<T>::max()));
+    assert(!std::isnormal(std::numeric_limits<T>::infinity()));
+    assert(std::isnormal(std::numeric_limits<T>::min()));
+    assert(!std::isnormal(std::numeric_limits<T>::denorm_min()));
+    assert(std::isnormal(std::numeric_limits<T>::lowest()));
+    assert(!std::isnormal(-std::numeric_limits<T>::infinity()));
+    assert(!std::isnormal(T(0)));
+    assert(!std::isnormal(std::numeric_limits<T>::quiet_NaN()));
+    assert(!std::isnormal(std::numeric_limits<T>::signaling_NaN()));
+
+    return true;
+  }
+
+  template <class T>
+  TEST_CONSTEXPR_CXX23 void operator()() {
+    test<T>();
+#if TEST_STD_VER >= 23
+    static_assert(test<T>());
+#endif
+  }
+};
+
+struct TestInt {
+  template <class T>
+  static TEST_CONSTEXPR_CXX23 bool test() {
+    assert(std::isnormal(std::numeric_limits<T>::max()));
+    assert(std::isnormal(std::numeric_limits<T>::lowest()) == std::is_signed<T>::value);
+    assert(!std::isnormal(T(0)));
+
+    return true;
+  }
+
+  template <class T>
+  TEST_CONSTEXPR_CXX23 void operator()() {
+    test<T>();
+#if TEST_STD_VER >= 23
+    static_assert(test<T>());
+#endif
+  }
+};
+
+int main(int, char**) {
+  meta::for_each(meta::floating_point_types(), TestFloat());
+  meta::for_each(meta::integral_types(), TestInt());
+
+  return 0;
+}


        


More information about the libcxx-commits mailing list