Hi, On 2019-07-17 17:29:58 +0900, Michael Paquier wrote: > Actually, one thing which may be a problem is that we lack currently > the equivalents of pg_mul_s16_overflow and such for unsigned > integers.
It's much simpler to implement them for unsigned than for signed, because unsigned overflow is well-defined. So I'd not be particularly worried about just adding them. E.g. comparing the "slow" version of pg_mul_s64_overflow() with an untested implementation of pg_mul_u64_overflow(): pg_mul_s64_overflow: /* * Overflow can only happen if at least one value is outside the range * sqrt(min)..sqrt(max) so check that first as the division can be quite a * bit more expensive than the multiplication. * * Multiplying by 0 or 1 can't overflow of course and checking for 0 * separately avoids any risk of dividing by 0. Be careful about dividing * INT_MIN by -1 also, note reversing the a and b to ensure we're always * dividing it by a positive value. * */ if ((a > PG_INT32_MAX || a < PG_INT32_MIN || b > PG_INT32_MAX || b < PG_INT32_MIN) && a != 0 && a != 1 && b != 0 && b != 1 && ((a > 0 && b > 0 && a > PG_INT64_MAX / b) || (a > 0 && b < 0 && b < PG_INT64_MIN / a) || (a < 0 && b > 0 && a < PG_INT64_MIN / b) || (a < 0 && b < 0 && a < PG_INT64_MAX / b))) { *result = 0x5EED; /* to avoid spurious warnings */ return true; } *result = a * b; return false; pg_mul_s64_overflow: /* * Checking for unsigned overflow is simple, just check * if reversing the multiplication indicates that the * multiplication overflowed. */ int64 res = a * b; if (a != 0 && b != res / a) { *result = 0x5EED; /* to avoid spurious warnings */ return true; } *result = res; return false; The cases for addition/subtraction are even easier: addition: res = a + b; if (res < a) /* overflow */ subtraction: if (a < b) /* underflow */ res = a - b; Greetings, Andres Freund