C++ Logo

std-proposals

Advanced search

Re: [std-proposals] Signed Overflow

From: Hans Åberg <haberg_1_at_[hidden]>
Date: Fri, 5 Sep 2025 10:01:05 +0200
> On 4 Sep 2025, at 16:48, David Brown via Std-Proposals <std-proposals_at_[hidden]> wrote:
>
> Let's pretend we have 4 bit ints - because it makes the numbers much smaller and easier.
>
> If you write "a + b" with wrapping, and get a result of -2, how do you know the result is correct? How do you know the correct mathematical sum of "a" and "b" is -2, and not 14 ? You don't - you have lost information when overflow occurred. You do not get the right answer for integer summation.

If you need the overflow values, it is best to use the functions in Tiago Freire's proposal, as they can use assembler if available. It would be more C++ if one can set a trap if needed, and call a function that, for example, throws an exception. I think this may be possible for floating-point types (on x86_64v and arm64).
https://isocpp.org/files/papers/P3161R4.html

If assembler is not available, for c = a + b to wrap around, a and b must be of the same sign, as otherwise the result is in the interval [a, b]. If both a and b are positive, the overflow occurs when c is less than any of a and b, as if 𝛽 is the base, the return value is a+b-𝛽, and both a-𝛽 and b-𝛽 are negative. Similarly, but reversed, when both a and b are negative.

For unsigned types, there is only one overflow test to do. It turns out that it is sufficient for doing full-word multiprecision division. The reason the original division algorithm is written for 64/32-bit words may be that the modular unsigned types were not available back then, in the 1990s or earlier, when it was first written.

When going down to a half-word implementation, the division algorithm slows down by a factor of 4–5 at least, I think. Since I wrote it as a template, I could check by comparing it with 16-bit words. (It is also useful with 8-bit words, as that may be used in the literature.)

The reason for ditching the undefined behavior is probably that all current hardware architectures are modular, so it is not needed anymore from that point of view. The UNIVAC 1100/2200 series uses ones' complement and is still supported, but I could see if it uses C++.
https://en.wikipedia.org/wiki/UNIVAC_1100/2200_series
https://en.wikipedia.org/wiki/Ones%27_complement

The optimizations are probably a later development, as the compilers became really good at it first in the 1990s or even later.

Dropping undefined behavior in favor of modularity would not break any user code, and the compilers would only need to change any optimizations using it into options.

Received on 2025-09-05 08:01:25