From: | Andres Freund <andres(at)anarazel(dot)de> |
---|---|
To: | Michael Paquier <michael(at)paquier(dot)xyz> |
Cc: | Fabien COELHO <coelho(at)cri(dot)ensmp(dot)fr>, Thomas Munro <thomas(dot)munro(at)gmail(dot)com>, Tom Lane <tgl(at)sss(dot)pgh(dot)pa(dot)us>, PostgreSQL Developers <pgsql-hackers(at)lists(dot)postgresql(dot)org> |
Subject: | Re: refactoring - share str2*int64 functions |
Date: | 2019-07-17 18:48:20 |
Message-ID: | 20190717184820.iqz7schxdbucmdmu@alap3.anarazel.de |
Views: | Raw Message | Whole Thread | Download mbox | Resend email |
Thread: | |
Lists: | pgsql-hackers |
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
From | Date | Subject | |
---|---|---|---|
Next Message | Darafei Komяpa Praliaskouski | 2019-07-17 18:54:21 | Unwanted expression simplification in PG12b2 |
Previous Message | Sergei Kornilov | 2019-07-17 18:44:47 | Re: Change ereport level for QueuePartitionConstraintValidation |