Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-03 08:13:37

0001 // -*- C++ -*-
0002 //===----------------------------------------------------------------------===//
0003 //
0004 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
0005 // See https://llvm.org/LICENSE.txt for license information.
0006 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
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   // Handle overflow
0035   if constexpr (__libcpp_unsigned_integer<_Tp>) {
0036     return std::numeric_limits<_Tp>::max();
0037   } else {
0038     // Signed addition overflow
0039     if (__x > 0)
0040       // Overflows if (x > 0 && y > 0)
0041       return std::numeric_limits<_Tp>::max();
0042     else
0043       // Overflows if  (x < 0 && y < 0)
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   // Handle overflow
0053   if constexpr (__libcpp_unsigned_integer<_Tp>) {
0054     // Overflows if (x < y)
0055     return std::numeric_limits<_Tp>::min();
0056   } else {
0057     // Signed subtration overflow
0058     if (__x >= 0)
0059       // Overflows if (x >= 0 && y < 0)
0060       return std::numeric_limits<_Tp>::max();
0061     else
0062       // Overflows if (x < 0 && y > 0)
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   // Handle overflow
0072   if constexpr (__libcpp_unsigned_integer<_Tp>) {
0073     return std::numeric_limits<_Tp>::max();
0074   } else {
0075     // Signed multiplication overflow
0076     if ((__x > 0 && __y > 0) || (__x < 0 && __y < 0))
0077       return std::numeric_limits<_Tp>::max();
0078     // Overflows if (x < 0 && y > 0) || (x > 0 && y < 0)
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     // Handle signed division overflow
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   // Saturation is impossible edge case when ((min _Rp) < (min _Tp) && (max _Rp) > (max _Tp)) and it is expected to be
0099   // optimized out by the compiler.
0100 
0101   // Handle overflow
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   // No overflow
0107   return static_cast<_Rp>(__x);
0108 }
0109 
0110 #endif // _LIBCPP_STD_VER >= 20
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 // _LIBCPP_STD_VER >= 26
0140 
0141 _LIBCPP_END_NAMESPACE_STD
0142 
0143 _LIBCPP_POP_MACROS
0144 
0145 #endif // _LIBCPP___CXX03___NUMERIC_SATURATION_ARITHMETIC_H