1/*-------------------------------------------------------------------------
4 * Overflow-aware integer math and integer comparison routines.
6 * The routines in this file are intended to be well defined C, without
7 * relying on compiler flags like -fwrapv.
9 * To reduce the overhead of these routines try to use compiler intrinsics
10 * where available. That's not that important for the 16, 32 bit cases, but
11 * the 64 bit cases can be considerably faster with intrinsics. In case no
12 * intrinsics are available 128 bit math is used where available.
14 * Copyright (c) 2017-2025, PostgreSQL Global Development Group
16 * src/include/common/int.h
18 *-------------------------------------------------------------------------
25 * The following guidelines apply to all the overflow routines:
27 * If the result overflows, return true, otherwise store the result into
28 * *result. The content of *result is implementation defined in case of
31 * bool pg_add_*_overflow(a, b, *result)
35 * bool pg_sub_*_overflow(a, b, *result)
39 * bool pg_mul_*_overflow(a, b, *result)
43 * bool pg_neg_*_overflow(a, *result)
48 * In addition, this file contains:
50 * <unsigned int type> pg_abs_*(<signed int type> a)
52 * Calculate absolute value of a. Unlike the standard library abs()
53 * and labs() functions, the return type is unsigned, so the operation
58/*------------------------------------------------------------------------
59 * Overflow routines for signed integers
60 *------------------------------------------------------------------------
69#if defined(HAVE__BUILTIN_OP_OVERFLOW)
70 return __builtin_add_overflow(
a,
b, result);
76 *result = 0x5EED;
/* to avoid spurious warnings */
79 *result = (
int16) res;
87#if defined(HAVE__BUILTIN_OP_OVERFLOW)
88 return __builtin_sub_overflow(
a,
b, result);
94 *result = 0x5EED;
/* to avoid spurious warnings */
97 *result = (
int16) res;
105#if defined(HAVE__BUILTIN_OP_OVERFLOW)
106 return __builtin_mul_overflow(
a,
b, result);
112 *result = 0x5EED;
/* to avoid spurious warnings */
115 *result = (
int16) res;
123#if defined(HAVE__BUILTIN_OP_OVERFLOW)
124 return __builtin_sub_overflow(0,
a, result);
128 *result = 0x5EED;
/* to avoid spurious warnings */
140 * This first widens the argument from int16 to int32 for use with abs().
141 * The result is then narrowed from int32 to uint16. This prevents any
142 * possibility of overflow.
153#if defined(HAVE__BUILTIN_OP_OVERFLOW)
154 return __builtin_add_overflow(
a,
b, result);
160 *result = 0x5EED;
/* to avoid spurious warnings */
163 *result = (
int32) res;
171#if defined(HAVE__BUILTIN_OP_OVERFLOW)
172 return __builtin_sub_overflow(
a,
b, result);
178 *result = 0x5EED;
/* to avoid spurious warnings */
181 *result = (
int32) res;
189#if defined(HAVE__BUILTIN_OP_OVERFLOW)
190 return __builtin_mul_overflow(
a,
b, result);
196 *result = 0x5EED;
/* to avoid spurious warnings */
199 *result = (
int32) res;
207#if defined(HAVE__BUILTIN_OP_OVERFLOW)
208 return __builtin_sub_overflow(0,
a, result);
212 *result = 0x5EED;
/* to avoid spurious warnings */
224 * This first widens the argument from int32 to int64 for use with
225 * i64abs(). The result is then narrowed from int64 to uint32. This
226 * prevents any possibility of overflow.
237#if defined(HAVE__BUILTIN_OP_OVERFLOW)
238 return __builtin_add_overflow(
a,
b, result);
239#elif defined(HAVE_INT128)
240 int128 res = (int128)
a + (int128)
b;
244 *result = 0x5EED;
/* to avoid spurious warnings */
247 *result = (
int64) res;
253 *result = 0x5EED;
/* to avoid spurious warnings */
264#if defined(HAVE__BUILTIN_OP_OVERFLOW)
265 return __builtin_sub_overflow(
a,
b, result);
266#elif defined(HAVE_INT128)
267 int128 res = (int128)
a - (int128)
b;
271 *result = 0x5EED;
/* to avoid spurious warnings */
274 *result = (
int64) res;
278 * Note: overflow is also possible when a == 0 and b < 0 (specifically,
279 * when b == PG_INT64_MIN).
284 *result = 0x5EED;
/* to avoid spurious warnings */
295#if defined(HAVE__BUILTIN_OP_OVERFLOW)
296 return __builtin_mul_overflow(
a,
b, result);
297#elif defined(HAVE_INT128)
298 int128 res = (int128)
a * (int128)
b;
302 *result = 0x5EED;
/* to avoid spurious warnings */
305 *result = (
int64) res;
309 * Overflow can only happen if at least one value is outside the range
310 * sqrt(min)..sqrt(max) so check that first as the division can be quite a
311 * bit more expensive than the multiplication.
313 * Multiplying by 0 or 1 can't overflow of course and checking for 0
314 * separately avoids any risk of dividing by 0. Be careful about dividing
315 * INT_MIN by -1 also, note reversing the a and b to ensure we're always
316 * dividing it by a positive value.
321 a != 0 &&
a != 1 &&
b != 0 &&
b != 1 &&
327 *result = 0x5EED;
/* to avoid spurious warnings */
338#if defined(HAVE__BUILTIN_OP_OVERFLOW)
339 return __builtin_sub_overflow(0,
a, result);
343 *result = 0x5EED;
/* to avoid spurious warnings */
359/*------------------------------------------------------------------------
360 * Overflow routines for unsigned integers
361 *------------------------------------------------------------------------
370#if defined(HAVE__BUILTIN_OP_OVERFLOW)
371 return __builtin_add_overflow(
a,
b, result);
377 *result = 0x5EED;
/* to avoid spurious warnings */
388#if defined(HAVE__BUILTIN_OP_OVERFLOW)
389 return __builtin_sub_overflow(
a,
b, result);
393 *result = 0x5EED;
/* to avoid spurious warnings */
404#if defined(HAVE__BUILTIN_OP_OVERFLOW)
405 return __builtin_mul_overflow(
a,
b, result);
411 *result = 0x5EED;
/* to avoid spurious warnings */
422#if defined(HAVE__BUILTIN_OP_OVERFLOW)
423 return __builtin_sub_overflow(0,
a, result);
429 *result = 0x5EED;
/* to avoid spurious warnings */
443#if defined(HAVE__BUILTIN_OP_OVERFLOW)
444 return __builtin_add_overflow(
a,
b, result);
450 *result = 0x5EED;
/* to avoid spurious warnings */
461#if defined(HAVE__BUILTIN_OP_OVERFLOW)
462 return __builtin_sub_overflow(
a,
b, result);
466 *result = 0x5EED;
/* to avoid spurious warnings */
477#if defined(HAVE__BUILTIN_OP_OVERFLOW)
478 return __builtin_mul_overflow(
a,
b, result);
484 *result = 0x5EED;
/* to avoid spurious warnings */
495#if defined(HAVE__BUILTIN_OP_OVERFLOW)
496 return __builtin_sub_overflow(0,
a, result);
502 *result = 0x5EED;
/* to avoid spurious warnings */
516#if defined(HAVE__BUILTIN_OP_OVERFLOW)
517 return __builtin_add_overflow(
a,
b, result);
523 *result = 0x5EED;
/* to avoid spurious warnings */
534#if defined(HAVE__BUILTIN_OP_OVERFLOW)
535 return __builtin_sub_overflow(
a,
b, result);
539 *result = 0x5EED;
/* to avoid spurious warnings */
550#if defined(HAVE__BUILTIN_OP_OVERFLOW)
551 return __builtin_mul_overflow(
a,
b, result);
552#elif defined(HAVE_INT128)
553 uint128 res = (uint128)
a * (uint128)
b;
557 *result = 0x5EED;
/* to avoid spurious warnings */
565 if (
a != 0 &&
b != res /
a)
567 *result = 0x5EED;
/* to avoid spurious warnings */
578#if defined(HAVE__BUILTIN_OP_OVERFLOW)
579 return __builtin_sub_overflow(0,
a, result);
580#elif defined(HAVE_INT128)
581 int128 res = -((int128)
a);
585 *result = 0x5EED;
/* to avoid spurious warnings */
593 *result = 0x5EED;
/* to avoid spurious warnings */
604/*------------------------------------------------------------------------
606 * Comparison routines for integer types.
608 * These routines are primarily intended for use in qsort() comparator
609 * functions and therefore return a positive integer, 0, or a negative
610 * integer depending on whether "a" is greater than, equal to, or less
611 * than "b", respectively. These functions are written to be as efficient
612 * as possible without introducing overflow risks, thereby helping ensure
613 * the comparators that use them are transitive.
615 * Types with fewer than 32 bits are cast to signed integers and
616 * subtracted. Other types are compared using > and <, and the results of
617 * those comparisons (which are either (int) 0 or (int) 1 per the C
618 * standard) are subtracted.
620 * NB: If the comparator function is inlined, some compilers may produce
621 * worse code with these helper functions than with code with the
630 *------------------------------------------------------------------------
648 return (
a >
b) - (
a <
b);
654 return (
a >
b) - (
a <
b);
660 return (
a >
b) - (
a <
b);
666 return (
a >
b) - (
a <
b);
672 return (
a >
b) - (
a <
b);
675#endif /* COMMON_INT_H */
static bool pg_mul_s64_overflow(int64 a, int64 b, int64 *result)
static bool pg_neg_s32_overflow(int32 a, int32 *result)
static int pg_cmp_s16(int16 a, int16 b)
static uint64 pg_abs_s64(int64 a)
static bool pg_sub_u32_overflow(uint32 a, uint32 b, uint32 *result)
static int pg_cmp_u32(uint32 a, uint32 b)
static bool pg_add_u32_overflow(uint32 a, uint32 b, uint32 *result)
static bool pg_neg_s16_overflow(int16 a, int16 *result)
static bool pg_sub_s64_overflow(int64 a, int64 b, int64 *result)
static bool pg_add_u64_overflow(uint64 a, uint64 b, uint64 *result)
static int pg_cmp_u16(uint16 a, uint16 b)
static bool pg_neg_u32_overflow(uint32 a, int32 *result)
static bool pg_sub_s16_overflow(int16 a, int16 b, int16 *result)
static bool pg_neg_u16_overflow(uint16 a, int16 *result)
static bool pg_neg_s64_overflow(int64 a, int64 *result)
static bool pg_mul_s32_overflow(int32 a, int32 b, int32 *result)
static bool pg_mul_u16_overflow(uint16 a, uint16 b, uint16 *result)
static bool pg_mul_u32_overflow(uint32 a, uint32 b, uint32 *result)
static bool pg_mul_s16_overflow(int16 a, int16 b, int16 *result)
static int pg_cmp_s64(int64 a, int64 b)
static bool pg_mul_u64_overflow(uint64 a, uint64 b, uint64 *result)
static bool pg_sub_u16_overflow(uint16 a, uint16 b, uint16 *result)
static bool pg_add_u16_overflow(uint16 a, uint16 b, uint16 *result)
static bool pg_add_s16_overflow(int16 a, int16 b, int16 *result)
static uint32 pg_abs_s32(int32 a)
static int pg_cmp_s32(int32 a, int32 b)
static int pg_cmp_u64(uint64 a, uint64 b)
static int pg_cmp_size(size_t a, size_t b)
static uint16 pg_abs_s16(int16 a)
static bool pg_sub_s32_overflow(int32 a, int32 b, int32 *result)
static bool pg_neg_u64_overflow(uint64 a, int64 *result)
static bool pg_add_s64_overflow(int64 a, int64 b, int64 *result)
static bool pg_sub_u64_overflow(uint64 a, uint64 b, uint64 *result)
static bool pg_add_s32_overflow(int32 a, int32 b, int32 *result)