From 8931d6263d5c4e35bb575b1be59f78f3fcfa49ca Mon Sep 17 00:00:00 2001 From: Hristo Hristov Date: Tue, 31 Mar 2026 12:41:09 +0300 Subject: [PATCH 1/7] [libc++][numeric] P4052R0: Renaming saturation arithmetic functions Also renames the internal version for consistency. - https://github.com/cplusplus/draft/pull/8877 - https://isocpp.org/files/papers/P4052R0.html --- libcxx/docs/FeatureTestMacroTable.rst | 2 +- libcxx/docs/ReleaseNotes/23.rst | 1 + .../include/__numeric/saturation_arithmetic.h | 30 +- libcxx/include/numeric | 10 +- libcxx/include/version | 4 +- libcxx/modules/std/numeric.inc | 10 +- .../test/libcxx/numerics/nodiscard.verify.cpp | 10 +- .../numeric.version.compile.pass.cpp | 4 +- .../version.version.compile.pass.cpp | 4 +- .../numeric.ops.sat/add_sat.compile.pass.cpp | 4 +- .../numeric.ops.sat/add_sat.pass.cpp | 118 ++--- .../numeric.ops.sat/div_sat.assert.pass.cpp | 4 +- .../numeric.ops.sat/div_sat.compile.pass.cpp | 6 +- .../numeric.ops.sat/div_sat.pass.cpp | 90 ++-- .../numeric.ops.sat/mul_sat.compile.pass.cpp | 4 +- .../numeric.ops.sat/mul_sat.pass.cpp | 116 ++--- .../saturate_cast.compile.pass.cpp | 4 +- .../numeric.ops.sat/saturate_cast.pass.cpp | 490 +++++++++--------- .../numeric.ops.sat/sub_sat.compile.pass.cpp | 4 +- .../numeric.ops.sat/sub_sat.pass.cpp | 102 ++-- .../generate_feature_test_macro_components.py | 2 +- 21 files changed, 510 insertions(+), 509 deletions(-) diff --git a/libcxx/docs/FeatureTestMacroTable.rst b/libcxx/docs/FeatureTestMacroTable.rst index 0f65770a4fa14..32c17a51b77dd 100644 --- a/libcxx/docs/FeatureTestMacroTable.rst +++ b/libcxx/docs/FeatureTestMacroTable.rst @@ -508,7 +508,7 @@ Status ---------------------------------------------------------- ----------------- ``__cpp_lib_reference_wrapper`` ``202403L`` ---------------------------------------------------------- ----------------- - ``__cpp_lib_saturation_arithmetic`` ``202311L`` + ``__cpp_lib_saturation_arithmetic`` ``202603L`` ---------------------------------------------------------- ----------------- ``__cpp_lib_senders`` *unimplemented* ---------------------------------------------------------- ----------------- diff --git a/libcxx/docs/ReleaseNotes/23.rst b/libcxx/docs/ReleaseNotes/23.rst index aeabfeedfbc5e..dd5a34e5bb20f 100644 --- a/libcxx/docs/ReleaseNotes/23.rst +++ b/libcxx/docs/ReleaseNotes/23.rst @@ -39,6 +39,7 @@ Implemented Papers ------------------ - P2440R1: ``ranges::iota``, ``ranges::shift_left`` and ``ranges::shift_right`` (`Github `__) +- P4052R0: Renaming saturation arithmetic functions Improvements and New Features ----------------------------- diff --git a/libcxx/include/__numeric/saturation_arithmetic.h b/libcxx/include/__numeric/saturation_arithmetic.h index 4491bab2b1479..34f784e4a9cf1 100644 --- a/libcxx/include/__numeric/saturation_arithmetic.h +++ b/libcxx/include/__numeric/saturation_arithmetic.h @@ -29,7 +29,7 @@ _LIBCPP_BEGIN_NAMESPACE_STD #if _LIBCPP_STD_VER >= 20 template <__signed_or_unsigned_integer _Tp> -_LIBCPP_HIDE_FROM_ABI constexpr _Tp __add_sat(_Tp __x, _Tp __y) noexcept { +_LIBCPP_HIDE_FROM_ABI constexpr _Tp __saturating_add(_Tp __x, _Tp __y) noexcept { # if defined(_LIBCPP_CLANG_VER) && _LIBCPP_CLANG_VER >= 2101 return __builtin_elementwise_add_sat(__x, __y); # else @@ -51,7 +51,7 @@ _LIBCPP_HIDE_FROM_ABI constexpr _Tp __add_sat(_Tp __x, _Tp __y) noexcept { } template <__signed_or_unsigned_integer _Tp> -_LIBCPP_HIDE_FROM_ABI constexpr _Tp __sub_sat(_Tp __x, _Tp __y) noexcept { +_LIBCPP_HIDE_FROM_ABI constexpr _Tp __saturating_sub(_Tp __x, _Tp __y) noexcept { # if defined(_LIBCPP_CLANG_VER) && _LIBCPP_CLANG_VER >= 2101 return __builtin_elementwise_sub_sat(__x, __y); # else @@ -74,7 +74,7 @@ _LIBCPP_HIDE_FROM_ABI constexpr _Tp __sub_sat(_Tp __x, _Tp __y) noexcept { } template <__signed_or_unsigned_integer _Tp> -_LIBCPP_HIDE_FROM_ABI constexpr _Tp __mul_sat(_Tp __x, _Tp __y) noexcept { +_LIBCPP_HIDE_FROM_ABI constexpr _Tp __saturating_mul(_Tp __x, _Tp __y) noexcept { if (_Tp __mul; !__builtin_mul_overflow(__x, __y, std::addressof(__mul))) return __mul; // Handle overflow @@ -90,7 +90,7 @@ _LIBCPP_HIDE_FROM_ABI constexpr _Tp __mul_sat(_Tp __x, _Tp __y) noexcept { } template <__signed_or_unsigned_integer _Tp> -_LIBCPP_HIDE_FROM_ABI constexpr _Tp __div_sat(_Tp __x, _Tp __y) noexcept { +_LIBCPP_HIDE_FROM_ABI constexpr _Tp __saturating_div(_Tp __x, _Tp __y) noexcept { _LIBCPP_ASSERT_UNCATEGORIZED(__y != 0, "Division by 0 is undefined"); if constexpr (__unsigned_integer<_Tp>) { return __x / __y; @@ -103,7 +103,7 @@ _LIBCPP_HIDE_FROM_ABI constexpr _Tp __div_sat(_Tp __x, _Tp __y) noexcept { } template <__signed_or_unsigned_integer _Rp, __signed_or_unsigned_integer _Tp> -_LIBCPP_HIDE_FROM_ABI constexpr _Rp __saturate_cast(_Tp __x) noexcept { +_LIBCPP_HIDE_FROM_ABI constexpr _Rp __saturating_cast(_Tp __x) noexcept { // Saturation is impossible edge case when ((min _Rp) < (min _Tp) && (max _Rp) > (max _Tp)) and it is expected to be // optimized out by the compiler. @@ -121,28 +121,28 @@ _LIBCPP_HIDE_FROM_ABI constexpr _Rp __saturate_cast(_Tp __x) noexcept { #if _LIBCPP_STD_VER >= 26 template <__signed_or_unsigned_integer _Tp> -[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr _Tp add_sat(_Tp __x, _Tp __y) noexcept { - return std::__add_sat(__x, __y); +[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr _Tp saturating_add(_Tp __x, _Tp __y) noexcept { + return std::__saturating_add(__x, __y); } template <__signed_or_unsigned_integer _Tp> -[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr _Tp sub_sat(_Tp __x, _Tp __y) noexcept { - return std::__sub_sat(__x, __y); +[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr _Tp saturating_sub(_Tp __x, _Tp __y) noexcept { + return std::__saturating_sub(__x, __y); } template <__signed_or_unsigned_integer _Tp> -[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr _Tp mul_sat(_Tp __x, _Tp __y) noexcept { - return std::__mul_sat(__x, __y); +[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr _Tp saturating_mul(_Tp __x, _Tp __y) noexcept { + return std::__saturating_mul(__x, __y); } template <__signed_or_unsigned_integer _Tp> -[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr _Tp div_sat(_Tp __x, _Tp __y) noexcept { - return std::__div_sat(__x, __y); +[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr _Tp saturating_div(_Tp __x, _Tp __y) noexcept { + return std::__saturating_div(__x, __y); } template <__signed_or_unsigned_integer _Rp, __signed_or_unsigned_integer _Tp> -[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr _Rp saturate_cast(_Tp __x) noexcept { - return std::__saturate_cast<_Rp>(__x); +[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr _Rp saturating_cast(_Tp __x) noexcept { + return std::__saturating_cast<_Rp>(__x); } #endif // _LIBCPP_STD_VER >= 26 diff --git a/libcxx/include/numeric b/libcxx/include/numeric index 48c330fcb009c..e490499bdd522 100644 --- a/libcxx/include/numeric +++ b/libcxx/include/numeric @@ -142,15 +142,15 @@ template // [numeric.sat], saturation arithmetic template -constexpr T add_sat(T x, T y) noexcept; // freestanding, Since C++26 +constexpr T saturating_add(T x, T y) noexcept; // freestanding, Since C++26 template -constexpr T sub_sat(T x, T y) noexcept; // freestanding, Since C++26 +constexpr T saturating_sub(T x, T y) noexcept; // freestanding, Since C++26 template -constexpr T mul_sat(T x, T y) noexcept; // freestanding, Since C++26 +constexpr T saturating_mul(T x, T y) noexcept; // freestanding, Since C++26 template -constexpr T div_sat(T x, T y) noexcept; // freestanding, Since C++26 +constexpr T saturating_div(T x, T y) noexcept; // freestanding, Since C++26 template -constexpr T saturate_cast(U x) noexcept; // freestanding, Since C++26 +constexpr T saturating_cast(U x) noexcept; // freestanding, Since C++26 } // std diff --git a/libcxx/include/version b/libcxx/include/version index c43d36e569efb..286c8b654ff6b 100644 --- a/libcxx/include/version +++ b/libcxx/include/version @@ -227,7 +227,7 @@ __cpp_lib_remove_cvref 201711L __cpp_lib_result_of_sfinae 201210L __cpp_lib_robust_nonmodifying_seq_ops 201304L __cpp_lib_sample 201603L -__cpp_lib_saturation_arithmetic 202311L +__cpp_lib_saturation_arithmetic 202603L __cpp_lib_scoped_lock 201703L __cpp_lib_semaphore 201907L __cpp_lib_senders 202406L @@ -612,7 +612,7 @@ __cpp_lib_void_t 201411L # define __cpp_lib_ratio 202306L // # define __cpp_lib_rcu 202306L # define __cpp_lib_reference_wrapper 202403L -# define __cpp_lib_saturation_arithmetic 202311L +# define __cpp_lib_saturation_arithmetic 202603L // # define __cpp_lib_senders 202406L // # define __cpp_lib_smart_ptr_owner_equality 202306L # define __cpp_lib_span_at 202311L diff --git a/libcxx/modules/std/numeric.inc b/libcxx/modules/std/numeric.inc index 5a549552081d2..e0edff9dfb0a5 100644 --- a/libcxx/modules/std/numeric.inc +++ b/libcxx/modules/std/numeric.inc @@ -61,11 +61,11 @@ export namespace std { #if _LIBCPP_STD_VER >= 26 // [numeric.sat], saturation arithmetic - using std::add_sat; - using std::div_sat; - using std::mul_sat; - using std::saturate_cast; - using std::sub_sat; + using std::saturating_add; + using std::saturating_cast; + using std::saturating_div; + using std::saturating_mul; + using std::saturating_sub; #endif } // namespace std diff --git a/libcxx/test/libcxx/numerics/nodiscard.verify.cpp b/libcxx/test/libcxx/numerics/nodiscard.verify.cpp index fe59e6a6a3fa7..c3635b8027aee 100644 --- a/libcxx/test/libcxx/numerics/nodiscard.verify.cpp +++ b/libcxx/test/libcxx/numerics/nodiscard.verify.cpp @@ -25,11 +25,11 @@ void test() { // clang-format off #if TEST_STD_VER >= 26 // [numeric.sat] - std::add_sat(94, 82); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} - std::sub_sat(94, 82); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} - std::mul_sat(94, 82); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} - std::div_sat(94, 82); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} - std::saturate_cast(49); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + std::saturating_add(94, 82); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + std::saturating_sub(94, 82); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + std::saturating_mul(94, 82); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + std::saturating_div(94, 82); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + std::saturating_cast(49); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} #endif // TEST_STD_VER >= 26 // clang-format on diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/numeric.version.compile.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/numeric.version.compile.pass.cpp index cafbd2cac2ccf..d629407c9b645 100644 --- a/libcxx/test/std/language.support/support.limits/support.limits.general/numeric.version.compile.pass.cpp +++ b/libcxx/test/std/language.support/support.limits/support.limits.general/numeric.version.compile.pass.cpp @@ -245,8 +245,8 @@ # ifndef __cpp_lib_saturation_arithmetic # error "__cpp_lib_saturation_arithmetic should be defined in c++26" # endif -# if __cpp_lib_saturation_arithmetic != 202311L -# error "__cpp_lib_saturation_arithmetic should have the value 202311L in c++26" +# if __cpp_lib_saturation_arithmetic != 202603L +# error "__cpp_lib_saturation_arithmetic should have the value 202603L in c++26" # endif #endif // TEST_STD_VER > 23 diff --git a/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp b/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp index a1c8755af4ad9..718c67f11d00d 100644 --- a/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp +++ b/libcxx/test/std/language.support/support.limits/support.limits.general/version.version.compile.pass.cpp @@ -7782,8 +7782,8 @@ # ifndef __cpp_lib_saturation_arithmetic # error "__cpp_lib_saturation_arithmetic should be defined in c++26" # endif -# if __cpp_lib_saturation_arithmetic != 202311L -# error "__cpp_lib_saturation_arithmetic should have the value 202311L in c++26" +# if __cpp_lib_saturation_arithmetic != 202603L +# error "__cpp_lib_saturation_arithmetic should have the value 202603L in c++26" # endif # if !defined(_LIBCPP_VERSION) || _LIBCPP_HAS_THREADS diff --git a/libcxx/test/std/numerics/numeric.ops/numeric.ops.sat/add_sat.compile.pass.cpp b/libcxx/test/std/numerics/numeric.ops/numeric.ops.sat/add_sat.compile.pass.cpp index 23f780cfc2b5e..03c7dc724acfb 100644 --- a/libcxx/test/std/numerics/numeric.ops/numeric.ops.sat/add_sat.compile.pass.cpp +++ b/libcxx/test/std/numerics/numeric.ops/numeric.ops.sat/add_sat.compile.pass.cpp @@ -11,7 +11,7 @@ // // template -// constexpr T add_sat(T x, T y) noexcept; // freestanding +// constexpr T saturating_add(T x, T y) noexcept; // freestanding #include #include @@ -20,7 +20,7 @@ template concept CanDo = requires(T x, U y) { - { std::add_sat(x, y) } -> std::same_as; + { std::saturating_add(x, y) } -> std::same_as; }; template diff --git a/libcxx/test/std/numerics/numeric.ops/numeric.ops.sat/add_sat.pass.cpp b/libcxx/test/std/numerics/numeric.ops/numeric.ops.sat/add_sat.pass.cpp index f49e19acf0234..fb05119f7c220 100644 --- a/libcxx/test/std/numerics/numeric.ops/numeric.ops.sat/add_sat.pass.cpp +++ b/libcxx/test/std/numerics/numeric.ops/numeric.ops.sat/add_sat.pass.cpp @@ -11,7 +11,7 @@ // // template -// constexpr T add_sat(T x, T y) noexcept; // freestanding +// constexpr T saturating_add(T x, T y) noexcept; // freestanding #include #include @@ -25,52 +25,52 @@ constexpr bool test_signed() { constexpr auto minVal = std::numeric_limits::min(); constexpr auto maxVal = std::numeric_limits::max(); - std::same_as decltype(auto) _ = std::add_sat(minVal, maxVal); + std::same_as decltype(auto) _ = std::saturating_add(minVal, maxVal); - static_assert(noexcept(std::add_sat(minVal, maxVal))); + static_assert(noexcept(std::saturating_add(minVal, maxVal))); // clang-format off // Limit values (-1, 0, 1, min, max) - assert(std::add_sat(IntegerT{-1}, IntegerT{-1}) == IntegerT{-2}); - assert(std::add_sat(IntegerT{-1}, IntegerT{ 0}) == IntegerT{-1}); - assert(std::add_sat(IntegerT{-1}, IntegerT{ 1}) == IntegerT{ 0}); - assert(std::add_sat(IntegerT{-1}, minVal) == minVal); // saturated - assert(std::add_sat(IntegerT{-1}, maxVal) == IntegerT{-1} + maxVal); - - assert(std::add_sat(IntegerT{ 0}, IntegerT{-1}) == IntegerT{-1}); - assert(std::add_sat(IntegerT{ 0}, IntegerT{ 0}) == IntegerT{ 0}); - assert(std::add_sat(IntegerT{ 0}, IntegerT{ 1}) == IntegerT{ 1}); - assert(std::add_sat(IntegerT{ 0}, minVal) == minVal); - assert(std::add_sat(IntegerT{ 0}, maxVal) == maxVal); - - assert(std::add_sat(IntegerT{ 1}, IntegerT{-1}) == IntegerT{ 0}); - assert(std::add_sat(IntegerT{ 1}, IntegerT{ 0}) == IntegerT{ 1}); - assert(std::add_sat(IntegerT{ 1}, IntegerT{ 1}) == IntegerT{ 2}); - assert(std::add_sat(IntegerT{ 1}, minVal) == IntegerT{ 1} + minVal); - assert(std::add_sat(IntegerT{ 1}, maxVal) == maxVal); // saturated - - assert(std::add_sat( minVal, IntegerT{-1}) == minVal); // saturated - assert(std::add_sat( minVal, IntegerT{ 0}) == minVal); - assert(std::add_sat( minVal, IntegerT{ 1}) == minVal + IntegerT{ 1}); - assert(std::add_sat( minVal, minVal) == minVal); // saturated - assert(std::add_sat( minVal, maxVal) == IntegerT{-1}); - - assert(std::add_sat( maxVal, IntegerT{-1}) == maxVal + IntegerT{-1}); - assert(std::add_sat( maxVal, IntegerT{ 0}) == maxVal); - assert(std::add_sat( maxVal, IntegerT{ 1}) == maxVal); // saturated - assert(std::add_sat( maxVal, minVal) == IntegerT{-1}); - assert(std::add_sat( maxVal, maxVal) == maxVal); // saturated + assert(std::saturating_add(IntegerT{-1}, IntegerT{-1}) == IntegerT{-2}); + assert(std::saturating_add(IntegerT{-1}, IntegerT{ 0}) == IntegerT{-1}); + assert(std::saturating_add(IntegerT{-1}, IntegerT{ 1}) == IntegerT{ 0}); + assert(std::saturating_add(IntegerT{-1}, minVal) == minVal); // saturated + assert(std::saturating_add(IntegerT{-1}, maxVal) == IntegerT{-1} + maxVal); + + assert(std::saturating_add(IntegerT{ 0}, IntegerT{-1}) == IntegerT{-1}); + assert(std::saturating_add(IntegerT{ 0}, IntegerT{ 0}) == IntegerT{ 0}); + assert(std::saturating_add(IntegerT{ 0}, IntegerT{ 1}) == IntegerT{ 1}); + assert(std::saturating_add(IntegerT{ 0}, minVal) == minVal); + assert(std::saturating_add(IntegerT{ 0}, maxVal) == maxVal); + + assert(std::saturating_add(IntegerT{ 1}, IntegerT{-1}) == IntegerT{ 0}); + assert(std::saturating_add(IntegerT{ 1}, IntegerT{ 0}) == IntegerT{ 1}); + assert(std::saturating_add(IntegerT{ 1}, IntegerT{ 1}) == IntegerT{ 2}); + assert(std::saturating_add(IntegerT{ 1}, minVal) == IntegerT{ 1} + minVal); + assert(std::saturating_add(IntegerT{ 1}, maxVal) == maxVal); // saturated + + assert(std::saturating_add( minVal, IntegerT{-1}) == minVal); // saturated + assert(std::saturating_add( minVal, IntegerT{ 0}) == minVal); + assert(std::saturating_add( minVal, IntegerT{ 1}) == minVal + IntegerT{ 1}); + assert(std::saturating_add( minVal, minVal) == minVal); // saturated + assert(std::saturating_add( minVal, maxVal) == IntegerT{-1}); + + assert(std::saturating_add( maxVal, IntegerT{-1}) == maxVal + IntegerT{-1}); + assert(std::saturating_add( maxVal, IntegerT{ 0}) == maxVal); + assert(std::saturating_add( maxVal, IntegerT{ 1}) == maxVal); // saturated + assert(std::saturating_add( maxVal, minVal) == IntegerT{-1}); + assert(std::saturating_add( maxVal, maxVal) == maxVal); // saturated // No saturation (no limit values) - assert(std::add_sat(IntegerT{-27}, IntegerT{28})== IntegerT{ 1}); - assert(std::add_sat(IntegerT{ 27}, IntegerT{28})== IntegerT{55}); + assert(std::saturating_add(IntegerT{-27}, IntegerT{28})== IntegerT{ 1}); + assert(std::saturating_add(IntegerT{ 27}, IntegerT{28})== IntegerT{55}); { constexpr IntegerT x = maxVal / IntegerT{2} + IntegerT{27}; constexpr IntegerT y = maxVal / IntegerT{2} + IntegerT{28}; - assert(std::add_sat(x, y) == maxVal); + assert(std::saturating_add(x, y) == maxVal); } // Saturation (no limit values) @@ -78,12 +78,12 @@ constexpr bool test_signed() { { constexpr IntegerT x = minVal / IntegerT{2} + IntegerT{-27}; constexpr IntegerT y = minVal / IntegerT{2} + IntegerT{-28}; - assert(std::add_sat(x, y) == minVal); // saturated + assert(std::saturating_add(x, y) == minVal); // saturated } { constexpr IntegerT x = maxVal / IntegerT{2} + IntegerT{27}; constexpr IntegerT y = maxVal / IntegerT{2} + IntegerT{28}; - assert(std::add_sat(x, y) == maxVal); // saturated + assert(std::saturating_add(x, y) == maxVal); // saturated } // clang-format on @@ -96,43 +96,43 @@ constexpr bool test_unsigned() { constexpr auto minVal = std::numeric_limits::min(); constexpr auto maxVal = std::numeric_limits::max(); - std::same_as decltype(auto) _ = std::add_sat(minVal, maxVal); + std::same_as decltype(auto) _ = std::saturating_add(minVal, maxVal); - static_assert(noexcept(std::add_sat(minVal, maxVal))); + static_assert(noexcept(std::saturating_add(minVal, maxVal))); // clang-format off // Litmit values (0, 1, min, max) - assert(std::add_sat(IntegerT{0}, IntegerT{0}) == IntegerT{0}); - assert(std::add_sat(IntegerT{0}, IntegerT{1}) == IntegerT{1}); - assert(std::add_sat(IntegerT{0}, minVal) == IntegerT{0}); - assert(std::add_sat(IntegerT{0}, maxVal) == maxVal); - assert(std::add_sat(IntegerT{1}, IntegerT{0}) == IntegerT{1}); - assert(std::add_sat(IntegerT{1}, IntegerT{1}) == IntegerT{2}); - assert(std::add_sat(IntegerT{1}, minVal) == IntegerT{1}); - assert(std::add_sat(IntegerT{1}, maxVal) == maxVal); // saturated - assert(std::add_sat( minVal, IntegerT{0}) == IntegerT{0}); - assert(std::add_sat( minVal, IntegerT{1}) == IntegerT{1}); - assert(std::add_sat( minVal, minVal) == minVal); - assert(std::add_sat( minVal, maxVal) == maxVal); - assert(std::add_sat( maxVal, IntegerT{0}) == maxVal); - assert(std::add_sat( maxVal, IntegerT{1}) == maxVal); // saturated - assert(std::add_sat( maxVal, minVal) == maxVal); - assert(std::add_sat( maxVal, maxVal) == maxVal); // saturated + assert(std::saturating_add(IntegerT{0}, IntegerT{0}) == IntegerT{0}); + assert(std::saturating_add(IntegerT{0}, IntegerT{1}) == IntegerT{1}); + assert(std::saturating_add(IntegerT{0}, minVal) == IntegerT{0}); + assert(std::saturating_add(IntegerT{0}, maxVal) == maxVal); + assert(std::saturating_add(IntegerT{1}, IntegerT{0}) == IntegerT{1}); + assert(std::saturating_add(IntegerT{1}, IntegerT{1}) == IntegerT{2}); + assert(std::saturating_add(IntegerT{1}, minVal) == IntegerT{1}); + assert(std::saturating_add(IntegerT{1}, maxVal) == maxVal); // saturated + assert(std::saturating_add( minVal, IntegerT{0}) == IntegerT{0}); + assert(std::saturating_add( minVal, IntegerT{1}) == IntegerT{1}); + assert(std::saturating_add( minVal, minVal) == minVal); + assert(std::saturating_add( minVal, maxVal) == maxVal); + assert(std::saturating_add( maxVal, IntegerT{0}) == maxVal); + assert(std::saturating_add( maxVal, IntegerT{1}) == maxVal); // saturated + assert(std::saturating_add( maxVal, minVal) == maxVal); + assert(std::saturating_add( maxVal, maxVal) == maxVal); // saturated // No saturation (no limit values) - assert(std::add_sat(IntegerT{27}, IntegerT{28}) == IntegerT{55}); + assert(std::saturating_add(IntegerT{27}, IntegerT{28}) == IntegerT{55}); // Saturation (no limit values) { constexpr IntegerT x = maxVal / IntegerT{2} + IntegerT{27}; constexpr IntegerT y = maxVal / IntegerT{2} + IntegerT{28}; - assert(std::add_sat( x, y) == maxVal); // saturated - assert(std::add_sat( x, maxVal) == maxVal); // saturated - assert(std::add_sat(maxVal, y) == maxVal); // saturated + assert(std::saturating_add( x, y) == maxVal); // saturated + assert(std::saturating_add( x, maxVal) == maxVal); // saturated + assert(std::saturating_add(maxVal, y) == maxVal); // saturated } // clang-format on diff --git a/libcxx/test/std/numerics/numeric.ops/numeric.ops.sat/div_sat.assert.pass.cpp b/libcxx/test/std/numerics/numeric.ops/numeric.ops.sat/div_sat.assert.pass.cpp index 50bc29bee4d53..79cbd8124b2de 100644 --- a/libcxx/test/std/numerics/numeric.ops/numeric.ops.sat/div_sat.assert.pass.cpp +++ b/libcxx/test/std/numerics/numeric.ops/numeric.ops.sat/div_sat.assert.pass.cpp @@ -15,7 +15,7 @@ // // template -// constexpr T div_sat(T x, T y) noexcept; // freestanding +// constexpr T saturating_div(T x, T y) noexcept; // freestanding #include #include @@ -25,7 +25,7 @@ template void test_runtime_assertion() { - TEST_LIBCPP_ASSERT_FAILURE((void)std::div_sat(IntegerT{27}, IntegerT{0}), "Division by 0 is undefined"); + TEST_LIBCPP_ASSERT_FAILURE((void)std::saturating_div(IntegerT{27}, IntegerT{0}), "Division by 0 is undefined"); } bool test() { diff --git a/libcxx/test/std/numerics/numeric.ops/numeric.ops.sat/div_sat.compile.pass.cpp b/libcxx/test/std/numerics/numeric.ops/numeric.ops.sat/div_sat.compile.pass.cpp index 02ffb17292164..f644b11db05cd 100644 --- a/libcxx/test/std/numerics/numeric.ops/numeric.ops.sat/div_sat.compile.pass.cpp +++ b/libcxx/test/std/numerics/numeric.ops/numeric.ops.sat/div_sat.compile.pass.cpp @@ -11,7 +11,7 @@ // // template -// constexpr T div_sat(T x, T y) noexcept; // freestanding +// constexpr T saturating_div(T x, T y) noexcept; // freestanding #include #include @@ -23,7 +23,7 @@ template concept CanDo = requires(T x, U y) { - { std::div_sat(x, y) } -> std::same_as; + { std::saturating_div(x, y) } -> std::same_as; }; template @@ -82,7 +82,7 @@ constexpr void test() { // A function call expression that violates the precondition in the Preconditions: element is not a core constant expression (7.7 [expr.const]). template -using QuotT = std::integral_constant; +using QuotT = std::integral_constant; template QuotT div_by_zero(); diff --git a/libcxx/test/std/numerics/numeric.ops/numeric.ops.sat/div_sat.pass.cpp b/libcxx/test/std/numerics/numeric.ops/numeric.ops.sat/div_sat.pass.cpp index 0789213163847..75045e07c3b84 100644 --- a/libcxx/test/std/numerics/numeric.ops/numeric.ops.sat/div_sat.pass.cpp +++ b/libcxx/test/std/numerics/numeric.ops/numeric.ops.sat/div_sat.pass.cpp @@ -11,7 +11,7 @@ // // template -// constexpr T div_sat(T x, T y) noexcept; // freestanding +// constexpr T saturating_div(T x, T y) noexcept; // freestanding #include #include @@ -25,56 +25,56 @@ constexpr bool test_signed() { constexpr auto minVal = std::numeric_limits::min(); constexpr auto maxVal = std::numeric_limits::max(); - std::same_as decltype(auto) _ = std::div_sat(minVal, maxVal); + std::same_as decltype(auto) _ = std::saturating_div(minVal, maxVal); - static_assert(noexcept(std::div_sat(minVal, maxVal))); + static_assert(noexcept(std::saturating_div(minVal, maxVal))); // clang-format off // Limit values (-1, 0, 1, min, max) - assert(std::div_sat(IntegerT{-1}, IntegerT{-1}) == IntegerT{ 1}); - assert(std::div_sat(IntegerT{-1}, IntegerT{ 1}) == IntegerT{-1}); - assert(std::div_sat(IntegerT{-1}, minVal) == IntegerT{ 0}); - assert(std::div_sat(IntegerT{-1}, maxVal) == IntegerT{ 0}); - assert(std::div_sat(IntegerT{ 0}, IntegerT{-1}) == IntegerT{ 0}); - assert(std::div_sat(IntegerT{ 0}, IntegerT{ 1}) == IntegerT{ 0}); - assert(std::div_sat(IntegerT{ 0}, minVal) == IntegerT{ 0}); - assert(std::div_sat(IntegerT{ 0}, maxVal) == IntegerT{ 0}); - assert(std::div_sat(IntegerT{ 1}, IntegerT{-1}) == IntegerT{-1}); - assert(std::div_sat(IntegerT{ 1}, IntegerT{ 1}) == IntegerT{ 1}); - assert(std::div_sat(IntegerT{ 1}, minVal) == IntegerT{ 0}); - assert(std::div_sat(IntegerT{ 1}, maxVal) == IntegerT{ 0}); - assert(std::div_sat( minVal, IntegerT{ 1}) == minVal); - assert(std::div_sat( minVal, IntegerT{-1}) == maxVal); // saturated - assert(std::div_sat( minVal, minVal) == IntegerT{ 1}); - assert(std::div_sat( minVal, maxVal) == (minVal / maxVal)); - assert(std::div_sat( maxVal, IntegerT{-1}) == -maxVal); - assert(std::div_sat( maxVal, IntegerT{ 1}) == maxVal); - assert(std::div_sat( maxVal, minVal) == IntegerT{ 0}); - assert(std::div_sat( maxVal, maxVal) == IntegerT{ 1}); + assert(std::saturating_div(IntegerT{-1}, IntegerT{-1}) == IntegerT{ 1}); + assert(std::saturating_div(IntegerT{-1}, IntegerT{ 1}) == IntegerT{-1}); + assert(std::saturating_div(IntegerT{-1}, minVal) == IntegerT{ 0}); + assert(std::saturating_div(IntegerT{-1}, maxVal) == IntegerT{ 0}); + assert(std::saturating_div(IntegerT{ 0}, IntegerT{-1}) == IntegerT{ 0}); + assert(std::saturating_div(IntegerT{ 0}, IntegerT{ 1}) == IntegerT{ 0}); + assert(std::saturating_div(IntegerT{ 0}, minVal) == IntegerT{ 0}); + assert(std::saturating_div(IntegerT{ 0}, maxVal) == IntegerT{ 0}); + assert(std::saturating_div(IntegerT{ 1}, IntegerT{-1}) == IntegerT{-1}); + assert(std::saturating_div(IntegerT{ 1}, IntegerT{ 1}) == IntegerT{ 1}); + assert(std::saturating_div(IntegerT{ 1}, minVal) == IntegerT{ 0}); + assert(std::saturating_div(IntegerT{ 1}, maxVal) == IntegerT{ 0}); + assert(std::saturating_div( minVal, IntegerT{ 1}) == minVal); + assert(std::saturating_div( minVal, IntegerT{-1}) == maxVal); // saturated + assert(std::saturating_div( minVal, minVal) == IntegerT{ 1}); + assert(std::saturating_div( minVal, maxVal) == (minVal / maxVal)); + assert(std::saturating_div( maxVal, IntegerT{-1}) == -maxVal); + assert(std::saturating_div( maxVal, IntegerT{ 1}) == maxVal); + assert(std::saturating_div( maxVal, minVal) == IntegerT{ 0}); + assert(std::saturating_div( maxVal, maxVal) == IntegerT{ 1}); // No saturation (no limit values) - assert(std::div_sat(IntegerT{27}, IntegerT{28}) == IntegerT{0}); - assert(std::div_sat(IntegerT{28}, IntegerT{27}) == IntegerT{1}); + assert(std::saturating_div(IntegerT{27}, IntegerT{28}) == IntegerT{0}); + assert(std::saturating_div(IntegerT{28}, IntegerT{27}) == IntegerT{1}); { constexpr IntegerT lesserVal = minVal / IntegerT{2} + IntegerT{-28}; constexpr IntegerT biggerVal = minVal / IntegerT{2} + IntegerT{-27}; - assert(std::div_sat(lesserVal, biggerVal) == IntegerT{1}); - assert(std::div_sat(biggerVal, lesserVal) == IntegerT{0}); + assert(std::saturating_div(lesserVal, biggerVal) == IntegerT{1}); + assert(std::saturating_div(biggerVal, lesserVal) == IntegerT{0}); } { constexpr IntegerT lesserVal = minVal / IntegerT{2} + IntegerT{-27}; constexpr IntegerT biggerVal = maxVal / IntegerT{2} + IntegerT{28}; - assert(std::div_sat(lesserVal, biggerVal) == IntegerT{-1}); - assert(std::div_sat(biggerVal, lesserVal) == IntegerT{-1}); + assert(std::saturating_div(lesserVal, biggerVal) == IntegerT{-1}); + assert(std::saturating_div(biggerVal, lesserVal) == IntegerT{-1}); } { constexpr IntegerT lesserVal = maxVal / IntegerT{2} + IntegerT{27}; constexpr IntegerT biggerVal = maxVal / IntegerT{2} + IntegerT{28}; - assert(std::div_sat(lesserVal, biggerVal) == IntegerT{0}); - assert(std::div_sat(biggerVal, lesserVal) == IntegerT{1}); + assert(std::saturating_div(lesserVal, biggerVal) == IntegerT{0}); + assert(std::saturating_div(biggerVal, lesserVal) == IntegerT{1}); } // clang-format on @@ -87,34 +87,34 @@ constexpr bool test_unsigned() { constexpr auto minVal = std::numeric_limits::min(); constexpr auto maxVal = std::numeric_limits::max(); - std::same_as decltype(auto) _ = std::div_sat(minVal, maxVal); - static_assert(noexcept(std::div_sat(minVal, maxVal))); + std::same_as decltype(auto) _ = std::saturating_div(minVal, maxVal); + static_assert(noexcept(std::saturating_div(minVal, maxVal))); // clang-format off // No limit values (0, 1, min, max) - assert(std::div_sat(IntegerT{0}, IntegerT{1}) == IntegerT{0}); - assert(std::div_sat(IntegerT{0}, maxVal) == IntegerT{0}); + assert(std::saturating_div(IntegerT{0}, IntegerT{1}) == IntegerT{0}); + assert(std::saturating_div(IntegerT{0}, maxVal) == IntegerT{0}); - assert(std::div_sat(IntegerT{1}, IntegerT{1}) == IntegerT{1}); - assert(std::div_sat(IntegerT{1}, maxVal) == IntegerT{0}); + assert(std::saturating_div(IntegerT{1}, IntegerT{1}) == IntegerT{1}); + assert(std::saturating_div(IntegerT{1}, maxVal) == IntegerT{0}); - assert(std::div_sat( minVal, IntegerT{1}) == minVal); - assert(std::div_sat( minVal, maxVal) == IntegerT{0}); + assert(std::saturating_div( minVal, IntegerT{1}) == minVal); + assert(std::saturating_div( minVal, maxVal) == IntegerT{0}); - assert(std::div_sat( maxVal, IntegerT{1}) == maxVal); - assert(std::div_sat( maxVal, maxVal) == IntegerT{1}); + assert(std::saturating_div( maxVal, IntegerT{1}) == maxVal); + assert(std::saturating_div( maxVal, maxVal) == IntegerT{1}); // No saturation (no limit values) - assert(std::div_sat(IntegerT{27}, IntegerT{28}) == IntegerT{0}); - assert(std::div_sat(IntegerT{28}, IntegerT{27}) == IntegerT{1}); + assert(std::saturating_div(IntegerT{27}, IntegerT{28}) == IntegerT{0}); + assert(std::saturating_div(IntegerT{28}, IntegerT{27}) == IntegerT{1}); { constexpr IntegerT lesserVal = maxVal / IntegerT{2} + IntegerT{27}; constexpr IntegerT biggerVal = maxVal / IntegerT{2} + IntegerT{28}; - assert(std::div_sat(lesserVal, biggerVal) == IntegerT{0}); - assert(std::div_sat(biggerVal, lesserVal) == IntegerT{1}); + assert(std::saturating_div(lesserVal, biggerVal) == IntegerT{0}); + assert(std::saturating_div(biggerVal, lesserVal) == IntegerT{1}); } // Unsigned integer division never overflows diff --git a/libcxx/test/std/numerics/numeric.ops/numeric.ops.sat/mul_sat.compile.pass.cpp b/libcxx/test/std/numerics/numeric.ops/numeric.ops.sat/mul_sat.compile.pass.cpp index cd572a73006a8..418c479cd22c6 100644 --- a/libcxx/test/std/numerics/numeric.ops/numeric.ops.sat/mul_sat.compile.pass.cpp +++ b/libcxx/test/std/numerics/numeric.ops/numeric.ops.sat/mul_sat.compile.pass.cpp @@ -11,7 +11,7 @@ // // template -// constexpr T mul_sat(T x, T y) noexcept; // freestanding +// constexpr T saturating_mul(T x, T y) noexcept; // freestanding #include #include @@ -20,7 +20,7 @@ template concept CanDo = requires(T x, U y) { - { std::mul_sat(x, y) } -> std::same_as; + { std::saturating_mul(x, y) } -> std::same_as; }; template diff --git a/libcxx/test/std/numerics/numeric.ops/numeric.ops.sat/mul_sat.pass.cpp b/libcxx/test/std/numerics/numeric.ops/numeric.ops.sat/mul_sat.pass.cpp index f09bf30771102..f98aeaf4dd5a8 100644 --- a/libcxx/test/std/numerics/numeric.ops/numeric.ops.sat/mul_sat.pass.cpp +++ b/libcxx/test/std/numerics/numeric.ops/numeric.ops.sat/mul_sat.pass.cpp @@ -11,7 +11,7 @@ // // template -// constexpr T mul_sat(T x, T y) noexcept; // freestanding +// constexpr T saturating_mul(T x, T y) noexcept; // freestanding #include #include @@ -25,70 +25,70 @@ constexpr bool test_signed() { constexpr auto minVal = std::numeric_limits::min(); constexpr auto maxVal = std::numeric_limits::max(); - std::same_as decltype(auto) _ = std::mul_sat(minVal, maxVal); + std::same_as decltype(auto) _ = std::saturating_mul(minVal, maxVal); - static_assert(noexcept(std::mul_sat(minVal, maxVal))); + static_assert(noexcept(std::saturating_mul(minVal, maxVal))); // clang-format off // Limit values (-1, 0, 1, min, max) - assert(std::mul_sat(IntegerT{-1}, IntegerT{-1}) == IntegerT{ 1}); - assert(std::mul_sat(IntegerT{-1}, IntegerT{ 0}) == IntegerT{ 0}); - assert(std::mul_sat(IntegerT{-1}, IntegerT{ 1}) == IntegerT{-1}); - assert(std::mul_sat(IntegerT{-1}, minVal) == maxVal); // saturated - assert(std::mul_sat(IntegerT{-1}, maxVal) == -maxVal); - - assert(std::mul_sat(IntegerT{ 0}, IntegerT{-1}) == IntegerT{ 0}); - assert(std::mul_sat(IntegerT{ 0}, IntegerT{ 0}) == IntegerT{ 0}); - assert(std::mul_sat(IntegerT{ 0}, IntegerT{ 1}) == IntegerT{ 0}); - assert(std::mul_sat(IntegerT{ 0}, minVal) == IntegerT{ 0}); - assert(std::mul_sat(IntegerT{ 0}, maxVal) == IntegerT{ 0}); - - assert(std::mul_sat(IntegerT{ 1}, IntegerT{-1}) == IntegerT{-1}); - assert(std::mul_sat(IntegerT{ 1}, IntegerT{ 0}) == IntegerT{ 0}); - assert(std::mul_sat(IntegerT{ 1}, IntegerT{ 1}) == IntegerT{ 1}); - assert(std::mul_sat(IntegerT{ 1}, minVal) == minVal); - assert(std::mul_sat(IntegerT{ 1}, maxVal) == maxVal); - - assert(std::mul_sat( minVal, IntegerT{-1}) == maxVal); // saturated - assert(std::mul_sat( minVal, IntegerT{ 0}) == IntegerT{ 0}); - assert(std::mul_sat( minVal, IntegerT{ 1}) == minVal); - assert(std::mul_sat( minVal, minVal) == maxVal); // saturated - assert(std::mul_sat( minVal, maxVal) == minVal); // saturated - - assert(std::mul_sat( maxVal, IntegerT{-1}) == -maxVal); - assert(std::mul_sat( maxVal, IntegerT{ 0}) == IntegerT{ 0}); - assert(std::mul_sat( maxVal, IntegerT{ 1}) == maxVal); // saturated - assert(std::mul_sat( maxVal, minVal) == minVal); // saturated - assert(std::mul_sat( maxVal, maxVal) == maxVal); // saturated + assert(std::saturating_mul(IntegerT{-1}, IntegerT{-1}) == IntegerT{ 1}); + assert(std::saturating_mul(IntegerT{-1}, IntegerT{ 0}) == IntegerT{ 0}); + assert(std::saturating_mul(IntegerT{-1}, IntegerT{ 1}) == IntegerT{-1}); + assert(std::saturating_mul(IntegerT{-1}, minVal) == maxVal); // saturated + assert(std::saturating_mul(IntegerT{-1}, maxVal) == -maxVal); + + assert(std::saturating_mul(IntegerT{ 0}, IntegerT{-1}) == IntegerT{ 0}); + assert(std::saturating_mul(IntegerT{ 0}, IntegerT{ 0}) == IntegerT{ 0}); + assert(std::saturating_mul(IntegerT{ 0}, IntegerT{ 1}) == IntegerT{ 0}); + assert(std::saturating_mul(IntegerT{ 0}, minVal) == IntegerT{ 0}); + assert(std::saturating_mul(IntegerT{ 0}, maxVal) == IntegerT{ 0}); + + assert(std::saturating_mul(IntegerT{ 1}, IntegerT{-1}) == IntegerT{-1}); + assert(std::saturating_mul(IntegerT{ 1}, IntegerT{ 0}) == IntegerT{ 0}); + assert(std::saturating_mul(IntegerT{ 1}, IntegerT{ 1}) == IntegerT{ 1}); + assert(std::saturating_mul(IntegerT{ 1}, minVal) == minVal); + assert(std::saturating_mul(IntegerT{ 1}, maxVal) == maxVal); + + assert(std::saturating_mul( minVal, IntegerT{-1}) == maxVal); // saturated + assert(std::saturating_mul( minVal, IntegerT{ 0}) == IntegerT{ 0}); + assert(std::saturating_mul( minVal, IntegerT{ 1}) == minVal); + assert(std::saturating_mul( minVal, minVal) == maxVal); // saturated + assert(std::saturating_mul( minVal, maxVal) == minVal); // saturated + + assert(std::saturating_mul( maxVal, IntegerT{-1}) == -maxVal); + assert(std::saturating_mul( maxVal, IntegerT{ 0}) == IntegerT{ 0}); + assert(std::saturating_mul( maxVal, IntegerT{ 1}) == maxVal); // saturated + assert(std::saturating_mul( maxVal, minVal) == minVal); // saturated + assert(std::saturating_mul( maxVal, maxVal) == maxVal); // saturated // No saturation (no limit values) - assert(std::mul_sat(IntegerT{27}, IntegerT{ 2}) == IntegerT{54}); - assert(std::mul_sat(IntegerT{ 2}, IntegerT{28}) == IntegerT{56}); + assert(std::saturating_mul(IntegerT{27}, IntegerT{ 2}) == IntegerT{54}); + assert(std::saturating_mul(IntegerT{ 2}, IntegerT{28}) == IntegerT{56}); // Saturation (no limit values) { constexpr IntegerT x = minVal / IntegerT{2} + IntegerT{27}; constexpr IntegerT y = minVal / IntegerT{2} + IntegerT{28}; - assert(std::mul_sat(x, y) == maxVal); // saturated + assert(std::saturating_mul(x, y) == maxVal); // saturated } { constexpr IntegerT x = minVal / IntegerT{2} + IntegerT{27}; constexpr IntegerT y = maxVal / IntegerT{2} + IntegerT{28}; - assert(std::mul_sat(x, y) == minVal); // saturated + assert(std::saturating_mul(x, y) == minVal); // saturated } { constexpr IntegerT x = maxVal / IntegerT{2} + IntegerT{27}; constexpr IntegerT y = minVal / IntegerT{2} + IntegerT{28}; - assert(std::mul_sat(x, y) == minVal); // saturated + assert(std::saturating_mul(x, y) == minVal); // saturated } { constexpr IntegerT x = maxVal / IntegerT{2} + IntegerT{27}; constexpr IntegerT y = maxVal / IntegerT{2} + IntegerT{28}; - assert(std::mul_sat(x, y) == maxVal); // saturated + assert(std::saturating_mul(x, y) == maxVal); // saturated } // clang-format on @@ -101,44 +101,44 @@ constexpr bool test_unsigned() { constexpr auto minVal = std::numeric_limits::min(); constexpr auto maxVal = std::numeric_limits::max(); - std::same_as decltype(auto) _ = std::mul_sat(minVal, maxVal); + std::same_as decltype(auto) _ = std::saturating_mul(minVal, maxVal); - static_assert(noexcept(std::mul_sat(minVal, maxVal))); + static_assert(noexcept(std::saturating_mul(minVal, maxVal))); // clang-format off // No saturation (0, 1) - assert(std::mul_sat(IntegerT{0}, IntegerT{0}) == IntegerT{0}); - assert(std::mul_sat(IntegerT{0}, IntegerT{1}) == IntegerT{0}); - assert(std::mul_sat(IntegerT{0}, minVal) == IntegerT{0}); - assert(std::mul_sat(IntegerT{0}, maxVal) == IntegerT{0}); + assert(std::saturating_mul(IntegerT{0}, IntegerT{0}) == IntegerT{0}); + assert(std::saturating_mul(IntegerT{0}, IntegerT{1}) == IntegerT{0}); + assert(std::saturating_mul(IntegerT{0}, minVal) == IntegerT{0}); + assert(std::saturating_mul(IntegerT{0}, maxVal) == IntegerT{0}); - assert(std::mul_sat(IntegerT{1}, IntegerT{0}) == IntegerT{0}); - assert(std::mul_sat(IntegerT{1}, IntegerT{1}) == IntegerT{1}); - assert(std::mul_sat(IntegerT{1}, minVal) == minVal); - assert(std::mul_sat(IntegerT{1}, maxVal) == maxVal); + assert(std::saturating_mul(IntegerT{1}, IntegerT{0}) == IntegerT{0}); + assert(std::saturating_mul(IntegerT{1}, IntegerT{1}) == IntegerT{1}); + assert(std::saturating_mul(IntegerT{1}, minVal) == minVal); + assert(std::saturating_mul(IntegerT{1}, maxVal) == maxVal); - assert(std::mul_sat( minVal, IntegerT{0}) == IntegerT{0}); - assert(std::mul_sat( minVal, IntegerT{1}) == minVal); - assert(std::mul_sat( minVal, maxVal) == minVal); - assert(std::mul_sat( minVal, maxVal) == minVal); + assert(std::saturating_mul( minVal, IntegerT{0}) == IntegerT{0}); + assert(std::saturating_mul( minVal, IntegerT{1}) == minVal); + assert(std::saturating_mul( minVal, maxVal) == minVal); + assert(std::saturating_mul( minVal, maxVal) == minVal); - assert(std::mul_sat( maxVal, IntegerT{0}) == IntegerT{0}); - assert(std::mul_sat( maxVal, IntegerT{1}) == maxVal); - assert(std::mul_sat( maxVal, minVal) == IntegerT{0}); - assert(std::mul_sat( maxVal, maxVal) == maxVal); // saturated + assert(std::saturating_mul( maxVal, IntegerT{0}) == IntegerT{0}); + assert(std::saturating_mul( maxVal, IntegerT{1}) == maxVal); + assert(std::saturating_mul( maxVal, minVal) == IntegerT{0}); + assert(std::saturating_mul( maxVal, maxVal) == maxVal); // saturated // No saturation (no limit values) - assert(std::mul_sat(IntegerT{28}, IntegerT{2}) == IntegerT{56}); + assert(std::saturating_mul(IntegerT{28}, IntegerT{2}) == IntegerT{56}); // Saturation (no limit values { constexpr IntegerT x = maxVal / IntegerT{2} + IntegerT{27}; constexpr IntegerT y = maxVal / IntegerT{2} + IntegerT{28}; - assert(std::mul_sat(x, y) == maxVal); // saturated + assert(std::saturating_mul(x, y) == maxVal); // saturated } // clang-format on diff --git a/libcxx/test/std/numerics/numeric.ops/numeric.ops.sat/saturate_cast.compile.pass.cpp b/libcxx/test/std/numerics/numeric.ops/numeric.ops.sat/saturate_cast.compile.pass.cpp index 237deb0c7c138..b8d015811798b 100644 --- a/libcxx/test/std/numerics/numeric.ops/numeric.ops.sat/saturate_cast.compile.pass.cpp +++ b/libcxx/test/std/numerics/numeric.ops/numeric.ops.sat/saturate_cast.compile.pass.cpp @@ -11,7 +11,7 @@ // // template -// constexpr R saturate_cast(T x) noexcept; // freestanding +// constexpr R saturating_cast(T x) noexcept; // freestanding #include #include @@ -20,7 +20,7 @@ template concept CanDo = requires(T x) { - { std::saturate_cast(x) } -> std::same_as; + { std::saturating_cast(x) } -> std::same_as; }; template diff --git a/libcxx/test/std/numerics/numeric.ops/numeric.ops.sat/saturate_cast.pass.cpp b/libcxx/test/std/numerics/numeric.ops/numeric.ops.sat/saturate_cast.pass.cpp index 86e2e61647be8..2fcf888e084a1 100644 --- a/libcxx/test/std/numerics/numeric.ops/numeric.ops.sat/saturate_cast.pass.cpp +++ b/libcxx/test/std/numerics/numeric.ops/numeric.ops.sat/saturate_cast.pass.cpp @@ -11,7 +11,7 @@ // // template -// constexpr R saturate_cast(T x) noexcept; // freestanding +// constexpr R saturating_cast(T x) noexcept; // freestanding #include #include @@ -22,22 +22,22 @@ #include "test_macros.h" // Smaller to larger -static_assert(noexcept(std::saturate_cast(std::numeric_limits::max()))); -static_assert(noexcept(std::saturate_cast(std::numeric_limits::max()))); +static_assert(noexcept(std::saturating_cast(std::numeric_limits::max()))); +static_assert(noexcept(std::saturating_cast(std::numeric_limits::max()))); -static_assert(noexcept(std::saturate_cast(std::numeric_limits::max()))); -static_assert(noexcept(std::saturate_cast(std::numeric_limits::max()))); +static_assert(noexcept(std::saturating_cast(std::numeric_limits::max()))); +static_assert(noexcept(std::saturating_cast(std::numeric_limits::max()))); // Same type -static_assert(noexcept(std::saturate_cast(std::numeric_limits::max()))); -static_assert(noexcept(std::saturate_cast(std::numeric_limits::max()))); +static_assert(noexcept(std::saturating_cast(std::numeric_limits::max()))); +static_assert(noexcept(std::saturating_cast(std::numeric_limits::max()))); // Larger to smaller -static_assert(noexcept(std::saturate_cast(std::numeric_limits::max()))); -static_assert(noexcept(std::saturate_cast(std::numeric_limits::max()))); +static_assert(noexcept(std::saturating_cast(std::numeric_limits::max()))); +static_assert(noexcept(std::saturating_cast(std::numeric_limits::max()))); -static_assert(noexcept(std::saturate_cast(std::numeric_limits::max()))); -static_assert(noexcept(std::saturate_cast(std::numeric_limits::max()))); +static_assert(noexcept(std::saturating_cast(std::numeric_limits::max()))); +static_assert(noexcept(std::saturating_cast(std::numeric_limits::max()))); // Tests @@ -71,314 +71,314 @@ constexpr bool test() { // signed char - std::same_as decltype(auto) _ = std::saturate_cast(SCHAR_MAX); - assert(std::saturate_cast(SCHAR_MIN) == SCHAR_MIN); - assert(std::saturate_cast( O_C) == O_C); - assert(std::saturate_cast(SCHAR_MAX) == SCHAR_MAX); + std::same_as decltype(auto) _ = std::saturating_cast(SCHAR_MAX); + assert(std::saturating_cast(SCHAR_MIN) == SCHAR_MIN); + assert(std::saturating_cast( O_C) == O_C); + assert(std::saturating_cast(SCHAR_MAX) == SCHAR_MAX); - std::same_as decltype(auto) _ = std::saturate_cast(UCHAR_MAX); - assert(std::saturate_cast( O_UC) == O_C); - assert(std::saturate_cast(UCHAR_MAX) == SCHAR_MAX); + std::same_as decltype(auto) _ = std::saturating_cast(UCHAR_MAX); + assert(std::saturating_cast( O_UC) == O_C); + assert(std::saturating_cast(UCHAR_MAX) == SCHAR_MAX); - std::same_as decltype(auto) _ = std::saturate_cast(sBigMax); - assert(std::saturate_cast(sBigMin) == SCHAR_MIN); // saturated - assert(std::saturate_cast( sZero) == O_C); - assert(std::saturate_cast(sBigMax) == SCHAR_MAX); // saturated + std::same_as decltype(auto) _ = std::saturating_cast(sBigMax); + assert(std::saturating_cast(sBigMin) == SCHAR_MIN); // saturated + assert(std::saturating_cast( sZero) == O_C); + assert(std::saturating_cast(sBigMax) == SCHAR_MAX); // saturated - std::same_as decltype(auto) _ = std::saturate_cast(uBigMax); - assert(std::saturate_cast( uZero) == O_C); - assert(std::saturate_cast(uBigMax) == SCHAR_MAX); // saturated + std::same_as decltype(auto) _ = std::saturating_cast(uBigMax); + assert(std::saturating_cast( uZero) == O_C); + assert(std::saturating_cast(uBigMax) == SCHAR_MAX); // saturated // short - std::same_as decltype(auto) _ = std::saturate_cast(SCHAR_MAX); - assert(std::saturate_cast(SCHAR_MIN) == static_cast(SCHAR_MIN)); - assert(std::saturate_cast( O_C) == O_S); - assert(std::saturate_cast(SCHAR_MAX) == static_cast(SCHAR_MAX)); + std::same_as decltype(auto) _ = std::saturating_cast(SCHAR_MAX); + assert(std::saturating_cast(SCHAR_MIN) == static_cast(SCHAR_MIN)); + assert(std::saturating_cast( O_C) == O_S); + assert(std::saturating_cast(SCHAR_MAX) == static_cast(SCHAR_MAX)); - std::same_as decltype(auto) _ = std::saturate_cast(UCHAR_MAX); - assert(std::saturate_cast( O_UC) == O_S); - assert(std::saturate_cast(UCHAR_MAX) == static_cast(UCHAR_MAX)); + std::same_as decltype(auto) _ = std::saturating_cast(UCHAR_MAX); + assert(std::saturating_cast( O_UC) == O_S); + assert(std::saturating_cast(UCHAR_MAX) == static_cast(UCHAR_MAX)); - std::same_as decltype(auto) _ = std::saturate_cast(SHRT_MAX); - assert(std::saturate_cast( SHRT_MIN) == SHRT_MIN); - assert(std::saturate_cast( O_S) == O_S); - assert(std::saturate_cast( SHRT_MAX) == SHRT_MAX); + std::same_as decltype(auto) _ = std::saturating_cast(SHRT_MAX); + assert(std::saturating_cast( SHRT_MIN) == SHRT_MIN); + assert(std::saturating_cast( O_S) == O_S); + assert(std::saturating_cast( SHRT_MAX) == SHRT_MAX); - std::same_as decltype(auto) _ = std::saturate_cast(USHRT_MAX); - assert(std::saturate_cast( O_US) == O_S); - assert(std::saturate_cast(USHRT_MAX) == SHRT_MAX); // saturated + std::same_as decltype(auto) _ = std::saturating_cast(USHRT_MAX); + assert(std::saturating_cast( O_US) == O_S); + assert(std::saturating_cast(USHRT_MAX) == SHRT_MAX); // saturated - std::same_as decltype(auto) _ = std::saturate_cast(sBigMax); - assert(std::saturate_cast( sBigMin) == SHRT_MIN); // saturated - assert(std::saturate_cast( sZero) == O_S); - assert(std::saturate_cast( sBigMax) == SHRT_MAX); // saturated + std::same_as decltype(auto) _ = std::saturating_cast(sBigMax); + assert(std::saturating_cast( sBigMin) == SHRT_MIN); // saturated + assert(std::saturating_cast( sZero) == O_S); + assert(std::saturating_cast( sBigMax) == SHRT_MAX); // saturated - std::same_as decltype(auto) _ = std::saturate_cast(uBigMax); - assert(std::saturate_cast( uZero) == O_S); - assert(std::saturate_cast( uBigMax) == SHRT_MAX); // saturated + std::same_as decltype(auto) _ = std::saturating_cast(uBigMax); + assert(std::saturating_cast( uZero) == O_S); + assert(std::saturating_cast( uBigMax) == SHRT_MAX); // saturated // int - std::same_as decltype(auto) _ = std::saturate_cast(SCHAR_MAX); - assert(std::saturate_cast(SCHAR_MIN) == static_cast(SCHAR_MIN)); - assert(std::saturate_cast( O_C) == 0); - assert(std::saturate_cast(SCHAR_MAX) == static_cast(SCHAR_MAX)); + std::same_as decltype(auto) _ = std::saturating_cast(SCHAR_MAX); + assert(std::saturating_cast(SCHAR_MIN) == static_cast(SCHAR_MIN)); + assert(std::saturating_cast( O_C) == 0); + assert(std::saturating_cast(SCHAR_MAX) == static_cast(SCHAR_MAX)); - std::same_as decltype(auto) _ = std::saturate_cast(UCHAR_MAX); - assert(std::saturate_cast( O_UC) == 0); - assert(std::saturate_cast(UCHAR_MAX) == static_cast(UCHAR_MAX)); + std::same_as decltype(auto) _ = std::saturating_cast(UCHAR_MAX); + assert(std::saturating_cast( O_UC) == 0); + assert(std::saturating_cast(UCHAR_MAX) == static_cast(UCHAR_MAX)); - std::same_as decltype(auto) _ = std::saturate_cast(INT_MAX); - assert(std::saturate_cast( INT_MIN) == INT_MIN); - assert(std::saturate_cast( 0) == 0); - assert(std::saturate_cast( INT_MAX) == INT_MAX); + std::same_as decltype(auto) _ = std::saturating_cast(INT_MAX); + assert(std::saturating_cast( INT_MIN) == INT_MIN); + assert(std::saturating_cast( 0) == 0); + assert(std::saturating_cast( INT_MAX) == INT_MAX); - std::same_as decltype(auto) _ = std::saturate_cast(UINT_MAX); - assert(std::saturate_cast( 0) == 0); - assert(std::saturate_cast(UINT_MAX) == INT_MAX); // saturated + std::same_as decltype(auto) _ = std::saturating_cast(UINT_MAX); + assert(std::saturating_cast( 0) == 0); + assert(std::saturating_cast(UINT_MAX) == INT_MAX); // saturated - std::same_as decltype(auto) _ = std::saturate_cast(sBigMax); - assert(std::saturate_cast( sBigMin) == INT_MIN); // saturated - assert(std::saturate_cast( sZero) == 0); - assert(std::saturate_cast( sBigMax) == INT_MAX); // saturated + std::same_as decltype(auto) _ = std::saturating_cast(sBigMax); + assert(std::saturating_cast( sBigMin) == INT_MIN); // saturated + assert(std::saturating_cast( sZero) == 0); + assert(std::saturating_cast( sBigMax) == INT_MAX); // saturated - std::same_as decltype(auto) _ = std::saturate_cast(uBigMax); - assert(std::saturate_cast( uZero) == 0); - assert(std::saturate_cast( uBigMax) == INT_MAX); // saturated + std::same_as decltype(auto) _ = std::saturating_cast(uBigMax); + assert(std::saturating_cast( uZero) == 0); + assert(std::saturating_cast( uBigMax) == INT_MAX); // saturated // long - std::same_as decltype(auto) _ = std::saturate_cast(SCHAR_MAX); - assert(std::saturate_cast(SCHAR_MIN) == static_cast(SCHAR_MIN)); - assert(std::saturate_cast( O_C) == 0L); - assert(std::saturate_cast(SCHAR_MAX) == static_cast(SCHAR_MAX)); + std::same_as decltype(auto) _ = std::saturating_cast(SCHAR_MAX); + assert(std::saturating_cast(SCHAR_MIN) == static_cast(SCHAR_MIN)); + assert(std::saturating_cast( O_C) == 0L); + assert(std::saturating_cast(SCHAR_MAX) == static_cast(SCHAR_MAX)); - std::same_as decltype(auto) _ = std::saturate_cast(UCHAR_MAX); - assert(std::saturate_cast( O_UC) == 0L); - assert(std::saturate_cast(UCHAR_MAX) == static_cast(UCHAR_MAX)); + std::same_as decltype(auto) _ = std::saturating_cast(UCHAR_MAX); + assert(std::saturating_cast( O_UC) == 0L); + assert(std::saturating_cast(UCHAR_MAX) == static_cast(UCHAR_MAX)); - std::same_as decltype(auto) _ = std::saturate_cast(LONG_MAX); - assert(std::saturate_cast( LONG_MIN) == LONG_MIN); - assert(std::saturate_cast( 0L) == 0L); - assert(std::saturate_cast( LONG_MAX) == LONG_MAX); + std::same_as decltype(auto) _ = std::saturating_cast(LONG_MAX); + assert(std::saturating_cast( LONG_MIN) == LONG_MIN); + assert(std::saturating_cast( 0L) == 0L); + assert(std::saturating_cast( LONG_MAX) == LONG_MAX); - std::same_as decltype(auto) _ = std::saturate_cast(ULONG_MAX); - assert(std::saturate_cast( 0UL) == 0L); - assert(std::saturate_cast(ULONG_MAX) == LONG_MAX); // saturated + std::same_as decltype(auto) _ = std::saturating_cast(ULONG_MAX); + assert(std::saturating_cast( 0UL) == 0L); + assert(std::saturating_cast(ULONG_MAX) == LONG_MAX); // saturated - std::same_as decltype(auto) _ = std::saturate_cast(sBigMax); - assert(std::saturate_cast( sBigMin) == LONG_MIN); // saturated - assert(std::saturate_cast( sZero) == 0L); - assert(std::saturate_cast( sBigMax) == LONG_MAX); // saturated + std::same_as decltype(auto) _ = std::saturating_cast(sBigMax); + assert(std::saturating_cast( sBigMin) == LONG_MIN); // saturated + assert(std::saturating_cast( sZero) == 0L); + assert(std::saturating_cast( sBigMax) == LONG_MAX); // saturated - std::same_as decltype(auto) _ = std::saturate_cast(uBigMax); - assert(std::saturate_cast( uZero) == 0L); - assert(std::saturate_cast( uBigMax) == LONG_MAX); // saturated + std::same_as decltype(auto) _ = std::saturating_cast(uBigMax); + assert(std::saturating_cast( uZero) == 0L); + assert(std::saturating_cast( uBigMax) == LONG_MAX); // saturated // long long - std::same_as decltype(auto) _ = std::saturate_cast(SCHAR_MAX); - assert(std::saturate_cast(SCHAR_MIN) == static_cast(SCHAR_MIN)); - assert(std::saturate_cast( 0LL) == 0LL); - assert(std::saturate_cast(SCHAR_MAX) == static_cast(SCHAR_MAX)); + std::same_as decltype(auto) _ = std::saturating_cast(SCHAR_MAX); + assert(std::saturating_cast(SCHAR_MIN) == static_cast(SCHAR_MIN)); + assert(std::saturating_cast( 0LL) == 0LL); + assert(std::saturating_cast(SCHAR_MAX) == static_cast(SCHAR_MAX)); - std::same_as decltype(auto) _ = std::saturate_cast(UCHAR_MAX); - assert(std::saturate_cast( O_UC) == 0LL); - assert(std::saturate_cast(UCHAR_MAX) == static_cast(UCHAR_MAX)); + std::same_as decltype(auto) _ = std::saturating_cast(UCHAR_MAX); + assert(std::saturating_cast( O_UC) == 0LL); + assert(std::saturating_cast(UCHAR_MAX) == static_cast(UCHAR_MAX)); - std::same_as decltype(auto) _ = std::saturate_cast(LLONG_MIN); - assert(std::saturate_cast(LLONG_MIN) == LLONG_MIN); - assert(std::saturate_cast( 0LL) == 0LL); - assert(std::saturate_cast(LLONG_MAX) == LLONG_MAX); + std::same_as decltype(auto) _ = std::saturating_cast(LLONG_MIN); + assert(std::saturating_cast(LLONG_MIN) == LLONG_MIN); + assert(std::saturating_cast( 0LL) == 0LL); + assert(std::saturating_cast(LLONG_MAX) == LLONG_MAX); - std::same_as decltype(auto) _ = std::saturate_cast(ULLONG_MAX); - assert(std::saturate_cast( 0ULL) == 0LL); - assert(std::saturate_cast(ULLONG_MAX) == LLONG_MAX); // saturated + std::same_as decltype(auto) _ = std::saturating_cast(ULLONG_MAX); + assert(std::saturating_cast( 0ULL) == 0LL); + assert(std::saturating_cast(ULLONG_MAX) == LLONG_MAX); // saturated #ifndef TEST_HAS_NO_INT128 - std::same_as decltype(auto) _ = std::saturate_cast(sBigMax); - assert(std::saturate_cast( sBigMin) == LLONG_MIN); // (128-bit) saturated - assert(std::saturate_cast( sZero) == 0LL); - assert(std::saturate_cast( sBigMax) == LLONG_MAX); // (128-bit) saturated - - std::same_as decltype(auto) _ = std::saturate_cast(uBigMax); - assert(std::saturate_cast( uZero) == 0LL); - assert(std::saturate_cast( uBigMax) == LLONG_MAX); // (128-bit) saturated - - std::same_as<__int128_t> decltype(auto) _ = std::saturate_cast<__int128_t>(SCHAR_MAX); - assert(std::saturate_cast<__int128_t>(SCHAR_MIN) == static_cast<__int128_t>(SCHAR_MIN)); - assert(std::saturate_cast<__int128_t>( O_C) == sZero); - assert(std::saturate_cast<__int128_t>(SCHAR_MAX) == static_cast<__int128_t>(SCHAR_MAX)); - - std::same_as<__int128_t> decltype(auto) _ = std::saturate_cast<__int128_t>(UCHAR_MAX); - assert(std::saturate_cast<__int128_t>( O_UC) == sZero); - assert(std::saturate_cast<__int128_t>(UCHAR_MAX) == static_cast<__int128_t>(UCHAR_MAX)); - - std::same_as<__int128_t> decltype(auto) _ = std::saturate_cast<__int128_t>(sBigMax); - assert(std::saturate_cast<__int128_t>( sBigMin) == sBigMin); - assert(std::saturate_cast<__int128_t>( sZero) == sZero); - assert(std::saturate_cast<__int128_t>( sBigMax) == sBigMax); - - std::same_as<__int128_t> decltype(auto) _ = std::saturate_cast<__int128_t>(uBigMax); - assert(std::saturate_cast<__int128_t>( uZero) == sZero); - assert(std::saturate_cast<__int128_t>( uBigMax) == sBigMax); // saturated + std::same_as decltype(auto) _ = std::saturating_cast(sBigMax); + assert(std::saturating_cast( sBigMin) == LLONG_MIN); // (128-bit) saturated + assert(std::saturating_cast( sZero) == 0LL); + assert(std::saturating_cast( sBigMax) == LLONG_MAX); // (128-bit) saturated + + std::same_as decltype(auto) _ = std::saturating_cast(uBigMax); + assert(std::saturating_cast( uZero) == 0LL); + assert(std::saturating_cast( uBigMax) == LLONG_MAX); // (128-bit) saturated + + std::same_as<__int128_t> decltype(auto) _ = std::saturating_cast<__int128_t>(SCHAR_MAX); + assert(std::saturating_cast<__int128_t>(SCHAR_MIN) == static_cast<__int128_t>(SCHAR_MIN)); + assert(std::saturating_cast<__int128_t>( O_C) == sZero); + assert(std::saturating_cast<__int128_t>(SCHAR_MAX) == static_cast<__int128_t>(SCHAR_MAX)); + + std::same_as<__int128_t> decltype(auto) _ = std::saturating_cast<__int128_t>(UCHAR_MAX); + assert(std::saturating_cast<__int128_t>( O_UC) == sZero); + assert(std::saturating_cast<__int128_t>(UCHAR_MAX) == static_cast<__int128_t>(UCHAR_MAX)); + + std::same_as<__int128_t> decltype(auto) _ = std::saturating_cast<__int128_t>(sBigMax); + assert(std::saturating_cast<__int128_t>( sBigMin) == sBigMin); + assert(std::saturating_cast<__int128_t>( sZero) == sZero); + assert(std::saturating_cast<__int128_t>( sBigMax) == sBigMax); + + std::same_as<__int128_t> decltype(auto) _ = std::saturating_cast<__int128_t>(uBigMax); + assert(std::saturating_cast<__int128_t>( uZero) == sZero); + assert(std::saturating_cast<__int128_t>( uBigMax) == sBigMax); // saturated #endif // unsigned char - std::same_as decltype(auto) _ = std::saturate_cast(SCHAR_MAX); - assert(std::saturate_cast(SCHAR_MIN) == O_UC); - assert(std::saturate_cast( O_C) == O_UC); - assert(std::saturate_cast(SCHAR_MAX) == static_cast(SCHAR_MAX)); + std::same_as decltype(auto) _ = std::saturating_cast(SCHAR_MAX); + assert(std::saturating_cast(SCHAR_MIN) == O_UC); + assert(std::saturating_cast( O_C) == O_UC); + assert(std::saturating_cast(SCHAR_MAX) == static_cast(SCHAR_MAX)); - std::same_as decltype(auto) _ = std::saturate_cast(UCHAR_MAX); - assert(std::saturate_cast( O_UC) == O_UC); - assert(std::saturate_cast(UCHAR_MAX) == UCHAR_MAX); + std::same_as decltype(auto) _ = std::saturating_cast(UCHAR_MAX); + assert(std::saturating_cast( O_UC) == O_UC); + assert(std::saturating_cast(UCHAR_MAX) == UCHAR_MAX); - std::same_as decltype(auto) _ = std::saturate_cast(sBigMax); - assert(std::saturate_cast( sBigMin) == O_UC); // saturated - assert(std::saturate_cast( sZero) == O_UC); - assert(std::saturate_cast( sBigMax) == UCHAR_MAX); // saturated + std::same_as decltype(auto) _ = std::saturating_cast(sBigMax); + assert(std::saturating_cast( sBigMin) == O_UC); // saturated + assert(std::saturating_cast( sZero) == O_UC); + assert(std::saturating_cast( sBigMax) == UCHAR_MAX); // saturated - std::same_as decltype(auto) _ = std::saturate_cast(uBigMax); - assert(std::saturate_cast( uZero) == O_UC); - assert(std::saturate_cast( uBigMax) == UCHAR_MAX); // saturated + std::same_as decltype(auto) _ = std::saturating_cast(uBigMax); + assert(std::saturating_cast( uZero) == O_UC); + assert(std::saturating_cast( uBigMax) == UCHAR_MAX); // saturated // unsigned short - std::same_as decltype(auto) _ = std::saturate_cast(SCHAR_MAX); - assert(std::saturate_cast(SCHAR_MIN) == O_US); - assert(std::saturate_cast( O_C) == O_US); - assert(std::saturate_cast(SCHAR_MAX) == static_cast(SCHAR_MAX)); + std::same_as decltype(auto) _ = std::saturating_cast(SCHAR_MAX); + assert(std::saturating_cast(SCHAR_MIN) == O_US); + assert(std::saturating_cast( O_C) == O_US); + assert(std::saturating_cast(SCHAR_MAX) == static_cast(SCHAR_MAX)); - std::same_as decltype(auto) _ = std::saturate_cast(UCHAR_MAX); - assert(std::saturate_cast( O_UC) == O_US); - assert(std::saturate_cast(UCHAR_MAX) == static_cast(UCHAR_MAX)); + std::same_as decltype(auto) _ = std::saturating_cast(UCHAR_MAX); + assert(std::saturating_cast( O_UC) == O_US); + assert(std::saturating_cast(UCHAR_MAX) == static_cast(UCHAR_MAX)); - std::same_as decltype(auto) _ = std::saturate_cast(SCHAR_MIN); - assert(std::saturate_cast( SHRT_MIN) == O_US); - assert(std::saturate_cast( O_S) == O_US); - assert(std::saturate_cast( SHRT_MAX) == static_cast(SHRT_MAX)); + std::same_as decltype(auto) _ = std::saturating_cast(SCHAR_MIN); + assert(std::saturating_cast( SHRT_MIN) == O_US); + assert(std::saturating_cast( O_S) == O_US); + assert(std::saturating_cast( SHRT_MAX) == static_cast(SHRT_MAX)); - std::same_as decltype(auto) _ = std::saturate_cast(UCHAR_MAX); - assert(std::saturate_cast( O_US) == O_US); - assert(std::saturate_cast(USHRT_MAX) == USHRT_MAX); + std::same_as decltype(auto) _ = std::saturating_cast(UCHAR_MAX); + assert(std::saturating_cast( O_US) == O_US); + assert(std::saturating_cast(USHRT_MAX) == USHRT_MAX); - std::same_as decltype(auto) _ = std::saturate_cast(sBigMax); - assert(std::saturate_cast( sBigMin) == O_US); // saturated - assert(std::saturate_cast( sZero) == O_US); - assert(std::saturate_cast( sBigMax) == USHRT_MAX); // saturated + std::same_as decltype(auto) _ = std::saturating_cast(sBigMax); + assert(std::saturating_cast( sBigMin) == O_US); // saturated + assert(std::saturating_cast( sZero) == O_US); + assert(std::saturating_cast( sBigMax) == USHRT_MAX); // saturated - std::same_as decltype(auto) _ = std::saturate_cast(uBigMax); - assert(std::saturate_cast( uZero) == O_US); - assert(std::saturate_cast( uBigMax) == USHRT_MAX); // saturated + std::same_as decltype(auto) _ = std::saturating_cast(uBigMax); + assert(std::saturating_cast( uZero) == O_US); + assert(std::saturating_cast( uBigMax) == USHRT_MAX); // saturated // unsigned int - std::same_as decltype(auto) _ = std::saturate_cast(SCHAR_MAX); - assert(std::saturate_cast(SCHAR_MIN) == O_US); - assert(std::saturate_cast( O_UC) == 0U); - assert(std::saturate_cast(SCHAR_MAX) == static_cast(SCHAR_MAX)); + std::same_as decltype(auto) _ = std::saturating_cast(SCHAR_MAX); + assert(std::saturating_cast(SCHAR_MIN) == O_US); + assert(std::saturating_cast( O_UC) == 0U); + assert(std::saturating_cast(SCHAR_MAX) == static_cast(SCHAR_MAX)); - std::same_as decltype(auto) _ = std::saturate_cast(UCHAR_MAX); - assert(std::saturate_cast( O_UC) == 0U); - assert(std::saturate_cast(UCHAR_MAX) == static_cast(UCHAR_MAX)); + std::same_as decltype(auto) _ = std::saturating_cast(UCHAR_MAX); + assert(std::saturating_cast( O_UC) == 0U); + assert(std::saturating_cast(UCHAR_MAX) == static_cast(UCHAR_MAX)); - std::same_as decltype(auto) _ = std::saturate_cast(INT_MAX); - assert(std::saturate_cast( INT_MIN) == 0U); - assert(std::saturate_cast( 0) == 0U); - assert(std::saturate_cast( INT_MAX) == static_cast(INT_MAX)); + std::same_as decltype(auto) _ = std::saturating_cast(INT_MAX); + assert(std::saturating_cast( INT_MIN) == 0U); + assert(std::saturating_cast( 0) == 0U); + assert(std::saturating_cast( INT_MAX) == static_cast(INT_MAX)); - std::same_as decltype(auto) _ = std::saturate_cast(UINT_MAX); - assert(std::saturate_cast( 0U) == 0U); - assert(std::saturate_cast( UINT_MAX) == UINT_MAX); + std::same_as decltype(auto) _ = std::saturating_cast(UINT_MAX); + assert(std::saturating_cast( 0U) == 0U); + assert(std::saturating_cast( UINT_MAX) == UINT_MAX); - std::same_as decltype(auto) _ = std::saturate_cast(sBigMax); - assert(std::saturate_cast( sBigMin) == 0U); // saturated - assert(std::saturate_cast( sZero) == 0U); - assert(std::saturate_cast( sBigMax) == UINT_MAX); // saturated + std::same_as decltype(auto) _ = std::saturating_cast(sBigMax); + assert(std::saturating_cast( sBigMin) == 0U); // saturated + assert(std::saturating_cast( sZero) == 0U); + assert(std::saturating_cast( sBigMax) == UINT_MAX); // saturated - std::same_as decltype(auto) _ = std::saturate_cast(uBigMax); - assert(std::saturate_cast( uZero) == 0U); - assert(std::saturate_cast( uBigMax) == UINT_MAX); // saturated + std::same_as decltype(auto) _ = std::saturating_cast(uBigMax); + assert(std::saturating_cast( uZero) == 0U); + assert(std::saturating_cast( uBigMax) == UINT_MAX); // saturated // unsigned long - std::same_as decltype(auto) _ = std::saturate_cast(SCHAR_MAX); - assert(std::saturate_cast(SCHAR_MIN) == 0UL); - assert(std::saturate_cast( O_C) == 0UL); - assert(std::saturate_cast(SCHAR_MAX) == static_cast(SCHAR_MAX)); + std::same_as decltype(auto) _ = std::saturating_cast(SCHAR_MAX); + assert(std::saturating_cast(SCHAR_MIN) == 0UL); + assert(std::saturating_cast( O_C) == 0UL); + assert(std::saturating_cast(SCHAR_MAX) == static_cast(SCHAR_MAX)); - std::same_as decltype(auto) _ = std::saturate_cast(UCHAR_MAX); - assert(std::saturate_cast( O_UC) == 0UL); - assert(std::saturate_cast(UCHAR_MAX) == static_cast(UCHAR_MAX)); + std::same_as decltype(auto) _ = std::saturating_cast(UCHAR_MAX); + assert(std::saturating_cast( O_UC) == 0UL); + assert(std::saturating_cast(UCHAR_MAX) == static_cast(UCHAR_MAX)); - std::same_as decltype(auto) _ = std::saturate_cast(LONG_MAX); - assert(std::saturate_cast( LONG_MIN) == 0UL); - assert(std::saturate_cast( 0L) == 0UL); - assert(std::saturate_cast( LONG_MAX) == static_cast(LONG_MAX)); + std::same_as decltype(auto) _ = std::saturating_cast(LONG_MAX); + assert(std::saturating_cast( LONG_MIN) == 0UL); + assert(std::saturating_cast( 0L) == 0UL); + assert(std::saturating_cast( LONG_MAX) == static_cast(LONG_MAX)); - std::same_as decltype(auto) _ = std::saturate_cast(ULONG_MAX); - assert(std::saturate_cast( 0UL) == 0UL); - assert(std::saturate_cast(ULONG_MAX) == ULONG_MAX); + std::same_as decltype(auto) _ = std::saturating_cast(ULONG_MAX); + assert(std::saturating_cast( 0UL) == 0UL); + assert(std::saturating_cast(ULONG_MAX) == ULONG_MAX); - std::same_as decltype(auto) _ = std::saturate_cast(sBigMax); - assert(std::saturate_cast( sBigMin) == 0UL); // saturated - assert(std::saturate_cast( sZero) == 0UL); - assert(std::saturate_cast( sBigMax) == (sizeof(UIntT) > sizeof(unsigned long int) ? ULONG_MAX : LONG_MAX)); // saturated depending on underlying types + std::same_as decltype(auto) _ = std::saturating_cast(sBigMax); + assert(std::saturating_cast( sBigMin) == 0UL); // saturated + assert(std::saturating_cast( sZero) == 0UL); + assert(std::saturating_cast( sBigMax) == (sizeof(UIntT) > sizeof(unsigned long int) ? ULONG_MAX : LONG_MAX)); // saturated depending on underlying types - std::same_as decltype(auto) _ = std::saturate_cast(uBigMax); - assert(std::saturate_cast( uZero) == 0UL); - assert(std::saturate_cast( uBigMax) == ULONG_MAX); // saturated + std::same_as decltype(auto) _ = std::saturating_cast(uBigMax); + assert(std::saturating_cast( uZero) == 0UL); + assert(std::saturating_cast( uBigMax) == ULONG_MAX); // saturated // unsigned long long - std::same_as decltype(auto) _ = std::saturate_cast(SCHAR_MAX); - assert(std::saturate_cast( SCHAR_MIN) == 0ULL); - assert(std::saturate_cast( O_C) == 0ULL); - assert(std::saturate_cast( SCHAR_MAX) == static_cast(SCHAR_MAX)); + std::same_as decltype(auto) _ = std::saturating_cast(SCHAR_MAX); + assert(std::saturating_cast( SCHAR_MIN) == 0ULL); + assert(std::saturating_cast( O_C) == 0ULL); + assert(std::saturating_cast( SCHAR_MAX) == static_cast(SCHAR_MAX)); - std::same_as decltype(auto) _ = std::saturate_cast(UCHAR_MAX); - assert(std::saturate_cast( O_UC) == 0ULL); - assert(std::saturate_cast( UCHAR_MAX) == static_cast(UCHAR_MAX)); + std::same_as decltype(auto) _ = std::saturating_cast(UCHAR_MAX); + assert(std::saturating_cast( O_UC) == 0ULL); + assert(std::saturating_cast( UCHAR_MAX) == static_cast(UCHAR_MAX)); - std::same_as decltype(auto) _ = std::saturate_cast(LLONG_MAX); - assert(std::saturate_cast( LLONG_MIN) == 0ULL); - assert(std::saturate_cast( 0LL) == 0ULL); - assert(std::saturate_cast( LLONG_MAX) == static_cast(LLONG_MAX)); + std::same_as decltype(auto) _ = std::saturating_cast(LLONG_MAX); + assert(std::saturating_cast( LLONG_MIN) == 0ULL); + assert(std::saturating_cast( 0LL) == 0ULL); + assert(std::saturating_cast( LLONG_MAX) == static_cast(LLONG_MAX)); - std::same_as decltype(auto) _ = std::saturate_cast(ULLONG_MAX); - assert(std::saturate_cast( 0ULL) == 0ULL); - assert(std::saturate_cast(ULLONG_MAX) == ULLONG_MAX); + std::same_as decltype(auto) _ = std::saturating_cast(ULLONG_MAX); + assert(std::saturating_cast( 0ULL) == 0ULL); + assert(std::saturating_cast(ULLONG_MAX) == ULLONG_MAX); #ifndef TEST_HAS_NO_INT128 - std::same_as decltype(auto) _ = std::saturate_cast(sBigMax); - assert(std::saturate_cast( sBigMin) == 0ULL); // (128-bit) saturated - assert(std::saturate_cast( sZero) == 0ULL); - assert(std::saturate_cast( sBigMax) == ULLONG_MAX); // (128-bit) saturated - - std::same_as decltype(auto) _ = std::saturate_cast(uBigMax); - assert(std::saturate_cast( uZero) == 0ULL); - assert(std::saturate_cast( uBigMax) == ULLONG_MAX); // (128-bit) saturated - - std::same_as<__uint128_t> decltype(auto) _ = std::saturate_cast<__uint128_t>(SCHAR_MIN); - assert(std::saturate_cast<__uint128_t>(SCHAR_MIN) == uZero); - assert(std::saturate_cast<__uint128_t>( O_C) == uZero); - assert(std::saturate_cast<__uint128_t>(SCHAR_MAX) == static_cast<__uint128_t>(SCHAR_MAX)); - - std::same_as<__uint128_t> decltype(auto) _ = std::saturate_cast<__uint128_t>(UCHAR_MAX); - assert(std::saturate_cast<__uint128_t>( O_UC) == uZero); - assert(std::saturate_cast<__uint128_t>(UCHAR_MAX) == static_cast<__uint128_t>(UCHAR_MAX)); - - std::same_as<__uint128_t> decltype(auto) _ = std::saturate_cast<__uint128_t>(sBigMax); - assert(std::saturate_cast<__uint128_t>( sBigMin) == uZero); // saturated - assert(std::saturate_cast<__uint128_t>( sZero) == uZero); - assert(std::saturate_cast<__uint128_t>( sBigMax) == static_cast<__uint128_t>(sBigMax)); - - std::same_as<__uint128_t> decltype(auto) _ = std::saturate_cast<__uint128_t>(uBigMax); - assert(std::saturate_cast<__uint128_t>( uZero) == uZero); - assert(std::saturate_cast<__uint128_t>( uBigMax) == uBigMax); + std::same_as decltype(auto) _ = std::saturating_cast(sBigMax); + assert(std::saturating_cast( sBigMin) == 0ULL); // (128-bit) saturated + assert(std::saturating_cast( sZero) == 0ULL); + assert(std::saturating_cast( sBigMax) == ULLONG_MAX); // (128-bit) saturated + + std::same_as decltype(auto) _ = std::saturating_cast(uBigMax); + assert(std::saturating_cast( uZero) == 0ULL); + assert(std::saturating_cast( uBigMax) == ULLONG_MAX); // (128-bit) saturated + + std::same_as<__uint128_t> decltype(auto) _ = std::saturating_cast<__uint128_t>(SCHAR_MIN); + assert(std::saturating_cast<__uint128_t>(SCHAR_MIN) == uZero); + assert(std::saturating_cast<__uint128_t>( O_C) == uZero); + assert(std::saturating_cast<__uint128_t>(SCHAR_MAX) == static_cast<__uint128_t>(SCHAR_MAX)); + + std::same_as<__uint128_t> decltype(auto) _ = std::saturating_cast<__uint128_t>(UCHAR_MAX); + assert(std::saturating_cast<__uint128_t>( O_UC) == uZero); + assert(std::saturating_cast<__uint128_t>(UCHAR_MAX) == static_cast<__uint128_t>(UCHAR_MAX)); + + std::same_as<__uint128_t> decltype(auto) _ = std::saturating_cast<__uint128_t>(sBigMax); + assert(std::saturating_cast<__uint128_t>( sBigMin) == uZero); // saturated + assert(std::saturating_cast<__uint128_t>( sZero) == uZero); + assert(std::saturating_cast<__uint128_t>( sBigMax) == static_cast<__uint128_t>(sBigMax)); + + std::same_as<__uint128_t> decltype(auto) _ = std::saturating_cast<__uint128_t>(uBigMax); + assert(std::saturating_cast<__uint128_t>( uZero) == uZero); + assert(std::saturating_cast<__uint128_t>( uBigMax) == uBigMax); #endif // clang-format on diff --git a/libcxx/test/std/numerics/numeric.ops/numeric.ops.sat/sub_sat.compile.pass.cpp b/libcxx/test/std/numerics/numeric.ops/numeric.ops.sat/sub_sat.compile.pass.cpp index 453b9b3600f8a..9676d29b2c32c 100644 --- a/libcxx/test/std/numerics/numeric.ops/numeric.ops.sat/sub_sat.compile.pass.cpp +++ b/libcxx/test/std/numerics/numeric.ops/numeric.ops.sat/sub_sat.compile.pass.cpp @@ -11,7 +11,7 @@ // // template -// constexpr T sub_sat(T x, T y) noexcept; // freestanding +// constexpr T saturating_sub(T x, T y) noexcept; // freestanding #include #include @@ -20,7 +20,7 @@ template concept CanDo = requires(T x, U y) { - { std::sub_sat(x, y) } -> std::same_as; + { std::saturating_sub(x, y) } -> std::same_as; }; template diff --git a/libcxx/test/std/numerics/numeric.ops/numeric.ops.sat/sub_sat.pass.cpp b/libcxx/test/std/numerics/numeric.ops/numeric.ops.sat/sub_sat.pass.cpp index c2be8c5a47bdf..15659057ae45a 100644 --- a/libcxx/test/std/numerics/numeric.ops/numeric.ops.sat/sub_sat.pass.cpp +++ b/libcxx/test/std/numerics/numeric.ops/numeric.ops.sat/sub_sat.pass.cpp @@ -11,7 +11,7 @@ // // template -// constexpr T sub_sat(T x, T y) noexcept; // freestanding +// constexpr T saturating_sub(T x, T y) noexcept; // freestanding #include #include @@ -25,56 +25,56 @@ constexpr bool test_signed() { constexpr auto minVal = std::numeric_limits::min(); constexpr auto maxVal = std::numeric_limits::max(); - std::same_as decltype(auto) _ = std::sub_sat(minVal, maxVal); + std::same_as decltype(auto) _ = std::saturating_sub(minVal, maxVal); - static_assert(noexcept(std::sub_sat(minVal, maxVal))); + static_assert(noexcept(std::saturating_sub(minVal, maxVal))); // clang-format off // Limit values (-1, 0, 1, min, max) - assert(std::sub_sat(IntegerT{-1}, IntegerT{-1}) == IntegerT{ 0}); - assert(std::sub_sat(IntegerT{-1}, IntegerT{ 0}) == IntegerT{-1}); - assert(std::sub_sat(IntegerT{-1}, IntegerT{ 1}) == IntegerT{-2}); - assert(std::sub_sat(IntegerT{-1}, minVal) == IntegerT{-1} - minVal); - assert(std::sub_sat(IntegerT{-1}, maxVal) == IntegerT{-1} - maxVal); - - assert(std::sub_sat(IntegerT{ 0}, IntegerT{-1}) == IntegerT{ 1}); - assert(std::sub_sat(IntegerT{ 0}, IntegerT{ 0}) == IntegerT{ 0}); - assert(std::sub_sat(IntegerT{ 0}, IntegerT{ 1}) == IntegerT{-1}); - assert(std::sub_sat(IntegerT{ 0}, minVal) == maxVal); // saturated - assert(std::sub_sat(IntegerT{ 0}, maxVal) == -maxVal); - - assert(std::sub_sat( minVal, IntegerT{-1}) == minVal - IntegerT{-1}); - assert(std::sub_sat( minVal, IntegerT{ 0}) == minVal); - assert(std::sub_sat( minVal, IntegerT{ 1}) == minVal); // saturated - assert(std::sub_sat( minVal, minVal) == IntegerT{0}); - assert(std::sub_sat( minVal, maxVal) == minVal); // saturated - - assert(std::sub_sat( maxVal, IntegerT{-1}) == maxVal); // saturated - assert(std::sub_sat( maxVal, IntegerT{ 0}) == maxVal); - assert(std::sub_sat( maxVal, IntegerT{ 1}) == maxVal - IntegerT{ 1}); - assert(std::sub_sat( maxVal, minVal) == maxVal); // saturated - assert(std::sub_sat( maxVal, maxVal) == IntegerT{0}); + assert(std::saturating_sub(IntegerT{-1}, IntegerT{-1}) == IntegerT{ 0}); + assert(std::saturating_sub(IntegerT{-1}, IntegerT{ 0}) == IntegerT{-1}); + assert(std::saturating_sub(IntegerT{-1}, IntegerT{ 1}) == IntegerT{-2}); + assert(std::saturating_sub(IntegerT{-1}, minVal) == IntegerT{-1} - minVal); + assert(std::saturating_sub(IntegerT{-1}, maxVal) == IntegerT{-1} - maxVal); + + assert(std::saturating_sub(IntegerT{ 0}, IntegerT{-1}) == IntegerT{ 1}); + assert(std::saturating_sub(IntegerT{ 0}, IntegerT{ 0}) == IntegerT{ 0}); + assert(std::saturating_sub(IntegerT{ 0}, IntegerT{ 1}) == IntegerT{-1}); + assert(std::saturating_sub(IntegerT{ 0}, minVal) == maxVal); // saturated + assert(std::saturating_sub(IntegerT{ 0}, maxVal) == -maxVal); + + assert(std::saturating_sub( minVal, IntegerT{-1}) == minVal - IntegerT{-1}); + assert(std::saturating_sub( minVal, IntegerT{ 0}) == minVal); + assert(std::saturating_sub( minVal, IntegerT{ 1}) == minVal); // saturated + assert(std::saturating_sub( minVal, minVal) == IntegerT{0}); + assert(std::saturating_sub( minVal, maxVal) == minVal); // saturated + + assert(std::saturating_sub( maxVal, IntegerT{-1}) == maxVal); // saturated + assert(std::saturating_sub( maxVal, IntegerT{ 0}) == maxVal); + assert(std::saturating_sub( maxVal, IntegerT{ 1}) == maxVal - IntegerT{ 1}); + assert(std::saturating_sub( maxVal, minVal) == maxVal); // saturated + assert(std::saturating_sub( maxVal, maxVal) == IntegerT{0}); // No saturation (no limit values) - assert(std::sub_sat(IntegerT{ 27}, IntegerT{-28}) == 55); - assert(std::sub_sat(IntegerT{ 27}, IntegerT{ 28}) == -1); - assert(std::sub_sat(IntegerT{-27}, IntegerT{ 28}) == -55); - assert(std::sub_sat(IntegerT{-27}, IntegerT{-28}) == 1); + assert(std::saturating_sub(IntegerT{ 27}, IntegerT{-28}) == 55); + assert(std::saturating_sub(IntegerT{ 27}, IntegerT{ 28}) == -1); + assert(std::saturating_sub(IntegerT{-27}, IntegerT{ 28}) == -55); + assert(std::saturating_sub(IntegerT{-27}, IntegerT{-28}) == 1); // Saturation (no limit values) { constexpr IntegerT lesserVal = minVal / IntegerT{2} + IntegerT{27}; constexpr IntegerT biggerVal = maxVal / IntegerT{2} + IntegerT{28}; - assert(std::sub_sat(lesserVal, biggerVal) == minVal); // saturated + assert(std::saturating_sub(lesserVal, biggerVal) == minVal); // saturated } { constexpr IntegerT biggerVal = maxVal / IntegerT{2} + IntegerT{28}; constexpr IntegerT lesserVal = minVal / IntegerT{2} + IntegerT{27}; - assert(std::sub_sat(biggerVal, lesserVal) == maxVal); // saturated + assert(std::saturating_sub(biggerVal, lesserVal) == maxVal); // saturated } // clang-format on @@ -87,40 +87,40 @@ constexpr bool test_unsigned() { constexpr auto minVal = std::numeric_limits::min(); constexpr auto maxVal = std::numeric_limits::max(); - std::same_as decltype(auto) _ = std::sub_sat(minVal, maxVal); + std::same_as decltype(auto) _ = std::saturating_sub(minVal, maxVal); - static_assert(noexcept(std::sub_sat(minVal, maxVal))); + static_assert(noexcept(std::saturating_sub(minVal, maxVal))); // clang-format off // Limit values (0, 1, min, max) - assert(std::sub_sat(IntegerT{0}, IntegerT{0}) == IntegerT{0}); - assert(std::sub_sat(IntegerT{0}, IntegerT{1}) == minVal); // saturated - assert(std::sub_sat(IntegerT{0}, minVal) == minVal); - assert(std::sub_sat(IntegerT{0}, maxVal) == minVal); // saturated + assert(std::saturating_sub(IntegerT{0}, IntegerT{0}) == IntegerT{0}); + assert(std::saturating_sub(IntegerT{0}, IntegerT{1}) == minVal); // saturated + assert(std::saturating_sub(IntegerT{0}, minVal) == minVal); + assert(std::saturating_sub(IntegerT{0}, maxVal) == minVal); // saturated - assert(std::sub_sat(IntegerT{1}, IntegerT{0}) == IntegerT{1}); - assert(std::sub_sat(IntegerT{1}, IntegerT{1}) == IntegerT{0}); - assert(std::sub_sat(IntegerT{1}, minVal) == IntegerT{1}); - assert(std::sub_sat(IntegerT{1}, maxVal) == minVal); // saturated + assert(std::saturating_sub(IntegerT{1}, IntegerT{0}) == IntegerT{1}); + assert(std::saturating_sub(IntegerT{1}, IntegerT{1}) == IntegerT{0}); + assert(std::saturating_sub(IntegerT{1}, minVal) == IntegerT{1}); + assert(std::saturating_sub(IntegerT{1}, maxVal) == minVal); // saturated - assert(std::sub_sat( minVal, IntegerT{0}) == IntegerT{0}); - assert(std::sub_sat( minVal, IntegerT{1}) == minVal); - assert(std::sub_sat( minVal, maxVal) == minVal); - assert(std::sub_sat( minVal, maxVal) == minVal); + assert(std::saturating_sub( minVal, IntegerT{0}) == IntegerT{0}); + assert(std::saturating_sub( minVal, IntegerT{1}) == minVal); + assert(std::saturating_sub( minVal, maxVal) == minVal); + assert(std::saturating_sub( minVal, maxVal) == minVal); - assert(std::sub_sat( maxVal, IntegerT{0}) == maxVal); - assert(std::sub_sat( maxVal, IntegerT{1}) == maxVal - IntegerT{1}); - assert(std::sub_sat( maxVal, minVal) == maxVal); - assert(std::sub_sat( maxVal, maxVal) == IntegerT{0}); + assert(std::saturating_sub( maxVal, IntegerT{0}) == maxVal); + assert(std::saturating_sub( maxVal, IntegerT{1}) == maxVal - IntegerT{1}); + assert(std::saturating_sub( maxVal, minVal) == maxVal); + assert(std::saturating_sub( maxVal, maxVal) == IntegerT{0}); // Saturation (no limit values) { constexpr IntegerT lesserVal = minVal / IntegerT{2} + IntegerT{27}; constexpr IntegerT biggerVal = maxVal / IntegerT{2} + IntegerT{28}; - assert(std::sub_sat(lesserVal, biggerVal) == minVal); // saturated + assert(std::saturating_sub(lesserVal, biggerVal) == minVal); // saturated } // clang-format on diff --git a/libcxx/utils/generate_feature_test_macro_components.py b/libcxx/utils/generate_feature_test_macro_components.py index c5f81ca172f5a..812978c8dc4f1 100644 --- a/libcxx/utils/generate_feature_test_macro_components.py +++ b/libcxx/utils/generate_feature_test_macro_components.py @@ -1221,7 +1221,7 @@ def add_version_header(tc): }, { "name": "__cpp_lib_saturation_arithmetic", - "values": {"c++26": 202311}, # P0543R3 Saturation arithmetic + "values": {"c++26": 202603}, # P0543R3 Saturation arithmetic "headers": ["numeric"], }, { From a34d40ce2bdde66e37dd49ce4f888248bd015a2b Mon Sep 17 00:00:00 2001 From: Hristo Hristov Date: Tue, 31 Mar 2026 16:36:06 +0300 Subject: [PATCH 2/7] Renamed test files --- libcxx/include/numeric | 8 ++++---- ...t.compile.pass.cpp => saturating_add.compile.pass.cpp} | 0 .../{add_sat.pass.cpp => saturating_add.pass.cpp} | 0 ....compile.pass.cpp => saturating_cast.compile.pass.cpp} | 0 .../{saturate_cast.pass.cpp => saturating_cast.pass.cpp} | 0 ...sat.assert.pass.cpp => saturating_div.assert.pass.cpp} | 0 ...t.compile.pass.cpp => saturating_div.compile.pass.cpp} | 0 .../{div_sat.pass.cpp => saturating_div.pass.cpp} | 0 ...t.compile.pass.cpp => saturating_mul.compile.pass.cpp} | 0 .../{mul_sat.pass.cpp => saturating_mul.pass.cpp} | 0 ...t.compile.pass.cpp => saturating_sub.compile.pass.cpp} | 0 .../{sub_sat.pass.cpp => saturating_sub.pass.cpp} | 0 12 files changed, 4 insertions(+), 4 deletions(-) rename libcxx/test/std/numerics/numeric.ops/numeric.ops.sat/{add_sat.compile.pass.cpp => saturating_add.compile.pass.cpp} (100%) rename libcxx/test/std/numerics/numeric.ops/numeric.ops.sat/{add_sat.pass.cpp => saturating_add.pass.cpp} (100%) rename libcxx/test/std/numerics/numeric.ops/numeric.ops.sat/{saturate_cast.compile.pass.cpp => saturating_cast.compile.pass.cpp} (100%) rename libcxx/test/std/numerics/numeric.ops/numeric.ops.sat/{saturate_cast.pass.cpp => saturating_cast.pass.cpp} (100%) rename libcxx/test/std/numerics/numeric.ops/numeric.ops.sat/{div_sat.assert.pass.cpp => saturating_div.assert.pass.cpp} (100%) rename libcxx/test/std/numerics/numeric.ops/numeric.ops.sat/{div_sat.compile.pass.cpp => saturating_div.compile.pass.cpp} (100%) rename libcxx/test/std/numerics/numeric.ops/numeric.ops.sat/{div_sat.pass.cpp => saturating_div.pass.cpp} (100%) rename libcxx/test/std/numerics/numeric.ops/numeric.ops.sat/{mul_sat.compile.pass.cpp => saturating_mul.compile.pass.cpp} (100%) rename libcxx/test/std/numerics/numeric.ops/numeric.ops.sat/{mul_sat.pass.cpp => saturating_mul.pass.cpp} (100%) rename libcxx/test/std/numerics/numeric.ops/numeric.ops.sat/{sub_sat.compile.pass.cpp => saturating_sub.compile.pass.cpp} (100%) rename libcxx/test/std/numerics/numeric.ops/numeric.ops.sat/{sub_sat.pass.cpp => saturating_sub.pass.cpp} (100%) diff --git a/libcxx/include/numeric b/libcxx/include/numeric index e490499bdd522..64111b88d3538 100644 --- a/libcxx/include/numeric +++ b/libcxx/include/numeric @@ -142,13 +142,13 @@ template // [numeric.sat], saturation arithmetic template -constexpr T saturating_add(T x, T y) noexcept; // freestanding, Since C++26 +constexpr T saturating_add(T x, T y) noexcept; // freestanding, Since C++26 template -constexpr T saturating_sub(T x, T y) noexcept; // freestanding, Since C++26 +constexpr T saturating_sub(T x, T y) noexcept; // freestanding, Since C++26 template -constexpr T saturating_mul(T x, T y) noexcept; // freestanding, Since C++26 +constexpr T saturating_mul(T x, T y) noexcept; // freestanding, Since C++26 template -constexpr T saturating_div(T x, T y) noexcept; // freestanding, Since C++26 +constexpr T saturating_div(T x, T y) noexcept; // freestanding, Since C++26 template constexpr T saturating_cast(U x) noexcept; // freestanding, Since C++26 diff --git a/libcxx/test/std/numerics/numeric.ops/numeric.ops.sat/add_sat.compile.pass.cpp b/libcxx/test/std/numerics/numeric.ops/numeric.ops.sat/saturating_add.compile.pass.cpp similarity index 100% rename from libcxx/test/std/numerics/numeric.ops/numeric.ops.sat/add_sat.compile.pass.cpp rename to libcxx/test/std/numerics/numeric.ops/numeric.ops.sat/saturating_add.compile.pass.cpp diff --git a/libcxx/test/std/numerics/numeric.ops/numeric.ops.sat/add_sat.pass.cpp b/libcxx/test/std/numerics/numeric.ops/numeric.ops.sat/saturating_add.pass.cpp similarity index 100% rename from libcxx/test/std/numerics/numeric.ops/numeric.ops.sat/add_sat.pass.cpp rename to libcxx/test/std/numerics/numeric.ops/numeric.ops.sat/saturating_add.pass.cpp diff --git a/libcxx/test/std/numerics/numeric.ops/numeric.ops.sat/saturate_cast.compile.pass.cpp b/libcxx/test/std/numerics/numeric.ops/numeric.ops.sat/saturating_cast.compile.pass.cpp similarity index 100% rename from libcxx/test/std/numerics/numeric.ops/numeric.ops.sat/saturate_cast.compile.pass.cpp rename to libcxx/test/std/numerics/numeric.ops/numeric.ops.sat/saturating_cast.compile.pass.cpp diff --git a/libcxx/test/std/numerics/numeric.ops/numeric.ops.sat/saturate_cast.pass.cpp b/libcxx/test/std/numerics/numeric.ops/numeric.ops.sat/saturating_cast.pass.cpp similarity index 100% rename from libcxx/test/std/numerics/numeric.ops/numeric.ops.sat/saturate_cast.pass.cpp rename to libcxx/test/std/numerics/numeric.ops/numeric.ops.sat/saturating_cast.pass.cpp diff --git a/libcxx/test/std/numerics/numeric.ops/numeric.ops.sat/div_sat.assert.pass.cpp b/libcxx/test/std/numerics/numeric.ops/numeric.ops.sat/saturating_div.assert.pass.cpp similarity index 100% rename from libcxx/test/std/numerics/numeric.ops/numeric.ops.sat/div_sat.assert.pass.cpp rename to libcxx/test/std/numerics/numeric.ops/numeric.ops.sat/saturating_div.assert.pass.cpp diff --git a/libcxx/test/std/numerics/numeric.ops/numeric.ops.sat/div_sat.compile.pass.cpp b/libcxx/test/std/numerics/numeric.ops/numeric.ops.sat/saturating_div.compile.pass.cpp similarity index 100% rename from libcxx/test/std/numerics/numeric.ops/numeric.ops.sat/div_sat.compile.pass.cpp rename to libcxx/test/std/numerics/numeric.ops/numeric.ops.sat/saturating_div.compile.pass.cpp diff --git a/libcxx/test/std/numerics/numeric.ops/numeric.ops.sat/div_sat.pass.cpp b/libcxx/test/std/numerics/numeric.ops/numeric.ops.sat/saturating_div.pass.cpp similarity index 100% rename from libcxx/test/std/numerics/numeric.ops/numeric.ops.sat/div_sat.pass.cpp rename to libcxx/test/std/numerics/numeric.ops/numeric.ops.sat/saturating_div.pass.cpp diff --git a/libcxx/test/std/numerics/numeric.ops/numeric.ops.sat/mul_sat.compile.pass.cpp b/libcxx/test/std/numerics/numeric.ops/numeric.ops.sat/saturating_mul.compile.pass.cpp similarity index 100% rename from libcxx/test/std/numerics/numeric.ops/numeric.ops.sat/mul_sat.compile.pass.cpp rename to libcxx/test/std/numerics/numeric.ops/numeric.ops.sat/saturating_mul.compile.pass.cpp diff --git a/libcxx/test/std/numerics/numeric.ops/numeric.ops.sat/mul_sat.pass.cpp b/libcxx/test/std/numerics/numeric.ops/numeric.ops.sat/saturating_mul.pass.cpp similarity index 100% rename from libcxx/test/std/numerics/numeric.ops/numeric.ops.sat/mul_sat.pass.cpp rename to libcxx/test/std/numerics/numeric.ops/numeric.ops.sat/saturating_mul.pass.cpp diff --git a/libcxx/test/std/numerics/numeric.ops/numeric.ops.sat/sub_sat.compile.pass.cpp b/libcxx/test/std/numerics/numeric.ops/numeric.ops.sat/saturating_sub.compile.pass.cpp similarity index 100% rename from libcxx/test/std/numerics/numeric.ops/numeric.ops.sat/sub_sat.compile.pass.cpp rename to libcxx/test/std/numerics/numeric.ops/numeric.ops.sat/saturating_sub.compile.pass.cpp diff --git a/libcxx/test/std/numerics/numeric.ops/numeric.ops.sat/sub_sat.pass.cpp b/libcxx/test/std/numerics/numeric.ops/numeric.ops.sat/saturating_sub.pass.cpp similarity index 100% rename from libcxx/test/std/numerics/numeric.ops/numeric.ops.sat/sub_sat.pass.cpp rename to libcxx/test/std/numerics/numeric.ops/numeric.ops.sat/saturating_sub.pass.cpp From 42e6cb5e5931e2c21ddfde30146b180e648572b6 Mon Sep 17 00:00:00 2001 From: Hristo Hristov Date: Tue, 31 Mar 2026 17:07:24 +0300 Subject: [PATCH 3/7] Update libcxx/docs/ReleaseNotes/23.rst Co-authored-by: A. Jiang --- libcxx/docs/ReleaseNotes/23.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libcxx/docs/ReleaseNotes/23.rst b/libcxx/docs/ReleaseNotes/23.rst index dd5a34e5bb20f..77d977149baf3 100644 --- a/libcxx/docs/ReleaseNotes/23.rst +++ b/libcxx/docs/ReleaseNotes/23.rst @@ -39,7 +39,7 @@ Implemented Papers ------------------ - P2440R1: ``ranges::iota``, ``ranges::shift_left`` and ``ranges::shift_right`` (`Github `__) -- P4052R0: Renaming saturation arithmetic functions +- P4052R0: Renaming saturation arithmetic functions (`Github `__) Improvements and New Features ----------------------------- From 2c299379b34cd31606087030a2290e5716f84195 Mon Sep 17 00:00:00 2001 From: Hristo Hristov Date: Tue, 31 Mar 2026 17:32:50 +0300 Subject: [PATCH 4/7] Update libcxx/test/libcxx/numerics/nodiscard.verify.cpp --- libcxx/test/libcxx/numerics/nodiscard.verify.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libcxx/test/libcxx/numerics/nodiscard.verify.cpp b/libcxx/test/libcxx/numerics/nodiscard.verify.cpp index c3635b8027aee..089ebb73b1502 100644 --- a/libcxx/test/libcxx/numerics/nodiscard.verify.cpp +++ b/libcxx/test/libcxx/numerics/nodiscard.verify.cpp @@ -29,7 +29,7 @@ void test() { std::saturating_sub(94, 82); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} std::saturating_mul(94, 82); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} std::saturating_div(94, 82); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} - std::saturating_cast(49); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} + std::saturating_cast(49); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}} #endif // TEST_STD_VER >= 26 // clang-format on From aee6ee5f4808df9e4d17415aa0ff6e3875004e3e Mon Sep 17 00:00:00 2001 From: Hristo Hristov Date: Wed, 1 Apr 2026 11:05:41 +0300 Subject: [PATCH 5/7] Update libcxx/test/std/numerics/numeric.ops/numeric.ops.sat/saturating_mul.pass.cpp --- .../numeric.ops/numeric.ops.sat/saturating_mul.pass.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libcxx/test/std/numerics/numeric.ops/numeric.ops.sat/saturating_mul.pass.cpp b/libcxx/test/std/numerics/numeric.ops/numeric.ops.sat/saturating_mul.pass.cpp index f98aeaf4dd5a8..3913b7f632e29 100644 --- a/libcxx/test/std/numerics/numeric.ops/numeric.ops.sat/saturating_mul.pass.cpp +++ b/libcxx/test/std/numerics/numeric.ops/numeric.ops.sat/saturating_mul.pass.cpp @@ -133,7 +133,7 @@ constexpr bool test_unsigned() { assert(std::saturating_mul(IntegerT{28}, IntegerT{2}) == IntegerT{56}); - // Saturation (no limit values + // Saturation (no limit values) { constexpr IntegerT x = maxVal / IntegerT{2} + IntegerT{27}; From 6d46c936e37c1a5d4305e9cf134a3137721b226f Mon Sep 17 00:00:00 2001 From: Hristo Hristov Date: Sat, 11 Apr 2026 14:48:11 +0300 Subject: [PATCH 6/7] Mark as DONE --- libcxx/docs/Status/Cxx2cPapers.csv | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libcxx/docs/Status/Cxx2cPapers.csv b/libcxx/docs/Status/Cxx2cPapers.csv index 6eda9128fda48..c2914fcd53035 100644 --- a/libcxx/docs/Status/Cxx2cPapers.csv +++ b/libcxx/docs/Status/Cxx2cPapers.csv @@ -209,7 +209,7 @@ "`P4156R0 `__","Rename meta::has_ellipsis_parameter to meta::is_vararg_function","2026-03 (Croydon)","","","`#189622 `__","" "`P3953R3 `__","Rename ``std::runtime_format``","2026-03 (Croydon)","","","`#189624 `__","" "`P4052R0 `__","Renaming saturation arithmetic functions","2026-03 (Croydon)","","","`#189589 `__","" -"`P3941R4 `__","Scheduler Affinity","2026-03 (Croydon)","","","`#189627 `__","" +"`P3941R4 `__","Scheduler Affinity","2026-03 (Croydon)","|Complete|","23","`#189627 `__","" "`P3856R8 `__","New reflection metafunction - is_structural_type (US NB comment 49)","2026-03 (Croydon)","","","`#189625 `__","" "`P3927R2 `__","``task_scheduler`` support for parallel ``bulk`` execution","2026-03 (Croydon)","","","`#189629 `__","" "`P4151R1 `__","Rename ``affine_on``","2026-03 (Croydon)","","","`#189631 `__","" From ac250f0b53da0b18d4f82c86e9f6831334528e5a Mon Sep 17 00:00:00 2001 From: Hristo Hristov Date: Sat, 11 Apr 2026 14:56:04 +0300 Subject: [PATCH 7/7] Fix status --- libcxx/docs/Status/Cxx2cPapers.csv | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libcxx/docs/Status/Cxx2cPapers.csv b/libcxx/docs/Status/Cxx2cPapers.csv index c2914fcd53035..5806e4cb59ef7 100644 --- a/libcxx/docs/Status/Cxx2cPapers.csv +++ b/libcxx/docs/Status/Cxx2cPapers.csv @@ -208,8 +208,8 @@ "`P3980R1 `__","Task's Allocator Use","2026-03 (Croydon)","","","`#189621 `__","" "`P4156R0 `__","Rename meta::has_ellipsis_parameter to meta::is_vararg_function","2026-03 (Croydon)","","","`#189622 `__","" "`P3953R3 `__","Rename ``std::runtime_format``","2026-03 (Croydon)","","","`#189624 `__","" -"`P4052R0 `__","Renaming saturation arithmetic functions","2026-03 (Croydon)","","","`#189589 `__","" -"`P3941R4 `__","Scheduler Affinity","2026-03 (Croydon)","|Complete|","23","`#189627 `__","" +"`P4052R0 `__","Renaming saturation arithmetic functions","2026-03 (Croydon)","|Complete|","23","`#189589 `__","" +"`P3941R4 `__","Scheduler Affinity","2026-03 (Croydon)","","","`#189627 `__","" "`P3856R8 `__","New reflection metafunction - is_structural_type (US NB comment 49)","2026-03 (Croydon)","","","`#189625 `__","" "`P3927R2 `__","``task_scheduler`` support for parallel ``bulk`` execution","2026-03 (Croydon)","","","`#189629 `__","" "`P4151R1 `__","Rename ``affine_on``","2026-03 (Croydon)","","","`#189631 `__",""