Am Fr., 17. Nov. 2023 um 18:31 Uhr schrieb Jonathan Wakely <jwak...@redhat.com>: > > On Fri, 17 Nov 2023 at 17:01, Daniel Krügler <daniel.krueg...@gmail.com> > wrote: > > [..] > > > + > > > +namespace std _GLIBCXX_VISIBILITY(default) > > > +{ > > > +_GLIBCXX_BEGIN_NAMESPACE_VERSION > > > + > > > + /// Add two integers, with saturation in case of overflow. > > > + template<typename _Tp> requires __is_standard_integer<_Tp>::value > > > + constexpr _Tp > > > + add_sat(_Tp __x, _Tp __y) noexcept > > > + { > > > + _Tp __z; > > > + if (!__builtin_add_overflow(__x, __y, &__z)) > > > + return __z; > > > + if constexpr (is_unsigned_v<_Tp>) > > > + return __gnu_cxx::__int_traits<_Tp>::__max; > > > + else if (__x < 0) > > > + return __gnu_cxx::__int_traits<_Tp>::__min; > > > > My apologies, but why does the sign of x decide the direction of the > > result, shouldn't that be the sign of the returned value of z? > > z is incorrect at this point, it only has the correct value if no > overflow occurred. But we know that an overflow occurred because the > built-in returned true. > > We need to determine whether the overflow was positive, i.e. greater > than numeric_limits<T>::max(), or negative, i.e. lower than > numeric_limits<T>::min(). For unsigned types, it must have been a > positive overflow, because neither value is negative so that's easy. > > If x is negative, then there is no possible y that can cause a > positive overflow. If we consider Tp==int, then the maximum y is > INT_MAX, so if x is negative, x+INT_MAX < INT_MAX. So if x is > negative, we must have had a negative overflow, and so the result > saturates to INT_MIN. > > If x is positive, there is no possible y that can cause a negative > overflow. The minimum y is INT_MIN, and so if x is positive, x + > INT_MIN > INT_MIN. So if x is positive, we must have had a positive > overflow. > > (And x can't be zero, because 0+y would not overflow).
Ah right, thanks. - Daniel