Bart van Ingen Schenau said:
So, the portability of this code is limited to systems where it is
documented that overflow results in wraparound.
Are you saying that, because your assumption does not hold for
saturating arithmetic, saturation is not useful or that you can't take
proper measures against overflow?
Here is a more portable version:
long add(int a, int b) { /* portable */
#if LONG_MAX >= 2L*INT_MAX
Writing the test this way is neither needed not advisable:
if LONG_MAX == INT_MAX, the expression 2L*INT_MAX overflows.
The definition of possible integer representations in the Standard specifies
value bits and binary representation: INT_MAX is a power of 2 minus 1.
Just testint LONG_MAX > INT_MAX would suffice.
if (a >= 0)
return (b <= INT_MAX - a) ? a + b : (long)a + b;
else
return (b >= INT_MIN - a) ? a + b : (long)a + b;
That's my proposal.
#else
if (a >= 0)
return (b <= LONG_MAX - a) ? (long)a + b : (unsigned long)a + b;
else
return (b >= LONG_MIN - a) ? (long)a + b : (unsigned long)a + b;
This does not work. Casting a as unsigned long forces the computation to use
unsigned arithmetics, which is fine, but the return statement will have to
convert the result back to a long: c99 6.3.1.3p3 "the new type is signed
and the value cannot be represented in it; either the result is
implementation-defined or an implementation-defined signal is raised."
We know there is an overflow is these cases, we just have to decide what
behaviour we want for add in case of long overflow:
#if INT_MAX == LONG_MAX
#if OVERFLOW_SATURATE
if (a >= 0)
return (b <= LONG_MAX - a) ? a + b : LONG_MAX;
else
return (b >= LONG_MIN - a) ? a + b : LONG_MIN;
#elif OVERFLOW_WRAP_AROUND && LONG_MIN < -LONG_MAX
if (a >= 0) {
if (b <= LONG_MAX - a) {
return a + b;
} else {
unsigned long s = (unsigned long)a + b;
if (s == (unsigned long)LONG_MIN)
return LONG_MIN;
else
return -(long)-s;
}
} else {
return (b >= LONG_MIN - a) ? a + b :
(unsigned long)a + b;
}
#else
#error "unsupported configuration"
#endif
#endif
As a matter of fact, what is or was the behaviour of non 2s-complement
hardware on signed integer overflow ?