|
23 | 23 |
|
24 | 24 | /*---------
|
25 | 25 | * The following guidelines apply to all the overflow routines:
|
26 |
| - * - If a + b overflows, return true, otherwise store the result of a + b |
27 |
| - * into *result. The content of *result is implementation defined in case of |
28 |
| - * overflow. |
29 |
| - * - If a - b overflows, return true, otherwise store the result of a - b |
30 |
| - * into *result. The content of *result is implementation defined in case of |
31 |
| - * overflow. |
32 |
| - * - If a * b overflows, return true, otherwise store the result of a * b |
33 |
| - * into *result. The content of *result is implementation defined in case of |
| 26 | + * |
| 27 | + * If the result overflows, return true, otherwise store the result into |
| 28 | + * *result. The content of *result is implementation defined in case of |
34 | 29 | * overflow.
|
| 30 | + * |
| 31 | + * bool pg_add_*_overflow(a, b, *result) |
| 32 | + * |
| 33 | + * Calculate a + b |
| 34 | + * |
| 35 | + * bool pg_sub_*_overflow(a, b, *result) |
| 36 | + * |
| 37 | + * Calculate a - b |
| 38 | + * |
| 39 | + * bool pg_mul_*_overflow(a, b, *result) |
| 40 | + * |
| 41 | + * Calculate a * b |
| 42 | + * |
| 43 | + * bool pg_neg_*_overflow(a, *result) |
| 44 | + * |
| 45 | + * Calculate -a |
| 46 | + * |
| 47 | + * |
| 48 | + * In addition, this file contains: |
| 49 | + * |
| 50 | + * <unsigned int type> pg_abs_*(<signed int type> a) |
| 51 | + * |
| 52 | + * Calculate absolute value of a. Unlike the standard library abs() |
| 53 | + * and labs() functions, the return type is unsigned, so the operation |
| 54 | + * cannot overflow. |
35 | 55 | *---------
|
36 | 56 | */
|
37 | 57 |
|
@@ -97,6 +117,17 @@ pg_mul_s16_overflow(int16 a, int16 b, int16 *result)
|
97 | 117 | #endif
|
98 | 118 | }
|
99 | 119 |
|
| 120 | +static inline uint16 |
| 121 | +pg_abs_s16(int16 a) |
| 122 | +{ |
| 123 | + /* |
| 124 | + * This first widens the argument from int16 to int32 for use with abs(). |
| 125 | + * The result is then narrowed from int32 to uint16. This prevents any |
| 126 | + * possibility of overflow. |
| 127 | + */ |
| 128 | + return (uint16) abs((int32) a); |
| 129 | +} |
| 130 | + |
100 | 131 | /*
|
101 | 132 | * INT32
|
102 | 133 | */
|
@@ -154,6 +185,17 @@ pg_mul_s32_overflow(int32 a, int32 b, int32 *result)
|
154 | 185 | #endif
|
155 | 186 | }
|
156 | 187 |
|
| 188 | +static inline uint32 |
| 189 | +pg_abs_s32(int32 a) |
| 190 | +{ |
| 191 | + /* |
| 192 | + * This first widens the argument from int32 to int64 for use with |
| 193 | + * i64abs(). The result is then narrowed from int64 to uint32. This |
| 194 | + * prevents any possibility of overflow. |
| 195 | + */ |
| 196 | + return (uint32) i64abs((int64) a); |
| 197 | +} |
| 198 | + |
157 | 199 | /*
|
158 | 200 | * INT64
|
159 | 201 | */
|
@@ -258,6 +300,14 @@ pg_mul_s64_overflow(int64 a, int64 b, int64 *result)
|
258 | 300 | #endif
|
259 | 301 | }
|
260 | 302 |
|
| 303 | +static inline uint64 |
| 304 | +pg_abs_s64(int64 a) |
| 305 | +{ |
| 306 | + if (unlikely(a == PG_INT64_MIN)) |
| 307 | + return (uint64) PG_INT64_MAX + 1; |
| 308 | + return (uint64) i64abs(a); |
| 309 | +} |
| 310 | + |
261 | 311 | /*------------------------------------------------------------------------
|
262 | 312 | * Overflow routines for unsigned integers
|
263 | 313 | *------------------------------------------------------------------------
|
@@ -318,6 +368,24 @@ pg_mul_u16_overflow(uint16 a, uint16 b, uint16 *result)
|
318 | 368 | #endif
|
319 | 369 | }
|
320 | 370 |
|
| 371 | +static inline bool |
| 372 | +pg_neg_u16_overflow(uint16 a, int16 *result) |
| 373 | +{ |
| 374 | +#if defined(HAVE__BUILTIN_OP_OVERFLOW) |
| 375 | + return __builtin_sub_overflow(0, a, result); |
| 376 | +#else |
| 377 | + int32 res = -((int32) a); |
| 378 | + |
| 379 | + if (unlikely(res < PG_INT16_MIN)) |
| 380 | + { |
| 381 | + *result = 0x5EED; /* to avoid spurious warnings */ |
| 382 | + return true; |
| 383 | + } |
| 384 | + *result = res; |
| 385 | + return false; |
| 386 | +#endif |
| 387 | +} |
| 388 | + |
321 | 389 | /*
|
322 | 390 | * INT32
|
323 | 391 | */
|
@@ -373,6 +441,24 @@ pg_mul_u32_overflow(uint32 a, uint32 b, uint32 *result)
|
373 | 441 | #endif
|
374 | 442 | }
|
375 | 443 |
|
| 444 | +static inline bool |
| 445 | +pg_neg_u32_overflow(uint32 a, int32 *result) |
| 446 | +{ |
| 447 | +#if defined(HAVE__BUILTIN_OP_OVERFLOW) |
| 448 | + return __builtin_sub_overflow(0, a, result); |
| 449 | +#else |
| 450 | + int64 res = -((int64) a); |
| 451 | + |
| 452 | + if (unlikely(res < PG_INT32_MIN)) |
| 453 | + { |
| 454 | + *result = 0x5EED; /* to avoid spurious warnings */ |
| 455 | + return true; |
| 456 | + } |
| 457 | + *result = res; |
| 458 | + return false; |
| 459 | +#endif |
| 460 | +} |
| 461 | + |
376 | 462 | /*
|
377 | 463 | * UINT64
|
378 | 464 | */
|
@@ -438,6 +524,35 @@ pg_mul_u64_overflow(uint64 a, uint64 b, uint64 *result)
|
438 | 524 | #endif
|
439 | 525 | }
|
440 | 526 |
|
| 527 | +static inline bool |
| 528 | +pg_neg_u64_overflow(uint64 a, int64 *result) |
| 529 | +{ |
| 530 | +#if defined(HAVE__BUILTIN_OP_OVERFLOW) |
| 531 | + return __builtin_sub_overflow(0, a, result); |
| 532 | +#elif defined(HAVE_INT128) |
| 533 | + int128 res = -((int128) a); |
| 534 | + |
| 535 | + if (unlikely(res < PG_INT64_MIN)) |
| 536 | + { |
| 537 | + *result = 0x5EED; /* to avoid spurious warnings */ |
| 538 | + return true; |
| 539 | + } |
| 540 | + *result = res; |
| 541 | + return false; |
| 542 | +#else |
| 543 | + if (unlikely(a > (uint64) PG_INT64_MAX + 1)) |
| 544 | + { |
| 545 | + *result = 0x5EED; /* to avoid spurious warnings */ |
| 546 | + return true; |
| 547 | + } |
| 548 | + if (unlikely(a == (uint64) PG_INT64_MAX + 1)) |
| 549 | + *result = PG_INT64_MIN; |
| 550 | + else |
| 551 | + *result = -((int64) a); |
| 552 | + return false; |
| 553 | +#endif |
| 554 | +} |
| 555 | + |
441 | 556 | /*------------------------------------------------------------------------
|
442 | 557 | *
|
443 | 558 | * Comparison routines for integer types.
|
|
0 commit comments