File indexing completed on 2026-05-03 08:13:37
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #ifndef _LIBCPP___CXX03___NUMERIC_SATURATION_ARITHMETIC_H
0011 #define _LIBCPP___CXX03___NUMERIC_SATURATION_ARITHMETIC_H
0012
0013 #include <__cxx03/__assert>
0014 #include <__cxx03/__concepts/arithmetic.h>
0015 #include <__cxx03/__config>
0016 #include <__cxx03/__utility/cmp.h>
0017 #include <__cxx03/limits>
0018
0019 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
0020 # pragma GCC system_header
0021 #endif
0022
0023 _LIBCPP_PUSH_MACROS
0024 #include <__cxx03/__undef_macros>
0025
0026 _LIBCPP_BEGIN_NAMESPACE_STD
0027
0028 #if _LIBCPP_STD_VER >= 20
0029
0030 template <__libcpp_integer _Tp>
0031 _LIBCPP_HIDE_FROM_ABI constexpr _Tp __add_sat(_Tp __x, _Tp __y) noexcept {
0032 if (_Tp __sum; !__builtin_add_overflow(__x, __y, &__sum))
0033 return __sum;
0034
0035 if constexpr (__libcpp_unsigned_integer<_Tp>) {
0036 return std::numeric_limits<_Tp>::max();
0037 } else {
0038
0039 if (__x > 0)
0040
0041 return std::numeric_limits<_Tp>::max();
0042 else
0043
0044 return std::numeric_limits<_Tp>::min();
0045 }
0046 }
0047
0048 template <__libcpp_integer _Tp>
0049 _LIBCPP_HIDE_FROM_ABI constexpr _Tp __sub_sat(_Tp __x, _Tp __y) noexcept {
0050 if (_Tp __sub; !__builtin_sub_overflow(__x, __y, &__sub))
0051 return __sub;
0052
0053 if constexpr (__libcpp_unsigned_integer<_Tp>) {
0054
0055 return std::numeric_limits<_Tp>::min();
0056 } else {
0057
0058 if (__x >= 0)
0059
0060 return std::numeric_limits<_Tp>::max();
0061 else
0062
0063 return std::numeric_limits<_Tp>::min();
0064 }
0065 }
0066
0067 template <__libcpp_integer _Tp>
0068 _LIBCPP_HIDE_FROM_ABI constexpr _Tp __mul_sat(_Tp __x, _Tp __y) noexcept {
0069 if (_Tp __mul; !__builtin_mul_overflow(__x, __y, &__mul))
0070 return __mul;
0071
0072 if constexpr (__libcpp_unsigned_integer<_Tp>) {
0073 return std::numeric_limits<_Tp>::max();
0074 } else {
0075
0076 if ((__x > 0 && __y > 0) || (__x < 0 && __y < 0))
0077 return std::numeric_limits<_Tp>::max();
0078
0079 return std::numeric_limits<_Tp>::min();
0080 }
0081 }
0082
0083 template <__libcpp_integer _Tp>
0084 _LIBCPP_HIDE_FROM_ABI constexpr _Tp __div_sat(_Tp __x, _Tp __y) noexcept {
0085 _LIBCPP_ASSERT_UNCATEGORIZED(__y != 0, "Division by 0 is undefined");
0086 if constexpr (__libcpp_unsigned_integer<_Tp>) {
0087 return __x / __y;
0088 } else {
0089
0090 if (__x == std::numeric_limits<_Tp>::min() && __y == _Tp{-1})
0091 return std::numeric_limits<_Tp>::max();
0092 return __x / __y;
0093 }
0094 }
0095
0096 template <__libcpp_integer _Rp, __libcpp_integer _Tp>
0097 _LIBCPP_HIDE_FROM_ABI constexpr _Rp __saturate_cast(_Tp __x) noexcept {
0098
0099
0100
0101
0102 if (std::cmp_less(__x, std::numeric_limits<_Rp>::min()))
0103 return std::numeric_limits<_Rp>::min();
0104 if (std::cmp_greater(__x, std::numeric_limits<_Rp>::max()))
0105 return std::numeric_limits<_Rp>::max();
0106
0107 return static_cast<_Rp>(__x);
0108 }
0109
0110 #endif
0111
0112 #if _LIBCPP_STD_VER >= 26
0113
0114 template <__libcpp_integer _Tp>
0115 _LIBCPP_HIDE_FROM_ABI constexpr _Tp add_sat(_Tp __x, _Tp __y) noexcept {
0116 return std::__add_sat(__x, __y);
0117 }
0118
0119 template <__libcpp_integer _Tp>
0120 _LIBCPP_HIDE_FROM_ABI constexpr _Tp sub_sat(_Tp __x, _Tp __y) noexcept {
0121 return std::__sub_sat(__x, __y);
0122 }
0123
0124 template <__libcpp_integer _Tp>
0125 _LIBCPP_HIDE_FROM_ABI constexpr _Tp mul_sat(_Tp __x, _Tp __y) noexcept {
0126 return std::__mul_sat(__x, __y);
0127 }
0128
0129 template <__libcpp_integer _Tp>
0130 _LIBCPP_HIDE_FROM_ABI constexpr _Tp div_sat(_Tp __x, _Tp __y) noexcept {
0131 return std::__div_sat(__x, __y);
0132 }
0133
0134 template <__libcpp_integer _Rp, __libcpp_integer _Tp>
0135 _LIBCPP_HIDE_FROM_ABI constexpr _Rp saturate_cast(_Tp __x) noexcept {
0136 return std::__saturate_cast<_Rp>(__x);
0137 }
0138
0139 #endif
0140
0141 _LIBCPP_END_NAMESPACE_STD
0142
0143 _LIBCPP_POP_MACROS
0144
0145 #endif