LCOV - code coverage report
Current view: top level - src/include/common - int.h (source / functions) Hit Total Coverage
Test: PostgreSQL 18devel Lines: 46 46 100.0 %
Date: 2024-11-21 08:14:44 Functions: 22 22 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*-------------------------------------------------------------------------
       2             :  *
       3             :  * int.h
       4             :  *    Overflow-aware integer math and integer comparison routines.
       5             :  *
       6             :  * The routines in this file are intended to be well defined C, without
       7             :  * relying on compiler flags like -fwrapv.
       8             :  *
       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.
      13             :  *
      14             :  * Copyright (c) 2017-2024, PostgreSQL Global Development Group
      15             :  *
      16             :  * src/include/common/int.h
      17             :  *
      18             :  *-------------------------------------------------------------------------
      19             :  */
      20             : #ifndef COMMON_INT_H
      21             : #define COMMON_INT_H
      22             : 
      23             : 
      24             : /*---------
      25             :  * The following guidelines apply to all the overflow routines:
      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
      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.
      55             :  *---------
      56             :  */
      57             : 
      58             : /*------------------------------------------------------------------------
      59             :  * Overflow routines for signed integers
      60             :  *------------------------------------------------------------------------
      61             :  */
      62             : 
      63             : /*
      64             :  * INT16
      65             :  */
      66             : static inline bool
      67        6606 : pg_add_s16_overflow(int16 a, int16 b, int16 *result)
      68             : {
      69             : #if defined(HAVE__BUILTIN_OP_OVERFLOW)
      70        6606 :     return __builtin_add_overflow(a, b, result);
      71             : #else
      72             :     int32       res = (int32) a + (int32) b;
      73             : 
      74             :     if (res > PG_INT16_MAX || res < PG_INT16_MIN)
      75             :     {
      76             :         *result = 0x5EED;       /* to avoid spurious warnings */
      77             :         return true;
      78             :     }
      79             :     *result = (int16) res;
      80             :     return false;
      81             : #endif
      82             : }
      83             : 
      84             : static inline bool
      85        1218 : pg_sub_s16_overflow(int16 a, int16 b, int16 *result)
      86             : {
      87             : #if defined(HAVE__BUILTIN_OP_OVERFLOW)
      88        1218 :     return __builtin_sub_overflow(a, b, result);
      89             : #else
      90             :     int32       res = (int32) a - (int32) b;
      91             : 
      92             :     if (res > PG_INT16_MAX || res < PG_INT16_MIN)
      93             :     {
      94             :         *result = 0x5EED;       /* to avoid spurious warnings */
      95             :         return true;
      96             :     }
      97             :     *result = (int16) res;
      98             :     return false;
      99             : #endif
     100             : }
     101             : 
     102             : static inline bool
     103          54 : pg_mul_s16_overflow(int16 a, int16 b, int16 *result)
     104             : {
     105             : #if defined(HAVE__BUILTIN_OP_OVERFLOW)
     106          54 :     return __builtin_mul_overflow(a, b, result);
     107             : #else
     108             :     int32       res = (int32) a * (int32) b;
     109             : 
     110             :     if (res > PG_INT16_MAX || res < PG_INT16_MIN)
     111             :     {
     112             :         *result = 0x5EED;       /* to avoid spurious warnings */
     113             :         return true;
     114             :     }
     115             :     *result = (int16) res;
     116             :     return false;
     117             : #endif
     118             : }
     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             : 
     131             : /*
     132             :  * INT32
     133             :  */
     134             : static inline bool
     135    20954412 : pg_add_s32_overflow(int32 a, int32 b, int32 *result)
     136             : {
     137             : #if defined(HAVE__BUILTIN_OP_OVERFLOW)
     138    20954412 :     return __builtin_add_overflow(a, b, result);
     139             : #else
     140             :     int64       res = (int64) a + (int64) b;
     141             : 
     142             :     if (res > PG_INT32_MAX || res < PG_INT32_MIN)
     143             :     {
     144             :         *result = 0x5EED;       /* to avoid spurious warnings */
     145             :         return true;
     146             :     }
     147             :     *result = (int32) res;
     148             :     return false;
     149             : #endif
     150             : }
     151             : 
     152             : static inline bool
     153     1458210 : pg_sub_s32_overflow(int32 a, int32 b, int32 *result)
     154             : {
     155             : #if defined(HAVE__BUILTIN_OP_OVERFLOW)
     156     1458210 :     return __builtin_sub_overflow(a, b, result);
     157             : #else
     158             :     int64       res = (int64) a - (int64) b;
     159             : 
     160             :     if (res > PG_INT32_MAX || res < PG_INT32_MIN)
     161             :     {
     162             :         *result = 0x5EED;       /* to avoid spurious warnings */
     163             :         return true;
     164             :     }
     165             :     *result = (int32) res;
     166             :     return false;
     167             : #endif
     168             : }
     169             : 
     170             : static inline bool
     171     3748612 : pg_mul_s32_overflow(int32 a, int32 b, int32 *result)
     172             : {
     173             : #if defined(HAVE__BUILTIN_OP_OVERFLOW)
     174     3748612 :     return __builtin_mul_overflow(a, b, result);
     175             : #else
     176             :     int64       res = (int64) a * (int64) b;
     177             : 
     178             :     if (res > PG_INT32_MAX || res < PG_INT32_MIN)
     179             :     {
     180             :         *result = 0x5EED;       /* to avoid spurious warnings */
     181             :         return true;
     182             :     }
     183             :     *result = (int32) res;
     184             :     return false;
     185             : #endif
     186             : }
     187             : 
     188             : static inline uint32
     189        1146 : 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        1146 :     return (uint32) i64abs((int64) a);
     197             : }
     198             : 
     199             : /*
     200             :  * INT64
     201             :  */
     202             : static inline bool
     203    22054628 : pg_add_s64_overflow(int64 a, int64 b, int64 *result)
     204             : {
     205             : #if defined(HAVE__BUILTIN_OP_OVERFLOW)
     206    22054628 :     return __builtin_add_overflow(a, b, result);
     207             : #elif defined(HAVE_INT128)
     208             :     int128      res = (int128) a + (int128) b;
     209             : 
     210             :     if (res > PG_INT64_MAX || res < PG_INT64_MIN)
     211             :     {
     212             :         *result = 0x5EED;       /* to avoid spurious warnings */
     213             :         return true;
     214             :     }
     215             :     *result = (int64) res;
     216             :     return false;
     217             : #else
     218             :     if ((a > 0 && b > 0 && a > PG_INT64_MAX - b) ||
     219             :         (a < 0 && b < 0 && a < PG_INT64_MIN - b))
     220             :     {
     221             :         *result = 0x5EED;       /* to avoid spurious warnings */
     222             :         return true;
     223             :     }
     224             :     *result = a + b;
     225             :     return false;
     226             : #endif
     227             : }
     228             : 
     229             : static inline bool
     230      250706 : pg_sub_s64_overflow(int64 a, int64 b, int64 *result)
     231             : {
     232             : #if defined(HAVE__BUILTIN_OP_OVERFLOW)
     233      250706 :     return __builtin_sub_overflow(a, b, result);
     234             : #elif defined(HAVE_INT128)
     235             :     int128      res = (int128) a - (int128) b;
     236             : 
     237             :     if (res > PG_INT64_MAX || res < PG_INT64_MIN)
     238             :     {
     239             :         *result = 0x5EED;       /* to avoid spurious warnings */
     240             :         return true;
     241             :     }
     242             :     *result = (int64) res;
     243             :     return false;
     244             : #else
     245             :     /*
     246             :      * Note: overflow is also possible when a == 0 and b < 0 (specifically,
     247             :      * when b == PG_INT64_MIN).
     248             :      */
     249             :     if ((a < 0 && b > 0 && a < PG_INT64_MIN + b) ||
     250             :         (a >= 0 && b < 0 && a > PG_INT64_MAX + b))
     251             :     {
     252             :         *result = 0x5EED;       /* to avoid spurious warnings */
     253             :         return true;
     254             :     }
     255             :     *result = a - b;
     256             :     return false;
     257             : #endif
     258             : }
     259             : 
     260             : static inline bool
     261      234660 : pg_mul_s64_overflow(int64 a, int64 b, int64 *result)
     262             : {
     263             : #if defined(HAVE__BUILTIN_OP_OVERFLOW)
     264      234660 :     return __builtin_mul_overflow(a, b, result);
     265             : #elif defined(HAVE_INT128)
     266             :     int128      res = (int128) a * (int128) b;
     267             : 
     268             :     if (res > PG_INT64_MAX || res < PG_INT64_MIN)
     269             :     {
     270             :         *result = 0x5EED;       /* to avoid spurious warnings */
     271             :         return true;
     272             :     }
     273             :     *result = (int64) res;
     274             :     return false;
     275             : #else
     276             :     /*
     277             :      * Overflow can only happen if at least one value is outside the range
     278             :      * sqrt(min)..sqrt(max) so check that first as the division can be quite a
     279             :      * bit more expensive than the multiplication.
     280             :      *
     281             :      * Multiplying by 0 or 1 can't overflow of course and checking for 0
     282             :      * separately avoids any risk of dividing by 0.  Be careful about dividing
     283             :      * INT_MIN by -1 also, note reversing the a and b to ensure we're always
     284             :      * dividing it by a positive value.
     285             :      *
     286             :      */
     287             :     if ((a > PG_INT32_MAX || a < PG_INT32_MIN ||
     288             :          b > PG_INT32_MAX || b < PG_INT32_MIN) &&
     289             :         a != 0 && a != 1 && b != 0 && b != 1 &&
     290             :         ((a > 0 && b > 0 && a > PG_INT64_MAX / b) ||
     291             :          (a > 0 && b < 0 && b < PG_INT64_MIN / a) ||
     292             :          (a < 0 && b > 0 && a < PG_INT64_MIN / b) ||
     293             :          (a < 0 && b < 0 && a < PG_INT64_MAX / b)))
     294             :     {
     295             :         *result = 0x5EED;       /* to avoid spurious warnings */
     296             :         return true;
     297             :     }
     298             :     *result = a * b;
     299             :     return false;
     300             : #endif
     301             : }
     302             : 
     303             : static inline uint64
     304        2230 : pg_abs_s64(int64 a)
     305             : {
     306        2230 :     if (unlikely(a == PG_INT64_MIN))
     307          12 :         return (uint64) PG_INT64_MAX + 1;
     308        2218 :     return (uint64) i64abs(a);
     309             : }
     310             : 
     311             : /*------------------------------------------------------------------------
     312             :  * Overflow routines for unsigned integers
     313             :  *------------------------------------------------------------------------
     314             :  */
     315             : 
     316             : /*
     317             :  * UINT16
     318             :  */
     319             : static inline bool
     320             : pg_add_u16_overflow(uint16 a, uint16 b, uint16 *result)
     321             : {
     322             : #if defined(HAVE__BUILTIN_OP_OVERFLOW)
     323             :     return __builtin_add_overflow(a, b, result);
     324             : #else
     325             :     uint16      res = a + b;
     326             : 
     327             :     if (res < a)
     328             :     {
     329             :         *result = 0x5EED;       /* to avoid spurious warnings */
     330             :         return true;
     331             :     }
     332             :     *result = res;
     333             :     return false;
     334             : #endif
     335             : }
     336             : 
     337             : static inline bool
     338             : pg_sub_u16_overflow(uint16 a, uint16 b, uint16 *result)
     339             : {
     340             : #if defined(HAVE__BUILTIN_OP_OVERFLOW)
     341             :     return __builtin_sub_overflow(a, b, result);
     342             : #else
     343             :     if (b > a)
     344             :     {
     345             :         *result = 0x5EED;       /* to avoid spurious warnings */
     346             :         return true;
     347             :     }
     348             :     *result = a - b;
     349             :     return false;
     350             : #endif
     351             : }
     352             : 
     353             : static inline bool
     354             : pg_mul_u16_overflow(uint16 a, uint16 b, uint16 *result)
     355             : {
     356             : #if defined(HAVE__BUILTIN_OP_OVERFLOW)
     357             :     return __builtin_mul_overflow(a, b, result);
     358             : #else
     359             :     uint32      res = (uint32) a * (uint32) b;
     360             : 
     361             :     if (res > PG_UINT16_MAX)
     362             :     {
     363             :         *result = 0x5EED;       /* to avoid spurious warnings */
     364             :         return true;
     365             :     }
     366             :     *result = (uint16) res;
     367             :     return false;
     368             : #endif
     369             : }
     370             : 
     371             : static inline bool
     372       17000 : pg_neg_u16_overflow(uint16 a, int16 *result)
     373             : {
     374             : #if defined(HAVE__BUILTIN_OP_OVERFLOW)
     375       17000 :     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             : 
     389             : /*
     390             :  * INT32
     391             :  */
     392             : static inline bool
     393             : pg_add_u32_overflow(uint32 a, uint32 b, uint32 *result)
     394             : {
     395             : #if defined(HAVE__BUILTIN_OP_OVERFLOW)
     396             :     return __builtin_add_overflow(a, b, result);
     397             : #else
     398             :     uint32      res = a + b;
     399             : 
     400             :     if (res < a)
     401             :     {
     402             :         *result = 0x5EED;       /* to avoid spurious warnings */
     403             :         return true;
     404             :     }
     405             :     *result = res;
     406             :     return false;
     407             : #endif
     408             : }
     409             : 
     410             : static inline bool
     411             : pg_sub_u32_overflow(uint32 a, uint32 b, uint32 *result)
     412             : {
     413             : #if defined(HAVE__BUILTIN_OP_OVERFLOW)
     414             :     return __builtin_sub_overflow(a, b, result);
     415             : #else
     416             :     if (b > a)
     417             :     {
     418             :         *result = 0x5EED;       /* to avoid spurious warnings */
     419             :         return true;
     420             :     }
     421             :     *result = a - b;
     422             :     return false;
     423             : #endif
     424             : }
     425             : 
     426             : static inline bool
     427             : pg_mul_u32_overflow(uint32 a, uint32 b, uint32 *result)
     428             : {
     429             : #if defined(HAVE__BUILTIN_OP_OVERFLOW)
     430             :     return __builtin_mul_overflow(a, b, result);
     431             : #else
     432             :     uint64      res = (uint64) a * (uint64) b;
     433             : 
     434             :     if (res > PG_UINT32_MAX)
     435             :     {
     436             :         *result = 0x5EED;       /* to avoid spurious warnings */
     437             :         return true;
     438             :     }
     439             :     *result = (uint32) res;
     440             :     return false;
     441             : #endif
     442             : }
     443             : 
     444             : static inline bool
     445       62638 : pg_neg_u32_overflow(uint32 a, int32 *result)
     446             : {
     447             : #if defined(HAVE__BUILTIN_OP_OVERFLOW)
     448       62638 :     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             : 
     462             : /*
     463             :  * UINT64
     464             :  */
     465             : static inline bool
     466         178 : pg_add_u64_overflow(uint64 a, uint64 b, uint64 *result)
     467             : {
     468             : #if defined(HAVE__BUILTIN_OP_OVERFLOW)
     469         178 :     return __builtin_add_overflow(a, b, result);
     470             : #else
     471             :     uint64      res = a + b;
     472             : 
     473             :     if (res < a)
     474             :     {
     475             :         *result = 0x5EED;       /* to avoid spurious warnings */
     476             :         return true;
     477             :     }
     478             :     *result = res;
     479             :     return false;
     480             : #endif
     481             : }
     482             : 
     483             : static inline bool
     484             : pg_sub_u64_overflow(uint64 a, uint64 b, uint64 *result)
     485             : {
     486             : #if defined(HAVE__BUILTIN_OP_OVERFLOW)
     487             :     return __builtin_sub_overflow(a, b, result);
     488             : #else
     489             :     if (b > a)
     490             :     {
     491             :         *result = 0x5EED;       /* to avoid spurious warnings */
     492             :         return true;
     493             :     }
     494             :     *result = a - b;
     495             :     return false;
     496             : #endif
     497             : }
     498             : 
     499             : static inline bool
     500         178 : pg_mul_u64_overflow(uint64 a, uint64 b, uint64 *result)
     501             : {
     502             : #if defined(HAVE__BUILTIN_OP_OVERFLOW)
     503         178 :     return __builtin_mul_overflow(a, b, result);
     504             : #elif defined(HAVE_INT128)
     505             :     uint128     res = (uint128) a * (uint128) b;
     506             : 
     507             :     if (res > PG_UINT64_MAX)
     508             :     {
     509             :         *result = 0x5EED;       /* to avoid spurious warnings */
     510             :         return true;
     511             :     }
     512             :     *result = (uint64) res;
     513             :     return false;
     514             : #else
     515             :     uint64      res = a * b;
     516             : 
     517             :     if (a != 0 && b != res / a)
     518             :     {
     519             :         *result = 0x5EED;       /* to avoid spurious warnings */
     520             :         return true;
     521             :     }
     522             :     *result = res;
     523             :     return false;
     524             : #endif
     525             : }
     526             : 
     527             : static inline bool
     528        1102 : pg_neg_u64_overflow(uint64 a, int64 *result)
     529             : {
     530             : #if defined(HAVE__BUILTIN_OP_OVERFLOW)
     531        1102 :     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             : 
     556             : /*------------------------------------------------------------------------
     557             :  *
     558             :  * Comparison routines for integer types.
     559             :  *
     560             :  * These routines are primarily intended for use in qsort() comparator
     561             :  * functions and therefore return a positive integer, 0, or a negative
     562             :  * integer depending on whether "a" is greater than, equal to, or less
     563             :  * than "b", respectively.  These functions are written to be as efficient
     564             :  * as possible without introducing overflow risks, thereby helping ensure
     565             :  * the comparators that use them are transitive.
     566             :  *
     567             :  * Types with fewer than 32 bits are cast to signed integers and
     568             :  * subtracted.  Other types are compared using > and <, and the results of
     569             :  * those comparisons (which are either (int) 0 or (int) 1 per the C
     570             :  * standard) are subtracted.
     571             :  *
     572             :  * NB: If the comparator function is inlined, some compilers may produce
     573             :  * worse code with these helper functions than with code with the
     574             :  * following form:
     575             :  *
     576             :  *     if (a < b)
     577             :  *         return -1;
     578             :  *     if (a > b)
     579             :  *         return 1;
     580             :  *     return 0;
     581             :  *
     582             :  *------------------------------------------------------------------------
     583             :  */
     584             : 
     585             : static inline int
     586    74346742 : pg_cmp_s16(int16 a, int16 b)
     587             : {
     588    74346742 :     return (int32) a - (int32) b;
     589             : }
     590             : 
     591             : static inline int
     592    11160762 : pg_cmp_u16(uint16 a, uint16 b)
     593             : {
     594    11160762 :     return (int32) a - (int32) b;
     595             : }
     596             : 
     597             : static inline int
     598   480583066 : pg_cmp_s32(int32 a, int32 b)
     599             : {
     600   480583066 :     return (a > b) - (a < b);
     601             : }
     602             : 
     603             : static inline int
     604    70438138 : pg_cmp_u32(uint32 a, uint32 b)
     605             : {
     606    70438138 :     return (a > b) - (a < b);
     607             : }
     608             : 
     609             : static inline int
     610             : pg_cmp_s64(int64 a, int64 b)
     611             : {
     612             :     return (a > b) - (a < b);
     613             : }
     614             : 
     615             : static inline int
     616    15156164 : pg_cmp_u64(uint64 a, uint64 b)
     617             : {
     618    15156164 :     return (a > b) - (a < b);
     619             : }
     620             : 
     621             : static inline int
     622           4 : pg_cmp_size(size_t a, size_t b)
     623             : {
     624           4 :     return (a > b) - (a < b);
     625             : }
     626             : 
     627             : #endif                          /* COMMON_INT_H */

Generated by: LCOV version 1.14