The following C++ template detects overflows from multiplying two unsigned integers.
template<typename UInt> UInt safe_multiply(UInt a, UInt b) {
UInt x = a * b; // x := ab mod n, for n := 2^#bits > 0
if (a != 0 && x / a != b)
cerr << "Overflow for " << a << " * " << b << "." << endl;
return x;
}
Can you give a proof that this algorithm detects every potential overflow, regardless of how many bits UInt uses?
cannot result in overflows, so we can consider
.
It seems that the correctness proof boils down to leading
to a contradiction, since x / a actually means .
, this leads to the straightforward consequence
which contradicts n > 0.
or there must be another way.
If the last equation is true, WolframAlpha fails to confirm that (also with exponents).
However, it asserts that the original assumptions have no integer solutions, so the algorithms seems to be correct indeed.
But it doesn't provide an explanation. So why is it correct?
I am looking for the smallest possible explanation that is still mathematically profound, ideally that it fits in a single-line comment. Maybe I am missing something trivial, or the problem is not as easy as it looks.
On a side note, I used Codecogs Equation Editor for the LaTeX markup images, which apparently looks bad in dark mode, so consider switching to light mode or, if you know, please tell me how to use different images depending on the client settings. It is just \bg{white} vs. \bg{black} as part of the image URLs.
To be clear, I'll use the multiplication and division symbols (
*,/) mathematically.Also, for convenience let's name the set
N = {0, 1, ..., n - 1}.Let's clear up what unsigned multiplication is:
Unsigned multiplication for some magnitude,
n, is a modularnoperation on unsigned-ninputs (inputs that are inN) that results in an unsigned-noutput (ie. also inN).In other words, the result of unsigned multiplication,
x, isx = a*b (mod n), and, additionally, we know thatx,a,bare inN.It's important to be able to expand many modular formulas like so:
x = a*b - k*n, wherekis an integer - but in our casex,a,bare inNso this implies thatkis inN.Now, let's mathematically say what we're trying to prove:
Given positive integers,
a,n, and non-negative integersx,b, wherex,a,bare inN, andx = a*b (mod n), thena*b >= n(overflow) impliesfloor(x/a) != b.Proof:
If overflow (
a*b >= n) thenx >= n - k*n = (1 - k)*n(forkinN),As
x < nthen(1 - k)*n < n, sok > 0.This means
x <= a*b - n.So,
floor(x/a) <= floor([a*b - n]/a) = floor(a*b/a - n/a) = b - floor(n/a) <= b - 1,Abbreviated:
floor(x/a) <= b - 1Therefore
floor(x/a) != b