LCOV - code coverage report
Current view: top level - src/backend/utils/adt - int.c (source / functions) Hit Total Coverage
Test: PostgreSQL 17devel Lines: 508 587 86.5 %
Date: 2024-04-19 04:11:42 Functions: 82 94 87.2 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*-------------------------------------------------------------------------
       2             :  *
       3             :  * int.c
       4             :  *    Functions for the built-in integer types (except int8).
       5             :  *
       6             :  * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group
       7             :  * Portions Copyright (c) 1994, Regents of the University of California
       8             :  *
       9             :  *
      10             :  * IDENTIFICATION
      11             :  *    src/backend/utils/adt/int.c
      12             :  *
      13             :  *-------------------------------------------------------------------------
      14             :  */
      15             : /*
      16             :  * OLD COMMENTS
      17             :  *      I/O routines:
      18             :  *       int2in, int2out, int2recv, int2send
      19             :  *       int4in, int4out, int4recv, int4send
      20             :  *       int2vectorin, int2vectorout, int2vectorrecv, int2vectorsend
      21             :  *      Boolean operators:
      22             :  *       inteq, intne, intlt, intle, intgt, intge
      23             :  *      Arithmetic operators:
      24             :  *       intpl, intmi, int4mul, intdiv
      25             :  *
      26             :  *      Arithmetic operators:
      27             :  *       intmod
      28             :  */
      29             : #include "postgres.h"
      30             : 
      31             : #include <ctype.h>
      32             : #include <limits.h>
      33             : #include <math.h>
      34             : 
      35             : #include "catalog/pg_type.h"
      36             : #include "common/int.h"
      37             : #include "funcapi.h"
      38             : #include "libpq/pqformat.h"
      39             : #include "nodes/nodeFuncs.h"
      40             : #include "nodes/supportnodes.h"
      41             : #include "optimizer/optimizer.h"
      42             : #include "utils/array.h"
      43             : #include "utils/builtins.h"
      44             : 
      45             : #define Int2VectorSize(n)   (offsetof(int2vector, values) + (n) * sizeof(int16))
      46             : 
      47             : typedef struct
      48             : {
      49             :     int32       current;
      50             :     int32       finish;
      51             :     int32       step;
      52             : } generate_series_fctx;
      53             : 
      54             : 
      55             : /*****************************************************************************
      56             :  *   USER I/O ROUTINES                                                       *
      57             :  *****************************************************************************/
      58             : 
      59             : /*
      60             :  *      int2in          - converts "num" to short
      61             :  */
      62             : Datum
      63      740890 : int2in(PG_FUNCTION_ARGS)
      64             : {
      65      740890 :     char       *num = PG_GETARG_CSTRING(0);
      66             : 
      67      740890 :     PG_RETURN_INT16(pg_strtoint16_safe(num, fcinfo->context));
      68             : }
      69             : 
      70             : /*
      71             :  *      int2out         - converts short to "num"
      72             :  */
      73             : Datum
      74      276180 : int2out(PG_FUNCTION_ARGS)
      75             : {
      76      276180 :     int16       arg1 = PG_GETARG_INT16(0);
      77      276180 :     char       *result = (char *) palloc(7);    /* sign, 5 digits, '\0' */
      78             : 
      79      276180 :     pg_itoa(arg1, result);
      80      276180 :     PG_RETURN_CSTRING(result);
      81             : }
      82             : 
      83             : /*
      84             :  *      int2recv            - converts external binary format to int2
      85             :  */
      86             : Datum
      87           0 : int2recv(PG_FUNCTION_ARGS)
      88             : {
      89           0 :     StringInfo  buf = (StringInfo) PG_GETARG_POINTER(0);
      90             : 
      91           0 :     PG_RETURN_INT16((int16) pq_getmsgint(buf, sizeof(int16)));
      92             : }
      93             : 
      94             : /*
      95             :  *      int2send            - converts int2 to binary format
      96             :  */
      97             : Datum
      98           6 : int2send(PG_FUNCTION_ARGS)
      99             : {
     100           6 :     int16       arg1 = PG_GETARG_INT16(0);
     101             :     StringInfoData buf;
     102             : 
     103           6 :     pq_begintypsend(&buf);
     104           6 :     pq_sendint16(&buf, arg1);
     105           6 :     PG_RETURN_BYTEA_P(pq_endtypsend(&buf));
     106             : }
     107             : 
     108             : /*
     109             :  * construct int2vector given a raw array of int2s
     110             :  *
     111             :  * If int2s is NULL then caller must fill values[] afterward
     112             :  */
     113             : int2vector *
     114      110102 : buildint2vector(const int16 *int2s, int n)
     115             : {
     116             :     int2vector *result;
     117             : 
     118      110102 :     result = (int2vector *) palloc0(Int2VectorSize(n));
     119             : 
     120      110102 :     if (n > 0 && int2s)
     121       52068 :         memcpy(result->values, int2s, n * sizeof(int16));
     122             : 
     123             :     /*
     124             :      * Attach standard array header.  For historical reasons, we set the index
     125             :      * lower bound to 0 not 1.
     126             :      */
     127      110102 :     SET_VARSIZE(result, Int2VectorSize(n));
     128      110102 :     result->ndim = 1;
     129      110102 :     result->dataoffset = 0;      /* never any nulls */
     130      110102 :     result->elemtype = INT2OID;
     131      110102 :     result->dim1 = n;
     132      110102 :     result->lbound1 = 0;
     133             : 
     134      110102 :     return result;
     135             : }
     136             : 
     137             : /*
     138             :  *      int2vectorin            - converts "num num ..." to internal form
     139             :  */
     140             : Datum
     141         570 : int2vectorin(PG_FUNCTION_ARGS)
     142             : {
     143         570 :     char       *intString = PG_GETARG_CSTRING(0);
     144         570 :     Node       *escontext = fcinfo->context;
     145             :     int2vector *result;
     146             :     int         nalloc;
     147             :     int         n;
     148             : 
     149         570 :     nalloc = 32;                /* arbitrary initial size guess */
     150         570 :     result = (int2vector *) palloc0(Int2VectorSize(nalloc));
     151             : 
     152         570 :     for (n = 0;; n++)
     153         966 :     {
     154             :         long        l;
     155             :         char       *endp;
     156             : 
     157        1962 :         while (*intString && isspace((unsigned char) *intString))
     158         426 :             intString++;
     159        1536 :         if (*intString == '\0')
     160         558 :             break;
     161             : 
     162         978 :         if (n >= nalloc)
     163             :         {
     164           0 :             nalloc *= 2;
     165           0 :             result = (int2vector *) repalloc(result, Int2VectorSize(nalloc));
     166             :         }
     167             : 
     168         978 :         errno = 0;
     169         978 :         l = strtol(intString, &endp, 10);
     170             : 
     171         978 :         if (intString == endp)
     172          12 :             ereturn(escontext, (Datum) 0,
     173             :                     (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
     174             :                      errmsg("invalid input syntax for type %s: \"%s\"",
     175             :                             "smallint", intString)));
     176             : 
     177         972 :         if (errno == ERANGE || l < SHRT_MIN || l > SHRT_MAX)
     178           6 :             ereturn(escontext, (Datum) 0,
     179             :                     (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
     180             :                      errmsg("value \"%s\" is out of range for type %s", intString,
     181             :                             "smallint")));
     182             : 
     183         966 :         if (*endp && *endp != ' ')
     184           0 :             ereturn(escontext, (Datum) 0,
     185             :                     (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
     186             :                      errmsg("invalid input syntax for type %s: \"%s\"",
     187             :                             "smallint", intString)));
     188             : 
     189         966 :         result->values[n] = l;
     190         966 :         intString = endp;
     191             :     }
     192             : 
     193         558 :     SET_VARSIZE(result, Int2VectorSize(n));
     194         558 :     result->ndim = 1;
     195         558 :     result->dataoffset = 0;      /* never any nulls */
     196         558 :     result->elemtype = INT2OID;
     197         558 :     result->dim1 = n;
     198         558 :     result->lbound1 = 0;
     199             : 
     200         558 :     PG_RETURN_POINTER(result);
     201             : }
     202             : 
     203             : /*
     204             :  *      int2vectorout       - converts internal form to "num num ..."
     205             :  */
     206             : Datum
     207        5772 : int2vectorout(PG_FUNCTION_ARGS)
     208             : {
     209        5772 :     int2vector *int2Array = (int2vector *) PG_GETARG_POINTER(0);
     210             :     int         num,
     211        5772 :                 nnums = int2Array->dim1;
     212             :     char       *rp;
     213             :     char       *result;
     214             : 
     215             :     /* assumes sign, 5 digits, ' ' */
     216        5772 :     rp = result = (char *) palloc(nnums * 7 + 1);
     217       15284 :     for (num = 0; num < nnums; num++)
     218             :     {
     219        9512 :         if (num != 0)
     220        3774 :             *rp++ = ' ';
     221        9512 :         rp += pg_itoa(int2Array->values[num], rp);
     222             :     }
     223        5772 :     *rp = '\0';
     224        5772 :     PG_RETURN_CSTRING(result);
     225             : }
     226             : 
     227             : /*
     228             :  *      int2vectorrecv          - converts external binary format to int2vector
     229             :  */
     230             : Datum
     231           0 : int2vectorrecv(PG_FUNCTION_ARGS)
     232             : {
     233           0 :     LOCAL_FCINFO(locfcinfo, 3);
     234           0 :     StringInfo  buf = (StringInfo) PG_GETARG_POINTER(0);
     235             :     int2vector *result;
     236             : 
     237             :     /*
     238             :      * Normally one would call array_recv() using DirectFunctionCall3, but
     239             :      * that does not work since array_recv wants to cache some data using
     240             :      * fcinfo->flinfo->fn_extra.  So we need to pass it our own flinfo
     241             :      * parameter.
     242             :      */
     243           0 :     InitFunctionCallInfoData(*locfcinfo, fcinfo->flinfo, 3,
     244             :                              InvalidOid, NULL, NULL);
     245             : 
     246           0 :     locfcinfo->args[0].value = PointerGetDatum(buf);
     247           0 :     locfcinfo->args[0].isnull = false;
     248           0 :     locfcinfo->args[1].value = ObjectIdGetDatum(INT2OID);
     249           0 :     locfcinfo->args[1].isnull = false;
     250           0 :     locfcinfo->args[2].value = Int32GetDatum(-1);
     251           0 :     locfcinfo->args[2].isnull = false;
     252             : 
     253           0 :     result = (int2vector *) DatumGetPointer(array_recv(locfcinfo));
     254             : 
     255             :     Assert(!locfcinfo->isnull);
     256             : 
     257             :     /* sanity checks: int2vector must be 1-D, 0-based, no nulls */
     258           0 :     if (ARR_NDIM(result) != 1 ||
     259           0 :         ARR_HASNULL(result) ||
     260           0 :         ARR_ELEMTYPE(result) != INT2OID ||
     261           0 :         ARR_LBOUND(result)[0] != 0)
     262           0 :         ereport(ERROR,
     263             :                 (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
     264             :                  errmsg("invalid int2vector data")));
     265             : 
     266           0 :     PG_RETURN_POINTER(result);
     267             : }
     268             : 
     269             : /*
     270             :  *      int2vectorsend          - converts int2vector to binary format
     271             :  */
     272             : Datum
     273           0 : int2vectorsend(PG_FUNCTION_ARGS)
     274             : {
     275           0 :     return array_send(fcinfo);
     276             : }
     277             : 
     278             : 
     279             : /*****************************************************************************
     280             :  *   PUBLIC ROUTINES                                                         *
     281             :  *****************************************************************************/
     282             : 
     283             : /*
     284             :  *      int4in          - converts "num" to int4
     285             :  */
     286             : Datum
     287     4150070 : int4in(PG_FUNCTION_ARGS)
     288             : {
     289     4150070 :     char       *num = PG_GETARG_CSTRING(0);
     290             : 
     291     4150070 :     PG_RETURN_INT32(pg_strtoint32_safe(num, fcinfo->context));
     292             : }
     293             : 
     294             : /*
     295             :  *      int4out         - converts int4 to "num"
     296             :  */
     297             : Datum
     298    15705970 : int4out(PG_FUNCTION_ARGS)
     299             : {
     300    15705970 :     int32       arg1 = PG_GETARG_INT32(0);
     301    15705970 :     char       *result = (char *) palloc(12);   /* sign, 10 digits, '\0' */
     302             : 
     303    15705970 :     pg_ltoa(arg1, result);
     304    15705970 :     PG_RETURN_CSTRING(result);
     305             : }
     306             : 
     307             : /*
     308             :  *      int4recv            - converts external binary format to int4
     309             :  */
     310             : Datum
     311      203940 : int4recv(PG_FUNCTION_ARGS)
     312             : {
     313      203940 :     StringInfo  buf = (StringInfo) PG_GETARG_POINTER(0);
     314             : 
     315      203940 :     PG_RETURN_INT32((int32) pq_getmsgint(buf, sizeof(int32)));
     316             : }
     317             : 
     318             : /*
     319             :  *      int4send            - converts int4 to binary format
     320             :  */
     321             : Datum
     322      168120 : int4send(PG_FUNCTION_ARGS)
     323             : {
     324      168120 :     int32       arg1 = PG_GETARG_INT32(0);
     325             :     StringInfoData buf;
     326             : 
     327      168120 :     pq_begintypsend(&buf);
     328      168120 :     pq_sendint32(&buf, arg1);
     329      168120 :     PG_RETURN_BYTEA_P(pq_endtypsend(&buf));
     330             : }
     331             : 
     332             : 
     333             : /*
     334             :  *      ===================
     335             :  *      CONVERSION ROUTINES
     336             :  *      ===================
     337             :  */
     338             : 
     339             : Datum
     340       34208 : i2toi4(PG_FUNCTION_ARGS)
     341             : {
     342       34208 :     int16       arg1 = PG_GETARG_INT16(0);
     343             : 
     344       34208 :     PG_RETURN_INT32((int32) arg1);
     345             : }
     346             : 
     347             : Datum
     348       22526 : i4toi2(PG_FUNCTION_ARGS)
     349             : {
     350       22526 :     int32       arg1 = PG_GETARG_INT32(0);
     351             : 
     352       22526 :     if (unlikely(arg1 < SHRT_MIN) || unlikely(arg1 > SHRT_MAX))
     353          28 :         ereport(ERROR,
     354             :                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
     355             :                  errmsg("smallint out of range")));
     356             : 
     357       22498 :     PG_RETURN_INT16((int16) arg1);
     358             : }
     359             : 
     360             : /* Cast int4 -> bool */
     361             : Datum
     362          18 : int4_bool(PG_FUNCTION_ARGS)
     363             : {
     364          18 :     if (PG_GETARG_INT32(0) == 0)
     365           6 :         PG_RETURN_BOOL(false);
     366             :     else
     367          12 :         PG_RETURN_BOOL(true);
     368             : }
     369             : 
     370             : /* Cast bool -> int4 */
     371             : Datum
     372        1550 : bool_int4(PG_FUNCTION_ARGS)
     373             : {
     374        1550 :     if (PG_GETARG_BOOL(0) == false)
     375         812 :         PG_RETURN_INT32(0);
     376             :     else
     377         738 :         PG_RETURN_INT32(1);
     378             : }
     379             : 
     380             : /*
     381             :  *      ============================
     382             :  *      COMPARISON OPERATOR ROUTINES
     383             :  *      ============================
     384             :  */
     385             : 
     386             : /*
     387             :  *      inteq           - returns 1 iff arg1 == arg2
     388             :  *      intne           - returns 1 iff arg1 != arg2
     389             :  *      intlt           - returns 1 iff arg1 < arg2
     390             :  *      intle           - returns 1 iff arg1 <= arg2
     391             :  *      intgt           - returns 1 iff arg1 > arg2
     392             :  *      intge           - returns 1 iff arg1 >= arg2
     393             :  */
     394             : 
     395             : Datum
     396    27134722 : int4eq(PG_FUNCTION_ARGS)
     397             : {
     398    27134722 :     int32       arg1 = PG_GETARG_INT32(0);
     399    27134722 :     int32       arg2 = PG_GETARG_INT32(1);
     400             : 
     401    27134722 :     PG_RETURN_BOOL(arg1 == arg2);
     402             : }
     403             : 
     404             : Datum
     405      430360 : int4ne(PG_FUNCTION_ARGS)
     406             : {
     407      430360 :     int32       arg1 = PG_GETARG_INT32(0);
     408      430360 :     int32       arg2 = PG_GETARG_INT32(1);
     409             : 
     410      430360 :     PG_RETURN_BOOL(arg1 != arg2);
     411             : }
     412             : 
     413             : Datum
     414     6199850 : int4lt(PG_FUNCTION_ARGS)
     415             : {
     416     6199850 :     int32       arg1 = PG_GETARG_INT32(0);
     417     6199850 :     int32       arg2 = PG_GETARG_INT32(1);
     418             : 
     419     6199850 :     PG_RETURN_BOOL(arg1 < arg2);
     420             : }
     421             : 
     422             : Datum
     423     1173802 : int4le(PG_FUNCTION_ARGS)
     424             : {
     425     1173802 :     int32       arg1 = PG_GETARG_INT32(0);
     426     1173802 :     int32       arg2 = PG_GETARG_INT32(1);
     427             : 
     428     1173802 :     PG_RETURN_BOOL(arg1 <= arg2);
     429             : }
     430             : 
     431             : Datum
     432     2242206 : int4gt(PG_FUNCTION_ARGS)
     433             : {
     434     2242206 :     int32       arg1 = PG_GETARG_INT32(0);
     435     2242206 :     int32       arg2 = PG_GETARG_INT32(1);
     436             : 
     437     2242206 :     PG_RETURN_BOOL(arg1 > arg2);
     438             : }
     439             : 
     440             : Datum
     441      405136 : int4ge(PG_FUNCTION_ARGS)
     442             : {
     443      405136 :     int32       arg1 = PG_GETARG_INT32(0);
     444      405136 :     int32       arg2 = PG_GETARG_INT32(1);
     445             : 
     446      405136 :     PG_RETURN_BOOL(arg1 >= arg2);
     447             : }
     448             : 
     449             : Datum
     450     1866726 : int2eq(PG_FUNCTION_ARGS)
     451             : {
     452     1866726 :     int16       arg1 = PG_GETARG_INT16(0);
     453     1866726 :     int16       arg2 = PG_GETARG_INT16(1);
     454             : 
     455     1866726 :     PG_RETURN_BOOL(arg1 == arg2);
     456             : }
     457             : 
     458             : Datum
     459       30062 : int2ne(PG_FUNCTION_ARGS)
     460             : {
     461       30062 :     int16       arg1 = PG_GETARG_INT16(0);
     462       30062 :     int16       arg2 = PG_GETARG_INT16(1);
     463             : 
     464       30062 :     PG_RETURN_BOOL(arg1 != arg2);
     465             : }
     466             : 
     467             : Datum
     468      543822 : int2lt(PG_FUNCTION_ARGS)
     469             : {
     470      543822 :     int16       arg1 = PG_GETARG_INT16(0);
     471      543822 :     int16       arg2 = PG_GETARG_INT16(1);
     472             : 
     473      543822 :     PG_RETURN_BOOL(arg1 < arg2);
     474             : }
     475             : 
     476             : Datum
     477        4386 : int2le(PG_FUNCTION_ARGS)
     478             : {
     479        4386 :     int16       arg1 = PG_GETARG_INT16(0);
     480        4386 :     int16       arg2 = PG_GETARG_INT16(1);
     481             : 
     482        4386 :     PG_RETURN_BOOL(arg1 <= arg2);
     483             : }
     484             : 
     485             : Datum
     486     1771624 : int2gt(PG_FUNCTION_ARGS)
     487             : {
     488     1771624 :     int16       arg1 = PG_GETARG_INT16(0);
     489     1771624 :     int16       arg2 = PG_GETARG_INT16(1);
     490             : 
     491     1771624 :     PG_RETURN_BOOL(arg1 > arg2);
     492             : }
     493             : 
     494             : Datum
     495        3714 : int2ge(PG_FUNCTION_ARGS)
     496             : {
     497        3714 :     int16       arg1 = PG_GETARG_INT16(0);
     498        3714 :     int16       arg2 = PG_GETARG_INT16(1);
     499             : 
     500        3714 :     PG_RETURN_BOOL(arg1 >= arg2);
     501             : }
     502             : 
     503             : Datum
     504      127624 : int24eq(PG_FUNCTION_ARGS)
     505             : {
     506      127624 :     int16       arg1 = PG_GETARG_INT16(0);
     507      127624 :     int32       arg2 = PG_GETARG_INT32(1);
     508             : 
     509      127624 :     PG_RETURN_BOOL(arg1 == arg2);
     510             : }
     511             : 
     512             : Datum
     513       71040 : int24ne(PG_FUNCTION_ARGS)
     514             : {
     515       71040 :     int16       arg1 = PG_GETARG_INT16(0);
     516       71040 :     int32       arg2 = PG_GETARG_INT32(1);
     517             : 
     518       71040 :     PG_RETURN_BOOL(arg1 != arg2);
     519             : }
     520             : 
     521             : Datum
     522      131052 : int24lt(PG_FUNCTION_ARGS)
     523             : {
     524      131052 :     int16       arg1 = PG_GETARG_INT16(0);
     525      131052 :     int32       arg2 = PG_GETARG_INT32(1);
     526             : 
     527      131052 :     PG_RETURN_BOOL(arg1 < arg2);
     528             : }
     529             : 
     530             : Datum
     531       56580 : int24le(PG_FUNCTION_ARGS)
     532             : {
     533       56580 :     int16       arg1 = PG_GETARG_INT16(0);
     534       56580 :     int32       arg2 = PG_GETARG_INT32(1);
     535             : 
     536       56580 :     PG_RETURN_BOOL(arg1 <= arg2);
     537             : }
     538             : 
     539             : Datum
     540      500012 : int24gt(PG_FUNCTION_ARGS)
     541             : {
     542      500012 :     int16       arg1 = PG_GETARG_INT16(0);
     543      500012 :     int32       arg2 = PG_GETARG_INT32(1);
     544             : 
     545      500012 :     PG_RETURN_BOOL(arg1 > arg2);
     546             : }
     547             : 
     548             : Datum
     549        9748 : int24ge(PG_FUNCTION_ARGS)
     550             : {
     551        9748 :     int16       arg1 = PG_GETARG_INT16(0);
     552        9748 :     int32       arg2 = PG_GETARG_INT32(1);
     553             : 
     554        9748 :     PG_RETURN_BOOL(arg1 >= arg2);
     555             : }
     556             : 
     557             : Datum
     558      123734 : int42eq(PG_FUNCTION_ARGS)
     559             : {
     560      123734 :     int32       arg1 = PG_GETARG_INT32(0);
     561      123734 :     int16       arg2 = PG_GETARG_INT16(1);
     562             : 
     563      123734 :     PG_RETURN_BOOL(arg1 == arg2);
     564             : }
     565             : 
     566             : Datum
     567          30 : int42ne(PG_FUNCTION_ARGS)
     568             : {
     569          30 :     int32       arg1 = PG_GETARG_INT32(0);
     570          30 :     int16       arg2 = PG_GETARG_INT16(1);
     571             : 
     572          30 :     PG_RETURN_BOOL(arg1 != arg2);
     573             : }
     574             : 
     575             : Datum
     576       15756 : int42lt(PG_FUNCTION_ARGS)
     577             : {
     578       15756 :     int32       arg1 = PG_GETARG_INT32(0);
     579       15756 :     int16       arg2 = PG_GETARG_INT16(1);
     580             : 
     581       15756 :     PG_RETURN_BOOL(arg1 < arg2);
     582             : }
     583             : 
     584             : Datum
     585       15540 : int42le(PG_FUNCTION_ARGS)
     586             : {
     587       15540 :     int32       arg1 = PG_GETARG_INT32(0);
     588       15540 :     int16       arg2 = PG_GETARG_INT16(1);
     589             : 
     590       15540 :     PG_RETURN_BOOL(arg1 <= arg2);
     591             : }
     592             : 
     593             : Datum
     594        3228 : int42gt(PG_FUNCTION_ARGS)
     595             : {
     596        3228 :     int32       arg1 = PG_GETARG_INT32(0);
     597        3228 :     int16       arg2 = PG_GETARG_INT16(1);
     598             : 
     599        3228 :     PG_RETURN_BOOL(arg1 > arg2);
     600             : }
     601             : 
     602             : Datum
     603        3456 : int42ge(PG_FUNCTION_ARGS)
     604             : {
     605        3456 :     int32       arg1 = PG_GETARG_INT32(0);
     606        3456 :     int16       arg2 = PG_GETARG_INT16(1);
     607             : 
     608        3456 :     PG_RETURN_BOOL(arg1 >= arg2);
     609             : }
     610             : 
     611             : 
     612             : /*----------------------------------------------------------
     613             :  *  in_range functions for int4 and int2,
     614             :  *  including cross-data-type comparisons.
     615             :  *
     616             :  *  Note: we provide separate intN_int8 functions for performance
     617             :  *  reasons.  This forces also providing intN_int2, else cases with a
     618             :  *  smallint offset value would fail to resolve which function to use.
     619             :  *  But that's an unlikely situation, so don't duplicate code for it.
     620             :  *---------------------------------------------------------*/
     621             : 
     622             : Datum
     623        3198 : in_range_int4_int4(PG_FUNCTION_ARGS)
     624             : {
     625        3198 :     int32       val = PG_GETARG_INT32(0);
     626        3198 :     int32       base = PG_GETARG_INT32(1);
     627        3198 :     int32       offset = PG_GETARG_INT32(2);
     628        3198 :     bool        sub = PG_GETARG_BOOL(3);
     629        3198 :     bool        less = PG_GETARG_BOOL(4);
     630             :     int32       sum;
     631             : 
     632        3198 :     if (offset < 0)
     633          12 :         ereport(ERROR,
     634             :                 (errcode(ERRCODE_INVALID_PRECEDING_OR_FOLLOWING_SIZE),
     635             :                  errmsg("invalid preceding or following size in window function")));
     636             : 
     637        3186 :     if (sub)
     638        1440 :         offset = -offset;       /* cannot overflow */
     639             : 
     640        3186 :     if (unlikely(pg_add_s32_overflow(base, offset, &sum)))
     641             :     {
     642             :         /*
     643             :          * If sub is false, the true sum is surely more than val, so correct
     644             :          * answer is the same as "less".  If sub is true, the true sum is
     645             :          * surely less than val, so the answer is "!less".
     646             :          */
     647          36 :         PG_RETURN_BOOL(sub ? !less : less);
     648             :     }
     649             : 
     650        3150 :     if (less)
     651        1860 :         PG_RETURN_BOOL(val <= sum);
     652             :     else
     653        1290 :         PG_RETURN_BOOL(val >= sum);
     654             : }
     655             : 
     656             : Datum
     657         906 : in_range_int4_int2(PG_FUNCTION_ARGS)
     658             : {
     659             :     /* Doesn't seem worth duplicating code for, so just invoke int4_int4 */
     660         906 :     return DirectFunctionCall5(in_range_int4_int4,
     661             :                                PG_GETARG_DATUM(0),
     662             :                                PG_GETARG_DATUM(1),
     663             :                                Int32GetDatum((int32) PG_GETARG_INT16(2)),
     664             :                                PG_GETARG_DATUM(3),
     665             :                                PG_GETARG_DATUM(4));
     666             : }
     667             : 
     668             : Datum
     669         762 : in_range_int4_int8(PG_FUNCTION_ARGS)
     670             : {
     671             :     /* We must do all the math in int64 */
     672         762 :     int64       val = (int64) PG_GETARG_INT32(0);
     673         762 :     int64       base = (int64) PG_GETARG_INT32(1);
     674         762 :     int64       offset = PG_GETARG_INT64(2);
     675         762 :     bool        sub = PG_GETARG_BOOL(3);
     676         762 :     bool        less = PG_GETARG_BOOL(4);
     677             :     int64       sum;
     678             : 
     679         762 :     if (offset < 0)
     680           0 :         ereport(ERROR,
     681             :                 (errcode(ERRCODE_INVALID_PRECEDING_OR_FOLLOWING_SIZE),
     682             :                  errmsg("invalid preceding or following size in window function")));
     683             : 
     684         762 :     if (sub)
     685         690 :         offset = -offset;       /* cannot overflow */
     686             : 
     687         762 :     if (unlikely(pg_add_s64_overflow(base, offset, &sum)))
     688             :     {
     689             :         /*
     690             :          * If sub is false, the true sum is surely more than val, so correct
     691             :          * answer is the same as "less".  If sub is true, the true sum is
     692             :          * surely less than val, so the answer is "!less".
     693             :          */
     694           0 :         PG_RETURN_BOOL(sub ? !less : less);
     695             :     }
     696             : 
     697         762 :     if (less)
     698          72 :         PG_RETURN_BOOL(val <= sum);
     699             :     else
     700         690 :         PG_RETURN_BOOL(val >= sum);
     701             : }
     702             : 
     703             : Datum
     704          36 : in_range_int2_int4(PG_FUNCTION_ARGS)
     705             : {
     706             :     /* We must do all the math in int32 */
     707          36 :     int32       val = (int32) PG_GETARG_INT16(0);
     708          36 :     int32       base = (int32) PG_GETARG_INT16(1);
     709          36 :     int32       offset = PG_GETARG_INT32(2);
     710          36 :     bool        sub = PG_GETARG_BOOL(3);
     711          36 :     bool        less = PG_GETARG_BOOL(4);
     712             :     int32       sum;
     713             : 
     714          36 :     if (offset < 0)
     715           0 :         ereport(ERROR,
     716             :                 (errcode(ERRCODE_INVALID_PRECEDING_OR_FOLLOWING_SIZE),
     717             :                  errmsg("invalid preceding or following size in window function")));
     718             : 
     719          36 :     if (sub)
     720          18 :         offset = -offset;       /* cannot overflow */
     721             : 
     722          36 :     if (unlikely(pg_add_s32_overflow(base, offset, &sum)))
     723             :     {
     724             :         /*
     725             :          * If sub is false, the true sum is surely more than val, so correct
     726             :          * answer is the same as "less".  If sub is true, the true sum is
     727             :          * surely less than val, so the answer is "!less".
     728             :          */
     729          36 :         PG_RETURN_BOOL(sub ? !less : less);
     730             :     }
     731             : 
     732           0 :     if (less)
     733           0 :         PG_RETURN_BOOL(val <= sum);
     734             :     else
     735           0 :         PG_RETURN_BOOL(val >= sum);
     736             : }
     737             : 
     738             : Datum
     739           0 : in_range_int2_int2(PG_FUNCTION_ARGS)
     740             : {
     741             :     /* Doesn't seem worth duplicating code for, so just invoke int2_int4 */
     742           0 :     return DirectFunctionCall5(in_range_int2_int4,
     743             :                                PG_GETARG_DATUM(0),
     744             :                                PG_GETARG_DATUM(1),
     745             :                                Int32GetDatum((int32) PG_GETARG_INT16(2)),
     746             :                                PG_GETARG_DATUM(3),
     747             :                                PG_GETARG_DATUM(4));
     748             : }
     749             : 
     750             : Datum
     751           0 : in_range_int2_int8(PG_FUNCTION_ARGS)
     752             : {
     753             :     /* Doesn't seem worth duplicating code for, so just invoke int4_int8 */
     754           0 :     return DirectFunctionCall5(in_range_int4_int8,
     755             :                                Int32GetDatum((int32) PG_GETARG_INT16(0)),
     756             :                                Int32GetDatum((int32) PG_GETARG_INT16(1)),
     757             :                                PG_GETARG_DATUM(2),
     758             :                                PG_GETARG_DATUM(3),
     759             :                                PG_GETARG_DATUM(4));
     760             : }
     761             : 
     762             : 
     763             : /*
     764             :  *      int[24]pl       - returns arg1 + arg2
     765             :  *      int[24]mi       - returns arg1 - arg2
     766             :  *      int[24]mul      - returns arg1 * arg2
     767             :  *      int[24]div      - returns arg1 / arg2
     768             :  */
     769             : 
     770             : Datum
     771       52848 : int4um(PG_FUNCTION_ARGS)
     772             : {
     773       52848 :     int32       arg = PG_GETARG_INT32(0);
     774             : 
     775       52848 :     if (unlikely(arg == PG_INT32_MIN))
     776           0 :         ereport(ERROR,
     777             :                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
     778             :                  errmsg("integer out of range")));
     779       52848 :     PG_RETURN_INT32(-arg);
     780             : }
     781             : 
     782             : Datum
     783           6 : int4up(PG_FUNCTION_ARGS)
     784             : {
     785           6 :     int32       arg = PG_GETARG_INT32(0);
     786             : 
     787           6 :     PG_RETURN_INT32(arg);
     788             : }
     789             : 
     790             : Datum
     791     3317688 : int4pl(PG_FUNCTION_ARGS)
     792             : {
     793     3317688 :     int32       arg1 = PG_GETARG_INT32(0);
     794     3317688 :     int32       arg2 = PG_GETARG_INT32(1);
     795             :     int32       result;
     796             : 
     797     3317688 :     if (unlikely(pg_add_s32_overflow(arg1, arg2, &result)))
     798           6 :         ereport(ERROR,
     799             :                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
     800             :                  errmsg("integer out of range")));
     801     3317682 :     PG_RETURN_INT32(result);
     802             : }
     803             : 
     804             : Datum
     805     1400584 : int4mi(PG_FUNCTION_ARGS)
     806             : {
     807     1400584 :     int32       arg1 = PG_GETARG_INT32(0);
     808     1400584 :     int32       arg2 = PG_GETARG_INT32(1);
     809             :     int32       result;
     810             : 
     811     1400584 :     if (unlikely(pg_sub_s32_overflow(arg1, arg2, &result)))
     812           6 :         ereport(ERROR,
     813             :                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
     814             :                  errmsg("integer out of range")));
     815     1400578 :     PG_RETURN_INT32(result);
     816             : }
     817             : 
     818             : Datum
     819     2848970 : int4mul(PG_FUNCTION_ARGS)
     820             : {
     821     2848970 :     int32       arg1 = PG_GETARG_INT32(0);
     822     2848970 :     int32       arg2 = PG_GETARG_INT32(1);
     823             :     int32       result;
     824             : 
     825     2848970 :     if (unlikely(pg_mul_s32_overflow(arg1, arg2, &result)))
     826          18 :         ereport(ERROR,
     827             :                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
     828             :                  errmsg("integer out of range")));
     829     2848952 :     PG_RETURN_INT32(result);
     830             : }
     831             : 
     832             : Datum
     833     1505138 : int4div(PG_FUNCTION_ARGS)
     834             : {
     835     1505138 :     int32       arg1 = PG_GETARG_INT32(0);
     836     1505138 :     int32       arg2 = PG_GETARG_INT32(1);
     837             :     int32       result;
     838             : 
     839     1505138 :     if (arg2 == 0)
     840             :     {
     841         272 :         ereport(ERROR,
     842             :                 (errcode(ERRCODE_DIVISION_BY_ZERO),
     843             :                  errmsg("division by zero")));
     844             :         /* ensure compiler realizes we mustn't reach the division (gcc bug) */
     845             :         PG_RETURN_NULL();
     846             :     }
     847             : 
     848             :     /*
     849             :      * INT_MIN / -1 is problematic, since the result can't be represented on a
     850             :      * two's-complement machine.  Some machines produce INT_MIN, some produce
     851             :      * zero, some throw an exception.  We can dodge the problem by recognizing
     852             :      * that division by -1 is the same as negation.
     853             :      */
     854     1504866 :     if (arg2 == -1)
     855             :     {
     856          16 :         if (unlikely(arg1 == PG_INT32_MIN))
     857           6 :             ereport(ERROR,
     858             :                     (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
     859             :                      errmsg("integer out of range")));
     860          10 :         result = -arg1;
     861          10 :         PG_RETURN_INT32(result);
     862             :     }
     863             : 
     864             :     /* No overflow is possible */
     865             : 
     866     1504850 :     result = arg1 / arg2;
     867             : 
     868     1504850 :     PG_RETURN_INT32(result);
     869             : }
     870             : 
     871             : Datum
     872           0 : int4inc(PG_FUNCTION_ARGS)
     873             : {
     874           0 :     int32       arg = PG_GETARG_INT32(0);
     875             :     int32       result;
     876             : 
     877           0 :     if (unlikely(pg_add_s32_overflow(arg, 1, &result)))
     878           0 :         ereport(ERROR,
     879             :                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
     880             :                  errmsg("integer out of range")));
     881             : 
     882           0 :     PG_RETURN_INT32(result);
     883             : }
     884             : 
     885             : Datum
     886          18 : int2um(PG_FUNCTION_ARGS)
     887             : {
     888          18 :     int16       arg = PG_GETARG_INT16(0);
     889             : 
     890          18 :     if (unlikely(arg == PG_INT16_MIN))
     891           0 :         ereport(ERROR,
     892             :                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
     893             :                  errmsg("smallint out of range")));
     894          18 :     PG_RETURN_INT16(-arg);
     895             : }
     896             : 
     897             : Datum
     898           0 : int2up(PG_FUNCTION_ARGS)
     899             : {
     900           0 :     int16       arg = PG_GETARG_INT16(0);
     901             : 
     902           0 :     PG_RETURN_INT16(arg);
     903             : }
     904             : 
     905             : Datum
     906          54 : int2pl(PG_FUNCTION_ARGS)
     907             : {
     908          54 :     int16       arg1 = PG_GETARG_INT16(0);
     909          54 :     int16       arg2 = PG_GETARG_INT16(1);
     910             :     int16       result;
     911             : 
     912          54 :     if (unlikely(pg_add_s16_overflow(arg1, arg2, &result)))
     913           6 :         ereport(ERROR,
     914             :                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
     915             :                  errmsg("smallint out of range")));
     916          48 :     PG_RETURN_INT16(result);
     917             : }
     918             : 
     919             : Datum
     920         120 : int2mi(PG_FUNCTION_ARGS)
     921             : {
     922         120 :     int16       arg1 = PG_GETARG_INT16(0);
     923         120 :     int16       arg2 = PG_GETARG_INT16(1);
     924             :     int16       result;
     925             : 
     926         120 :     if (unlikely(pg_sub_s16_overflow(arg1, arg2, &result)))
     927           6 :         ereport(ERROR,
     928             :                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
     929             :                  errmsg("smallint out of range")));
     930         114 :     PG_RETURN_INT16(result);
     931             : }
     932             : 
     933             : Datum
     934          54 : int2mul(PG_FUNCTION_ARGS)
     935             : {
     936          54 :     int16       arg1 = PG_GETARG_INT16(0);
     937          54 :     int16       arg2 = PG_GETARG_INT16(1);
     938             :     int16       result;
     939             : 
     940          54 :     if (unlikely(pg_mul_s16_overflow(arg1, arg2, &result)))
     941          12 :         ereport(ERROR,
     942             :                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
     943             :                  errmsg("smallint out of range")));
     944             : 
     945          42 :     PG_RETURN_INT16(result);
     946             : }
     947             : 
     948             : Datum
     949          42 : int2div(PG_FUNCTION_ARGS)
     950             : {
     951          42 :     int16       arg1 = PG_GETARG_INT16(0);
     952          42 :     int16       arg2 = PG_GETARG_INT16(1);
     953             :     int16       result;
     954             : 
     955          42 :     if (arg2 == 0)
     956             :     {
     957           0 :         ereport(ERROR,
     958             :                 (errcode(ERRCODE_DIVISION_BY_ZERO),
     959             :                  errmsg("division by zero")));
     960             :         /* ensure compiler realizes we mustn't reach the division (gcc bug) */
     961             :         PG_RETURN_NULL();
     962             :     }
     963             : 
     964             :     /*
     965             :      * SHRT_MIN / -1 is problematic, since the result can't be represented on
     966             :      * a two's-complement machine.  Some machines produce SHRT_MIN, some
     967             :      * produce zero, some throw an exception.  We can dodge the problem by
     968             :      * recognizing that division by -1 is the same as negation.
     969             :      */
     970          42 :     if (arg2 == -1)
     971             :     {
     972           6 :         if (unlikely(arg1 == PG_INT16_MIN))
     973           6 :             ereport(ERROR,
     974             :                     (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
     975             :                      errmsg("smallint out of range")));
     976           0 :         result = -arg1;
     977           0 :         PG_RETURN_INT16(result);
     978             :     }
     979             : 
     980             :     /* No overflow is possible */
     981             : 
     982          36 :     result = arg1 / arg2;
     983             : 
     984          36 :     PG_RETURN_INT16(result);
     985             : }
     986             : 
     987             : Datum
     988        2220 : int24pl(PG_FUNCTION_ARGS)
     989             : {
     990        2220 :     int16       arg1 = PG_GETARG_INT16(0);
     991        2220 :     int32       arg2 = PG_GETARG_INT32(1);
     992             :     int32       result;
     993             : 
     994        2220 :     if (unlikely(pg_add_s32_overflow((int32) arg1, arg2, &result)))
     995           0 :         ereport(ERROR,
     996             :                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
     997             :                  errmsg("integer out of range")));
     998        2220 :     PG_RETURN_INT32(result);
     999             : }
    1000             : 
    1001             : Datum
    1002       25246 : int24mi(PG_FUNCTION_ARGS)
    1003             : {
    1004       25246 :     int16       arg1 = PG_GETARG_INT16(0);
    1005       25246 :     int32       arg2 = PG_GETARG_INT32(1);
    1006             :     int32       result;
    1007             : 
    1008       25246 :     if (unlikely(pg_sub_s32_overflow((int32) arg1, arg2, &result)))
    1009           0 :         ereport(ERROR,
    1010             :                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
    1011             :                  errmsg("integer out of range")));
    1012       25246 :     PG_RETURN_INT32(result);
    1013             : }
    1014             : 
    1015             : Datum
    1016          36 : int24mul(PG_FUNCTION_ARGS)
    1017             : {
    1018          36 :     int16       arg1 = PG_GETARG_INT16(0);
    1019          36 :     int32       arg2 = PG_GETARG_INT32(1);
    1020             :     int32       result;
    1021             : 
    1022          36 :     if (unlikely(pg_mul_s32_overflow((int32) arg1, arg2, &result)))
    1023           0 :         ereport(ERROR,
    1024             :                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
    1025             :                  errmsg("integer out of range")));
    1026          36 :     PG_RETURN_INT32(result);
    1027             : }
    1028             : 
    1029             : Datum
    1030          42 : int24div(PG_FUNCTION_ARGS)
    1031             : {
    1032          42 :     int16       arg1 = PG_GETARG_INT16(0);
    1033          42 :     int32       arg2 = PG_GETARG_INT32(1);
    1034             : 
    1035          42 :     if (unlikely(arg2 == 0))
    1036             :     {
    1037           6 :         ereport(ERROR,
    1038             :                 (errcode(ERRCODE_DIVISION_BY_ZERO),
    1039             :                  errmsg("division by zero")));
    1040             :         /* ensure compiler realizes we mustn't reach the division (gcc bug) */
    1041             :         PG_RETURN_NULL();
    1042             :     }
    1043             : 
    1044             :     /* No overflow is possible */
    1045          36 :     PG_RETURN_INT32((int32) arg1 / arg2);
    1046             : }
    1047             : 
    1048             : Datum
    1049          48 : int42pl(PG_FUNCTION_ARGS)
    1050             : {
    1051          48 :     int32       arg1 = PG_GETARG_INT32(0);
    1052          48 :     int16       arg2 = PG_GETARG_INT16(1);
    1053             :     int32       result;
    1054             : 
    1055          48 :     if (unlikely(pg_add_s32_overflow(arg1, (int32) arg2, &result)))
    1056           6 :         ereport(ERROR,
    1057             :                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
    1058             :                  errmsg("integer out of range")));
    1059          42 :     PG_RETURN_INT32(result);
    1060             : }
    1061             : 
    1062             : Datum
    1063          54 : int42mi(PG_FUNCTION_ARGS)
    1064             : {
    1065          54 :     int32       arg1 = PG_GETARG_INT32(0);
    1066          54 :     int16       arg2 = PG_GETARG_INT16(1);
    1067             :     int32       result;
    1068             : 
    1069          54 :     if (unlikely(pg_sub_s32_overflow(arg1, (int32) arg2, &result)))
    1070           6 :         ereport(ERROR,
    1071             :                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
    1072             :                  errmsg("integer out of range")));
    1073          48 :     PG_RETURN_INT32(result);
    1074             : }
    1075             : 
    1076             : Datum
    1077          54 : int42mul(PG_FUNCTION_ARGS)
    1078             : {
    1079          54 :     int32       arg1 = PG_GETARG_INT32(0);
    1080          54 :     int16       arg2 = PG_GETARG_INT16(1);
    1081             :     int32       result;
    1082             : 
    1083          54 :     if (unlikely(pg_mul_s32_overflow(arg1, (int32) arg2, &result)))
    1084          12 :         ereport(ERROR,
    1085             :                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
    1086             :                  errmsg("integer out of range")));
    1087          42 :     PG_RETURN_INT32(result);
    1088             : }
    1089             : 
    1090             : Datum
    1091          48 : int42div(PG_FUNCTION_ARGS)
    1092             : {
    1093          48 :     int32       arg1 = PG_GETARG_INT32(0);
    1094          48 :     int16       arg2 = PG_GETARG_INT16(1);
    1095             :     int32       result;
    1096             : 
    1097          48 :     if (unlikely(arg2 == 0))
    1098             :     {
    1099           6 :         ereport(ERROR,
    1100             :                 (errcode(ERRCODE_DIVISION_BY_ZERO),
    1101             :                  errmsg("division by zero")));
    1102             :         /* ensure compiler realizes we mustn't reach the division (gcc bug) */
    1103             :         PG_RETURN_NULL();
    1104             :     }
    1105             : 
    1106             :     /*
    1107             :      * INT_MIN / -1 is problematic, since the result can't be represented on a
    1108             :      * two's-complement machine.  Some machines produce INT_MIN, some produce
    1109             :      * zero, some throw an exception.  We can dodge the problem by recognizing
    1110             :      * that division by -1 is the same as negation.
    1111             :      */
    1112          42 :     if (arg2 == -1)
    1113             :     {
    1114           6 :         if (unlikely(arg1 == PG_INT32_MIN))
    1115           6 :             ereport(ERROR,
    1116             :                     (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
    1117             :                      errmsg("integer out of range")));
    1118           0 :         result = -arg1;
    1119           0 :         PG_RETURN_INT32(result);
    1120             :     }
    1121             : 
    1122             :     /* No overflow is possible */
    1123             : 
    1124          36 :     result = arg1 / arg2;
    1125             : 
    1126          36 :     PG_RETURN_INT32(result);
    1127             : }
    1128             : 
    1129             : Datum
    1130     7112254 : int4mod(PG_FUNCTION_ARGS)
    1131             : {
    1132     7112254 :     int32       arg1 = PG_GETARG_INT32(0);
    1133     7112254 :     int32       arg2 = PG_GETARG_INT32(1);
    1134             : 
    1135     7112254 :     if (unlikely(arg2 == 0))
    1136             :     {
    1137           0 :         ereport(ERROR,
    1138             :                 (errcode(ERRCODE_DIVISION_BY_ZERO),
    1139             :                  errmsg("division by zero")));
    1140             :         /* ensure compiler realizes we mustn't reach the division (gcc bug) */
    1141             :         PG_RETURN_NULL();
    1142             :     }
    1143             : 
    1144             :     /*
    1145             :      * Some machines throw a floating-point exception for INT_MIN % -1, which
    1146             :      * is a bit silly since the correct answer is perfectly well-defined,
    1147             :      * namely zero.
    1148             :      */
    1149     7112254 :     if (arg2 == -1)
    1150          12 :         PG_RETURN_INT32(0);
    1151             : 
    1152             :     /* No overflow is possible */
    1153             : 
    1154     7112242 :     PG_RETURN_INT32(arg1 % arg2);
    1155             : }
    1156             : 
    1157             : Datum
    1158          36 : int2mod(PG_FUNCTION_ARGS)
    1159             : {
    1160          36 :     int16       arg1 = PG_GETARG_INT16(0);
    1161          36 :     int16       arg2 = PG_GETARG_INT16(1);
    1162             : 
    1163          36 :     if (unlikely(arg2 == 0))
    1164             :     {
    1165           0 :         ereport(ERROR,
    1166             :                 (errcode(ERRCODE_DIVISION_BY_ZERO),
    1167             :                  errmsg("division by zero")));
    1168             :         /* ensure compiler realizes we mustn't reach the division (gcc bug) */
    1169             :         PG_RETURN_NULL();
    1170             :     }
    1171             : 
    1172             :     /*
    1173             :      * Some machines throw a floating-point exception for INT_MIN % -1, which
    1174             :      * is a bit silly since the correct answer is perfectly well-defined,
    1175             :      * namely zero.  (It's not clear this ever happens when dealing with
    1176             :      * int16, but we might as well have the test for safety.)
    1177             :      */
    1178          36 :     if (arg2 == -1)
    1179           6 :         PG_RETURN_INT16(0);
    1180             : 
    1181             :     /* No overflow is possible */
    1182             : 
    1183          30 :     PG_RETURN_INT16(arg1 % arg2);
    1184             : }
    1185             : 
    1186             : 
    1187             : /* int[24]abs()
    1188             :  * Absolute value
    1189             :  */
    1190             : Datum
    1191      128810 : int4abs(PG_FUNCTION_ARGS)
    1192             : {
    1193      128810 :     int32       arg1 = PG_GETARG_INT32(0);
    1194             :     int32       result;
    1195             : 
    1196      128810 :     if (unlikely(arg1 == PG_INT32_MIN))
    1197           0 :         ereport(ERROR,
    1198             :                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
    1199             :                  errmsg("integer out of range")));
    1200      128810 :     result = (arg1 < 0) ? -arg1 : arg1;
    1201      128810 :     PG_RETURN_INT32(result);
    1202             : }
    1203             : 
    1204             : Datum
    1205          30 : int2abs(PG_FUNCTION_ARGS)
    1206             : {
    1207          30 :     int16       arg1 = PG_GETARG_INT16(0);
    1208             :     int16       result;
    1209             : 
    1210          30 :     if (unlikely(arg1 == PG_INT16_MIN))
    1211           0 :         ereport(ERROR,
    1212             :                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
    1213             :                  errmsg("smallint out of range")));
    1214          30 :     result = (arg1 < 0) ? -arg1 : arg1;
    1215          30 :     PG_RETURN_INT16(result);
    1216             : }
    1217             : 
    1218             : /*
    1219             :  * Greatest Common Divisor
    1220             :  *
    1221             :  * Returns the largest positive integer that exactly divides both inputs.
    1222             :  * Special cases:
    1223             :  *   - gcd(x, 0) = gcd(0, x) = abs(x)
    1224             :  *          because 0 is divisible by anything
    1225             :  *   - gcd(0, 0) = 0
    1226             :  *          complies with the previous definition and is a common convention
    1227             :  *
    1228             :  * Special care must be taken if either input is INT_MIN --- gcd(0, INT_MIN),
    1229             :  * gcd(INT_MIN, 0) and gcd(INT_MIN, INT_MIN) are all equal to abs(INT_MIN),
    1230             :  * which cannot be represented as a 32-bit signed integer.
    1231             :  */
    1232             : static int32
    1233         264 : int4gcd_internal(int32 arg1, int32 arg2)
    1234             : {
    1235             :     int32       swap;
    1236             :     int32       a1,
    1237             :                 a2;
    1238             : 
    1239             :     /*
    1240             :      * Put the greater absolute value in arg1.
    1241             :      *
    1242             :      * This would happen automatically in the loop below, but avoids an
    1243             :      * expensive modulo operation, and simplifies the special-case handling
    1244             :      * for INT_MIN below.
    1245             :      *
    1246             :      * We do this in negative space in order to handle INT_MIN.
    1247             :      */
    1248         264 :     a1 = (arg1 < 0) ? arg1 : -arg1;
    1249         264 :     a2 = (arg2 < 0) ? arg2 : -arg2;
    1250         264 :     if (a1 > a2)
    1251             :     {
    1252          96 :         swap = arg1;
    1253          96 :         arg1 = arg2;
    1254          96 :         arg2 = swap;
    1255             :     }
    1256             : 
    1257             :     /* Special care needs to be taken with INT_MIN.  See comments above. */
    1258         264 :     if (arg1 == PG_INT32_MIN)
    1259             :     {
    1260          90 :         if (arg2 == 0 || arg2 == PG_INT32_MIN)
    1261          12 :             ereport(ERROR,
    1262             :                     (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
    1263             :                      errmsg("integer out of range")));
    1264             : 
    1265             :         /*
    1266             :          * Some machines throw a floating-point exception for INT_MIN % -1,
    1267             :          * which is a bit silly since the correct answer is perfectly
    1268             :          * well-defined, namely zero.  Guard against this and just return the
    1269             :          * result, gcd(INT_MIN, -1) = 1.
    1270             :          */
    1271          78 :         if (arg2 == -1)
    1272          12 :             return 1;
    1273             :     }
    1274             : 
    1275             :     /* Use the Euclidean algorithm to find the GCD */
    1276         942 :     while (arg2 != 0)
    1277             :     {
    1278         702 :         swap = arg2;
    1279         702 :         arg2 = arg1 % arg2;
    1280         702 :         arg1 = swap;
    1281             :     }
    1282             : 
    1283             :     /*
    1284             :      * Make sure the result is positive. (We know we don't have INT_MIN
    1285             :      * anymore).
    1286             :      */
    1287         240 :     if (arg1 < 0)
    1288         102 :         arg1 = -arg1;
    1289             : 
    1290         240 :     return arg1;
    1291             : }
    1292             : 
    1293             : Datum
    1294         180 : int4gcd(PG_FUNCTION_ARGS)
    1295             : {
    1296         180 :     int32       arg1 = PG_GETARG_INT32(0);
    1297         180 :     int32       arg2 = PG_GETARG_INT32(1);
    1298             :     int32       result;
    1299             : 
    1300         180 :     result = int4gcd_internal(arg1, arg2);
    1301             : 
    1302         168 :     PG_RETURN_INT32(result);
    1303             : }
    1304             : 
    1305             : /*
    1306             :  * Least Common Multiple
    1307             :  */
    1308             : Datum
    1309         156 : int4lcm(PG_FUNCTION_ARGS)
    1310             : {
    1311         156 :     int32       arg1 = PG_GETARG_INT32(0);
    1312         156 :     int32       arg2 = PG_GETARG_INT32(1);
    1313             :     int32       gcd;
    1314             :     int32       result;
    1315             : 
    1316             :     /*
    1317             :      * Handle lcm(x, 0) = lcm(0, x) = 0 as a special case.  This prevents a
    1318             :      * division-by-zero error below when x is zero, and an overflow error from
    1319             :      * the GCD computation when x = INT_MIN.
    1320             :      */
    1321         156 :     if (arg1 == 0 || arg2 == 0)
    1322          72 :         PG_RETURN_INT32(0);
    1323             : 
    1324             :     /* lcm(x, y) = abs(x / gcd(x, y) * y) */
    1325          84 :     gcd = int4gcd_internal(arg1, arg2);
    1326          84 :     arg1 = arg1 / gcd;
    1327             : 
    1328          84 :     if (unlikely(pg_mul_s32_overflow(arg1, arg2, &result)))
    1329           6 :         ereport(ERROR,
    1330             :                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
    1331             :                  errmsg("integer out of range")));
    1332             : 
    1333             :     /* If the result is INT_MIN, it cannot be represented. */
    1334          78 :     if (unlikely(result == PG_INT32_MIN))
    1335           6 :         ereport(ERROR,
    1336             :                 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
    1337             :                  errmsg("integer out of range")));
    1338             : 
    1339          72 :     if (result < 0)
    1340          36 :         result = -result;
    1341             : 
    1342          72 :     PG_RETURN_INT32(result);
    1343             : }
    1344             : 
    1345             : Datum
    1346         402 : int2larger(PG_FUNCTION_ARGS)
    1347             : {
    1348         402 :     int16       arg1 = PG_GETARG_INT16(0);
    1349         402 :     int16       arg2 = PG_GETARG_INT16(1);
    1350             : 
    1351         402 :     PG_RETURN_INT16((arg1 > arg2) ? arg1 : arg2);
    1352             : }
    1353             : 
    1354             : Datum
    1355           0 : int2smaller(PG_FUNCTION_ARGS)
    1356             : {
    1357           0 :     int16       arg1 = PG_GETARG_INT16(0);
    1358           0 :     int16       arg2 = PG_GETARG_INT16(1);
    1359             : 
    1360           0 :     PG_RETURN_INT16((arg1 < arg2) ? arg1 : arg2);
    1361             : }
    1362             : 
    1363             : Datum
    1364      322020 : int4larger(PG_FUNCTION_ARGS)
    1365             : {
    1366      322020 :     int32       arg1 = PG_GETARG_INT32(0);
    1367      322020 :     int32       arg2 = PG_GETARG_INT32(1);
    1368             : 
    1369      322020 :     PG_RETURN_INT32((arg1 > arg2) ? arg1 : arg2);
    1370             : }
    1371             : 
    1372             : Datum
    1373      251960 : int4smaller(PG_FUNCTION_ARGS)
    1374             : {
    1375      251960 :     int32       arg1 = PG_GETARG_INT32(0);
    1376      251960 :     int32       arg2 = PG_GETARG_INT32(1);
    1377             : 
    1378      251960 :     PG_RETURN_INT32((arg1 < arg2) ? arg1 : arg2);
    1379             : }
    1380             : 
    1381             : /*
    1382             :  * Bit-pushing operators
    1383             :  *
    1384             :  *      int[24]and      - returns arg1 & arg2
    1385             :  *      int[24]or       - returns arg1 | arg2
    1386             :  *      int[24]xor      - returns arg1 # arg2
    1387             :  *      int[24]not      - returns ~arg1
    1388             :  *      int[24]shl      - returns arg1 << arg2
    1389             :  *      int[24]shr      - returns arg1 >> arg2
    1390             :  */
    1391             : 
    1392             : Datum
    1393        5670 : int4and(PG_FUNCTION_ARGS)
    1394             : {
    1395        5670 :     int32       arg1 = PG_GETARG_INT32(0);
    1396        5670 :     int32       arg2 = PG_GETARG_INT32(1);
    1397             : 
    1398        5670 :     PG_RETURN_INT32(arg1 & arg2);
    1399             : }
    1400             : 
    1401             : Datum
    1402          18 : int4or(PG_FUNCTION_ARGS)
    1403             : {
    1404          18 :     int32       arg1 = PG_GETARG_INT32(0);
    1405          18 :     int32       arg2 = PG_GETARG_INT32(1);
    1406             : 
    1407          18 :     PG_RETURN_INT32(arg1 | arg2);
    1408             : }
    1409             : 
    1410             : Datum
    1411          18 : int4xor(PG_FUNCTION_ARGS)
    1412             : {
    1413          18 :     int32       arg1 = PG_GETARG_INT32(0);
    1414          18 :     int32       arg2 = PG_GETARG_INT32(1);
    1415             : 
    1416          18 :     PG_RETURN_INT32(arg1 ^ arg2);
    1417             : }
    1418             : 
    1419             : Datum
    1420        1548 : int4shl(PG_FUNCTION_ARGS)
    1421             : {
    1422        1548 :     int32       arg1 = PG_GETARG_INT32(0);
    1423        1548 :     int32       arg2 = PG_GETARG_INT32(1);
    1424             : 
    1425        1548 :     PG_RETURN_INT32(arg1 << arg2);
    1426             : }
    1427             : 
    1428             : Datum
    1429           0 : int4shr(PG_FUNCTION_ARGS)
    1430             : {
    1431           0 :     int32       arg1 = PG_GETARG_INT32(0);
    1432           0 :     int32       arg2 = PG_GETARG_INT32(1);
    1433             : 
    1434           0 :     PG_RETURN_INT32(arg1 >> arg2);
    1435             : }
    1436             : 
    1437             : Datum
    1438           0 : int4not(PG_FUNCTION_ARGS)
    1439             : {
    1440           0 :     int32       arg1 = PG_GETARG_INT32(0);
    1441             : 
    1442           0 :     PG_RETURN_INT32(~arg1);
    1443             : }
    1444             : 
    1445             : Datum
    1446          24 : int2and(PG_FUNCTION_ARGS)
    1447             : {
    1448          24 :     int16       arg1 = PG_GETARG_INT16(0);
    1449          24 :     int16       arg2 = PG_GETARG_INT16(1);
    1450             : 
    1451          24 :     PG_RETURN_INT16(arg1 & arg2);
    1452             : }
    1453             : 
    1454             : Datum
    1455          24 : int2or(PG_FUNCTION_ARGS)
    1456             : {
    1457          24 :     int16       arg1 = PG_GETARG_INT16(0);
    1458          24 :     int16       arg2 = PG_GETARG_INT16(1);
    1459             : 
    1460          24 :     PG_RETURN_INT16(arg1 | arg2);
    1461             : }
    1462             : 
    1463             : Datum
    1464          24 : int2xor(PG_FUNCTION_ARGS)
    1465             : {
    1466          24 :     int16       arg1 = PG_GETARG_INT16(0);
    1467          24 :     int16       arg2 = PG_GETARG_INT16(1);
    1468             : 
    1469          24 :     PG_RETURN_INT16(arg1 ^ arg2);
    1470             : }
    1471             : 
    1472             : Datum
    1473           0 : int2not(PG_FUNCTION_ARGS)
    1474             : {
    1475           0 :     int16       arg1 = PG_GETARG_INT16(0);
    1476             : 
    1477           0 :     PG_RETURN_INT16(~arg1);
    1478             : }
    1479             : 
    1480             : 
    1481             : Datum
    1482          12 : int2shl(PG_FUNCTION_ARGS)
    1483             : {
    1484          12 :     int16       arg1 = PG_GETARG_INT16(0);
    1485          12 :     int32       arg2 = PG_GETARG_INT32(1);
    1486             : 
    1487          12 :     PG_RETURN_INT16(arg1 << arg2);
    1488             : }
    1489             : 
    1490             : Datum
    1491           0 : int2shr(PG_FUNCTION_ARGS)
    1492             : {
    1493           0 :     int16       arg1 = PG_GETARG_INT16(0);
    1494           0 :     int32       arg2 = PG_GETARG_INT32(1);
    1495             : 
    1496           0 :     PG_RETURN_INT16(arg1 >> arg2);
    1497             : }
    1498             : 
    1499             : /*
    1500             :  * non-persistent numeric series generator
    1501             :  */
    1502             : Datum
    1503    14096090 : generate_series_int4(PG_FUNCTION_ARGS)
    1504             : {
    1505    14096090 :     return generate_series_step_int4(fcinfo);
    1506             : }
    1507             : 
    1508             : Datum
    1509    14461348 : generate_series_step_int4(PG_FUNCTION_ARGS)
    1510             : {
    1511             :     FuncCallContext *funcctx;
    1512             :     generate_series_fctx *fctx;
    1513             :     int32       result;
    1514             :     MemoryContext oldcontext;
    1515             : 
    1516             :     /* stuff done only on the first call of the function */
    1517    14461348 :     if (SRF_IS_FIRSTCALL())
    1518             :     {
    1519       14378 :         int32       start = PG_GETARG_INT32(0);
    1520       14378 :         int32       finish = PG_GETARG_INT32(1);
    1521       14378 :         int32       step = 1;
    1522             : 
    1523             :         /* see if we were given an explicit step size */
    1524       14378 :         if (PG_NARGS() == 3)
    1525         392 :             step = PG_GETARG_INT32(2);
    1526       14378 :         if (step == 0)
    1527           0 :             ereport(ERROR,
    1528             :                     (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
    1529             :                      errmsg("step size cannot equal zero")));
    1530             : 
    1531             :         /* create a function context for cross-call persistence */
    1532       14378 :         funcctx = SRF_FIRSTCALL_INIT();
    1533             : 
    1534             :         /*
    1535             :          * switch to memory context appropriate for multiple function calls
    1536             :          */
    1537       14378 :         oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
    1538             : 
    1539             :         /* allocate memory for user context */
    1540       14378 :         fctx = (generate_series_fctx *) palloc(sizeof(generate_series_fctx));
    1541             : 
    1542             :         /*
    1543             :          * Use fctx to keep state from call to call. Seed current with the
    1544             :          * original start value
    1545             :          */
    1546       14378 :         fctx->current = start;
    1547       14378 :         fctx->finish = finish;
    1548       14378 :         fctx->step = step;
    1549             : 
    1550       14378 :         funcctx->user_fctx = fctx;
    1551       14378 :         MemoryContextSwitchTo(oldcontext);
    1552             :     }
    1553             : 
    1554             :     /* stuff done on every call of the function */
    1555    14461348 :     funcctx = SRF_PERCALL_SETUP();
    1556             : 
    1557             :     /*
    1558             :      * get the saved state and use current as the result for this iteration
    1559             :      */
    1560    14461348 :     fctx = funcctx->user_fctx;
    1561    14461348 :     result = fctx->current;
    1562             : 
    1563    14461348 :     if ((fctx->step > 0 && fctx->current <= fctx->finish) ||
    1564      214340 :         (fctx->step < 0 && fctx->current >= fctx->finish))
    1565             :     {
    1566             :         /*
    1567             :          * Increment current in preparation for next iteration. If next-value
    1568             :          * computation overflows, this is the final result.
    1569             :          */
    1570    14447018 :         if (pg_add_s32_overflow(fctx->current, fctx->step, &fctx->current))
    1571           0 :             fctx->step = 0;
    1572             : 
    1573             :         /* do when there is more left to send */
    1574    14447018 :         SRF_RETURN_NEXT(funcctx, Int32GetDatum(result));
    1575             :     }
    1576             :     else
    1577             :         /* do when there is no more left */
    1578       14330 :         SRF_RETURN_DONE(funcctx);
    1579             : }
    1580             : 
    1581             : /*
    1582             :  * Planner support function for generate_series(int4, int4 [, int4])
    1583             :  */
    1584             : Datum
    1585       33792 : generate_series_int4_support(PG_FUNCTION_ARGS)
    1586             : {
    1587       33792 :     Node       *rawreq = (Node *) PG_GETARG_POINTER(0);
    1588       33792 :     Node       *ret = NULL;
    1589             : 
    1590       33792 :     if (IsA(rawreq, SupportRequestRows))
    1591             :     {
    1592             :         /* Try to estimate the number of rows returned */
    1593       11112 :         SupportRequestRows *req = (SupportRequestRows *) rawreq;
    1594             : 
    1595       11112 :         if (is_funcclause(req->node))    /* be paranoid */
    1596             :         {
    1597       11112 :             List       *args = ((FuncExpr *) req->node)->args;
    1598             :             Node       *arg1,
    1599             :                        *arg2,
    1600             :                        *arg3;
    1601             : 
    1602             :             /* We can use estimated argument values here */
    1603       11112 :             arg1 = estimate_expression_value(req->root, linitial(args));
    1604       11112 :             arg2 = estimate_expression_value(req->root, lsecond(args));
    1605       11112 :             if (list_length(args) >= 3)
    1606         416 :                 arg3 = estimate_expression_value(req->root, lthird(args));
    1607             :             else
    1608       10696 :                 arg3 = NULL;
    1609             : 
    1610             :             /*
    1611             :              * If any argument is constant NULL, we can safely assume that
    1612             :              * zero rows are returned.  Otherwise, if they're all non-NULL
    1613             :              * constants, we can calculate the number of rows that will be
    1614             :              * returned.  Use double arithmetic to avoid overflow hazards.
    1615             :              */
    1616       11112 :             if ((IsA(arg1, Const) &&
    1617       10962 :                  ((Const *) arg1)->constisnull) ||
    1618       11112 :                 (IsA(arg2, Const) &&
    1619       11112 :                  ((Const *) arg2)->constisnull) ||
    1620         416 :                 (arg3 != NULL && IsA(arg3, Const) &&
    1621         416 :                  ((Const *) arg3)->constisnull))
    1622             :             {
    1623           0 :                 req->rows = 0;
    1624           0 :                 ret = (Node *) req;
    1625             :             }
    1626       11112 :             else if (IsA(arg1, Const) &&
    1627       10962 :                      IsA(arg2, Const) &&
    1628         416 :                      (arg3 == NULL || IsA(arg3, Const)))
    1629             :             {
    1630             :                 double      start,
    1631             :                             finish,
    1632             :                             step;
    1633             : 
    1634        7600 :                 start = DatumGetInt32(((Const *) arg1)->constvalue);
    1635        7600 :                 finish = DatumGetInt32(((Const *) arg2)->constvalue);
    1636        7600 :                 step = arg3 ? DatumGetInt32(((Const *) arg3)->constvalue) : 1;
    1637             : 
    1638             :                 /* This equation works for either sign of step */
    1639        7600 :                 if (step != 0)
    1640             :                 {
    1641        7600 :                     req->rows = floor((finish - start + step) / step);
    1642        7600 :                     ret = (Node *) req;
    1643             :                 }
    1644             :             }
    1645             :         }
    1646             :     }
    1647             : 
    1648       33792 :     PG_RETURN_POINTER(ret);
    1649             : }

Generated by: LCOV version 1.14