Where Online Learning is simpler!
The C and C++ Include Header Files
cat -n /usr/include/c++/15/bits/sat_arith.h
1 // Saturation arithmetic -*- C++ -*- 2 3 // Copyright The GNU Toolchain Authors. 4 // 5 // This file is part of the GNU ISO C++ Library. This library is free 6 // software; you can redistribute it and/or modify it under the 7 // terms of the GNU General Public License as published by the 8 // Free Software Foundation; either version 3, or (at your option) 9 // any later version. 10 11 // This library is distributed in the hope that it will be useful, 12 // but WITHOUT ANY WARRANTY; without even the implied warranty of 13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 // GNU General Public License for more details. 15 16 // Under Section 7 of GPL version 3, you are granted additional 17 // permissions described in the GCC Runtime Library Exception, version 18 // 3.1, as published by the Free Software Foundation. 19 20 // You should have received a copy of the GNU General Public License and 21 // a copy of the GCC Runtime Library Exception along with this program; 22 // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see 23 // <http://www.gnu.org/licenses/>. 24 25 /** @file include/bits/sat_arith.h 26 * This is an internal header file, included by other library headers. 27 * Do not attempt to use it directly. @headername{numeric} 28 */ 29 30 #ifndef _GLIBCXX_SAT_ARITH_H 31 #define _GLIBCXX_SAT_ARITH_H 1 32 33 #ifdef _GLIBCXX_SYSHDR 34 #pragma GCC system_header 35 #endif 36 37 #include <bits/version.h> 38 39 #ifdef __glibcxx_saturation_arithmetic // C++ >= 26 40 41 #include <concepts> 42 #include <ext/numeric_traits.h> 43 44 namespace std _GLIBCXX_VISIBILITY(default) 45 { 46 _GLIBCXX_BEGIN_NAMESPACE_VERSION 47 48 /// Add two integers, with saturation in case of overflow. 49 template<typename _Tp> requires __is_standard_integer<_Tp>::value 50 constexpr _Tp 51 add_sat(_Tp __x, _Tp __y) noexcept 52 { 53 _Tp __z; 54 if (!__builtin_add_overflow(__x, __y, &__z)) 55 return __z; 56 if constexpr (is_unsigned_v<_Tp>) 57 return __gnu_cxx::__int_traits<_Tp>::__max; 58 else if (__x < 0) 59 return __gnu_cxx::__int_traits<_Tp>::__min; 60 else 61 return __gnu_cxx::__int_traits<_Tp>::__max; 62 } 63 64 /// Subtract one integer from another, with saturation in case of overflow. 65 template<typename _Tp> requires __is_standard_integer<_Tp>::value 66 constexpr _Tp 67 sub_sat(_Tp __x, _Tp __y) noexcept 68 { 69 _Tp __z; 70 if (!__builtin_sub_overflow(__x, __y, &__z)) 71 return __z; 72 if constexpr (is_unsigned_v<_Tp>) 73 return __gnu_cxx::__int_traits<_Tp>::__min; 74 else if (__x < 0) 75 return __gnu_cxx::__int_traits<_Tp>::__min; 76 else 77 return __gnu_cxx::__int_traits<_Tp>::__max; 78 } 79 80 /// Multiply two integers, with saturation in case of overflow. 81 template<typename _Tp> requires __is_standard_integer<_Tp>::value 82 constexpr _Tp 83 mul_sat(_Tp __x, _Tp __y) noexcept 84 { 85 _Tp __z; 86 if (!__builtin_mul_overflow(__x, __y, &__z)) 87 return __z; 88 if constexpr (is_unsigned_v<_Tp>) 89 return __gnu_cxx::__int_traits<_Tp>::__max; 90 else if (__x < 0 != __y < 0) 91 return __gnu_cxx::__int_traits<_Tp>::__min; 92 else 93 return __gnu_cxx::__int_traits<_Tp>::__max; 94 } 95 96 /// Divide one integer by another, with saturation in case of overflow. 97 template<typename _Tp> requires __is_standard_integer<_Tp>::value 98 constexpr _Tp 99 div_sat(_Tp __x, _Tp __y) noexcept 100 { 101 __glibcxx_assert(__y != 0); 102 if constexpr (is_signed_v<_Tp>) 103 if (__x == __gnu_cxx::__int_traits<_Tp>::__min && __y == _Tp(-1)) 104 return __gnu_cxx::__int_traits<_Tp>::__max; 105 return __x / __y; 106 } 107 108 /// Divide one integer by another, with saturation in case of overflow. 109 template<typename _Res, typename _Tp> 110 requires __is_standard_integer<_Res>::value 111 && __is_standard_integer<_Tp>::value 112 constexpr _Res 113 saturate_cast(_Tp __x) noexcept 114 { 115 constexpr int __digits_R = __gnu_cxx::__int_traits<_Res>::__digits; 116 constexpr int __digits_T = __gnu_cxx::__int_traits<_Tp>::__digits; 117 constexpr _Res __max_Res = __gnu_cxx::__int_traits<_Res>::__max; 118 119 if constexpr (is_signed_v<_Res> == is_signed_v<_Tp>) 120 { 121 if constexpr (__digits_R < __digits_T) 122 { 123 constexpr _Res __min_Res = __gnu_cxx::__int_traits<_Res>::__min; 124 125 if (__x < static_cast<_Tp>(__min_Res)) 126 return __min_Res; 127 else if (__x > static_cast<_Tp>(__max_Res)) 128 return __max_Res; 129 } 130 } 131 else if constexpr (is_signed_v<_Tp>) // Res is unsigned 132 { 133 if (__x < 0) 134 return 0; 135 else if (make_unsigned_t<_Tp>(__x) > __max_Res) 136 return __gnu_cxx::__int_traits<_Res>::__max; 137 } 138 else // Tp is unsigned, Res is signed 139 { 140 if (__x > make_unsigned_t<_Res>(__max_Res)) 141 return __max_Res; 142 } 143 return static_cast<_Res>(__x); 144 } 145 146 _GLIBCXX_END_NAMESPACE_VERSION 147 } // namespace 148 149 #endif // __glibcxx_saturation_arithmetic 150 #endif /* _GLIBCXX_SAT_ARITH_H */