From: Nikolas Klauser Date: Sun, 18 Dec 2022 23:02:44 +0000 (+0100) Subject: [libc++] Implement constexpr {isfinite, isinf, isnan, isnormal} X-Git-Tag: upstream/17.0.6~22651 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=52bff450dd46c28e1b2966c13bf0d603046214a5;p=platform%2Fupstream%2Fllvm.git [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 --- diff --git a/libcxx/docs/Status/Cxx2b.rst b/libcxx/docs/Status/Cxx2b.rst index 1537494..41b790e 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 9af4bca..aacdf16 100644 --- a/libcxx/docs/Status/Cxx2bPapers.csv +++ b/libcxx/docs/Status/Cxx2bPapers.csv @@ -39,7 +39,7 @@ "`P2401R0 `__","LWG","Add a conditional ``noexcept`` specification to ``std::exchange``","October 2021","|Complete|","14.0" "","","","","","" "`P0323R12 `__","LWG","``std::expected``","February 2022","|Complete|","16.0" -"`P0533R9 `__","LWG","``constexpr`` for ```` and ````","February 2022","","" +"`P0533R9 `__","LWG","``constexpr`` for ```` and ````","February 2022","|In progress| [#note-P0533R9]_","" "`P0627R6 `__","LWG","Function to mark unreachable code","February 2022","|Complete|","15.0" "`P1206R7 `__","LWG","``ranges::to``: A function to convert any range to a container","February 2022","","","|ranges|" "`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 dd68830..14fa9e2 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 ::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 ::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 ::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 -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 ::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 ::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 ::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 ::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 a64d322..269c487 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 #include #include @@ -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 f1d9539..b4ff47a 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 0000000..fd2ad11 --- /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 +#include +#include + +#include "test_macros.h" +#include "type_algorithms.h" + +struct TestFloat { + template + static TEST_CONSTEXPR_CXX23 bool test() { + assert(std::isfinite(std::numeric_limits::max())); + assert(!std::isfinite(std::numeric_limits::infinity())); + assert(std::isfinite(std::numeric_limits::min())); + assert(std::isfinite(std::numeric_limits::denorm_min())); + assert(std::isfinite(std::numeric_limits::lowest())); + assert(!std::isfinite(-std::numeric_limits::infinity())); + assert(std::isfinite(T(0))); + assert(!std::isfinite(std::numeric_limits::quiet_NaN())); + assert(!std::isfinite(std::numeric_limits::signaling_NaN())); + + return true; + } + + template + TEST_CONSTEXPR_CXX23 void operator()() { + test(); +#if TEST_STD_VER >= 23 + static_assert(test()); +#endif + } +}; + +struct TestInt { + template + static TEST_CONSTEXPR_CXX23 bool test() { + assert(std::isfinite(std::numeric_limits::max())); + assert(std::isfinite(std::numeric_limits::lowest())); + assert(std::isfinite(T(0))); + + return true; + } + + template + TEST_CONSTEXPR_CXX23 void operator()() { + test(); +#if TEST_STD_VER >= 23 + static_assert(test()); +#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 0000000..3b1e54f --- /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 +#include +#include + +#include "test_macros.h" +#include "type_algorithms.h" + +struct TestFloat { + template + static TEST_CONSTEXPR_CXX23 bool test() { + assert(!std::isinf(std::numeric_limits::max())); + assert(std::isinf(std::numeric_limits::infinity())); + assert(!std::isinf(std::numeric_limits::min())); + assert(!std::isinf(std::numeric_limits::denorm_min())); + assert(!std::isinf(std::numeric_limits::lowest())); + assert(std::isinf(-std::numeric_limits::infinity())); + assert(!std::isinf(T(0))); + assert(!std::isinf(std::numeric_limits::quiet_NaN())); + assert(!std::isinf(std::numeric_limits::signaling_NaN())); + + return true; + } + + template + TEST_CONSTEXPR_CXX23 void operator()() { + test(); +#if TEST_STD_VER >= 23 + static_assert(test()); +#endif + } +}; + +struct TestInt { + template + static TEST_CONSTEXPR_CXX23 bool test() { + assert(!std::isinf(std::numeric_limits::max())); + assert(!std::isinf(std::numeric_limits::lowest())); + assert(!std::isinf(T(0))); + + return true; + } + + template + TEST_CONSTEXPR_CXX23 void operator()() { + test(); +#if TEST_STD_VER >= 23 + static_assert(test()); +#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 0000000..c8ac055 --- /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 +#include +#include + +#include "test_macros.h" +#include "type_algorithms.h" + +struct TestFloat { + template + static TEST_CONSTEXPR_CXX23 bool test() { + assert(!std::isnan(std::numeric_limits::max())); + assert(!std::isnan(std::numeric_limits::infinity())); + assert(!std::isnan(std::numeric_limits::min())); + assert(!std::isnan(std::numeric_limits::denorm_min())); + assert(!std::isnan(std::numeric_limits::lowest())); + assert(!std::isnan(-std::numeric_limits::infinity())); + assert(!std::isnan(T(0))); + assert(std::isnan(std::numeric_limits::quiet_NaN())); + assert(std::isnan(std::numeric_limits::signaling_NaN())); + + return true; + } + + template + TEST_CONSTEXPR_CXX23 void operator()() { + test(); +#if TEST_STD_VER >= 23 + static_assert(test()); +#endif + } +}; + +struct TestInt { + template + static TEST_CONSTEXPR_CXX23 bool test() { + assert(!std::isnan(std::numeric_limits::max())); + assert(!std::isnan(std::numeric_limits::lowest())); + assert(!std::isnan(T(0))); + + return true; + } + + template + TEST_CONSTEXPR_CXX23 void operator()() { + test(); +#if TEST_STD_VER >= 23 + static_assert(test()); +#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 0000000..681438e --- /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 +#include +#include + +#include "test_macros.h" +#include "type_algorithms.h" + +struct TestFloat { + template + static TEST_CONSTEXPR_CXX23 bool test() { + assert(std::isnormal(std::numeric_limits::max())); + assert(!std::isnormal(std::numeric_limits::infinity())); + assert(std::isnormal(std::numeric_limits::min())); + assert(!std::isnormal(std::numeric_limits::denorm_min())); + assert(std::isnormal(std::numeric_limits::lowest())); + assert(!std::isnormal(-std::numeric_limits::infinity())); + assert(!std::isnormal(T(0))); + assert(!std::isnormal(std::numeric_limits::quiet_NaN())); + assert(!std::isnormal(std::numeric_limits::signaling_NaN())); + + return true; + } + + template + TEST_CONSTEXPR_CXX23 void operator()() { + test(); +#if TEST_STD_VER >= 23 + static_assert(test()); +#endif + } +}; + +struct TestInt { + template + static TEST_CONSTEXPR_CXX23 bool test() { + assert(std::isnormal(std::numeric_limits::max())); + assert(std::isnormal(std::numeric_limits::lowest()) == std::is_signed::value); + assert(!std::isnormal(T(0))); + + return true; + } + + template + TEST_CONSTEXPR_CXX23 void operator()() { + test(); +#if TEST_STD_VER >= 23 + static_assert(test()); +#endif + } +}; + +int main(int, char**) { + meta::for_each(meta::floating_point_types(), TestFloat()); + meta::for_each(meta::integral_types(), TestInt()); + + return 0; +}