C++ Logo

std-proposals

Advanced search

Re: [std-proposals] Integer overflow arithmetic with exceptions

From: Tiago Freire <tmiguelf_at_[hidden]>
Date: Thu, 12 Jun 2025 12:50:10 +0000
Ok,
x86 doesn't have an overflow flag for this operation, it just traps and you doesn't even get a result. Other CPUs just don't have the instruction.
In any case the solution is very simple.
Of unsigned integers, In order to detect the overflow all you have to do in your example:

a1 >= b

that's it
For unsigned integers it doesn't really matter at all what bits are set in your low dividend.
Mathematically if a1 >= b it is guaranteed to overflow, and a1 < b it is guaranteed to not overflow.
If you also can guarantee that the most significant bit of 'b' is set (and this condition is extremely important otherwise the following won't work), then you can just do this:

if(a1 < b)
{ //no overflow
 auto result = div_wide(a1, a0, b);
}
else //overflow
{
auto result = div_wide(a1 - b , a0, b);
//extra bit handling goes here
}

Otherwise you would have to break down into 2 divisions as mentioned before.

-----Original Message-----
From: Hans Åberg <haberg_1_at_icloud.com>
Sent: Thursday, June 12, 2025 2:17 PM
To: Tiago Freire <tmiguelf_at_[hidden]>
Cc: std-proposals_at_[hidden]
Subject: Re: Integer overflow arithmetic with exceptions


> On 12 Jun 2025, at 13:29, Tiago Freire <tmiguelf_at_hotmail.com> wrote:
>
> The suggestion that div_wide should have 2 words for the result (+ remainder) instead of the current 1 because of the potential overflow, is something that has come up before.

Only the overflow is needed in multiprecision division, not the upper word. If 𝛽 is the base, the overflow is at most 𝛽 + 2, so the upper word is never greater than 1. It is necessary to detect the overflow, but the quotient approximation can immediately be set to 𝛽 - 1, which is -1 in the unsigned type.

> 2. CPU's don't have such an instruction.

So the question is whether CPUs can detect overflow, and then report it as a boolean. I have written:
inline std::tuple<uint32_t, uint32_t, bool> div(uint32_t a0, uint32_t a1, uint32_t b) {
  uint64_t a = ((uint64_t)(a1) << 32) | (uint64_t)a0;
  uint64_t q = a/b;
  uint64_t r = a - q*b;
  return {q, r, q >> 32};
}

And similar for uint8_t, uint16_t.

There remains the case of uint64_t, which is really what the question is about.

Received on 2025-06-12 12:50:13