Coverage Report

Created: 2025-06-15 06:31

/src/postgres/src/backend/utils/adt/int.c
Line
Count
Source (jump to first uncovered line)
1
/*-------------------------------------------------------------------------
2
 *
3
 * int.c
4
 *    Functions for the built-in integer types (except int8).
5
 *
6
 * Portions Copyright (c) 1996-2025, 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
0
#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
int2in(PG_FUNCTION_ARGS)
64
0
{
65
0
  char     *num = PG_GETARG_CSTRING(0);
66
67
0
  PG_RETURN_INT16(pg_strtoint16_safe(num, fcinfo->context));
68
0
}
69
70
/*
71
 *    int2out     - converts short to "num"
72
 */
73
Datum
74
int2out(PG_FUNCTION_ARGS)
75
0
{
76
0
  int16   arg1 = PG_GETARG_INT16(0);
77
0
  char     *result = (char *) palloc(7);  /* sign, 5 digits, '\0' */
78
79
0
  pg_itoa(arg1, result);
80
0
  PG_RETURN_CSTRING(result);
81
0
}
82
83
/*
84
 *    int2recv      - converts external binary format to int2
85
 */
86
Datum
87
int2recv(PG_FUNCTION_ARGS)
88
0
{
89
0
  StringInfo  buf = (StringInfo) PG_GETARG_POINTER(0);
90
91
0
  PG_RETURN_INT16((int16) pq_getmsgint(buf, sizeof(int16)));
92
0
}
93
94
/*
95
 *    int2send      - converts int2 to binary format
96
 */
97
Datum
98
int2send(PG_FUNCTION_ARGS)
99
0
{
100
0
  int16   arg1 = PG_GETARG_INT16(0);
101
0
  StringInfoData buf;
102
103
0
  pq_begintypsend(&buf);
104
0
  pq_sendint16(&buf, arg1);
105
0
  PG_RETURN_BYTEA_P(pq_endtypsend(&buf));
106
0
}
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
buildint2vector(const int16 *int2s, int n)
115
0
{
116
0
  int2vector *result;
117
118
0
  result = (int2vector *) palloc0(Int2VectorSize(n));
119
120
0
  if (n > 0 && int2s)
121
0
    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
0
  SET_VARSIZE(result, Int2VectorSize(n));
128
0
  result->ndim = 1;
129
0
  result->dataoffset = 0;   /* never any nulls */
130
0
  result->elemtype = INT2OID;
131
0
  result->dim1 = n;
132
0
  result->lbound1 = 0;
133
134
0
  return result;
135
0
}
136
137
/*
138
 *    int2vectorin      - converts "num num ..." to internal form
139
 */
140
Datum
141
int2vectorin(PG_FUNCTION_ARGS)
142
0
{
143
0
  char     *intString = PG_GETARG_CSTRING(0);
144
0
  Node     *escontext = fcinfo->context;
145
0
  int2vector *result;
146
0
  int     nalloc;
147
0
  int     n;
148
149
0
  nalloc = 32;        /* arbitrary initial size guess */
150
0
  result = (int2vector *) palloc0(Int2VectorSize(nalloc));
151
152
0
  for (n = 0;; n++)
153
0
  {
154
0
    long    l;
155
0
    char     *endp;
156
157
0
    while (*intString && isspace((unsigned char) *intString))
158
0
      intString++;
159
0
    if (*intString == '\0')
160
0
      break;
161
162
0
    if (n >= nalloc)
163
0
    {
164
0
      nalloc *= 2;
165
0
      result = (int2vector *) repalloc(result, Int2VectorSize(nalloc));
166
0
    }
167
168
0
    errno = 0;
169
0
    l = strtol(intString, &endp, 10);
170
171
0
    if (intString == endp)
172
0
      ereturn(escontext, (Datum) 0,
173
0
          (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
174
0
           errmsg("invalid input syntax for type %s: \"%s\"",
175
0
              "smallint", intString)));
176
177
0
    if (errno == ERANGE || l < SHRT_MIN || l > SHRT_MAX)
178
0
      ereturn(escontext, (Datum) 0,
179
0
          (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
180
0
           errmsg("value \"%s\" is out of range for type %s", intString,
181
0
              "smallint")));
182
183
0
    if (*endp && *endp != ' ')
184
0
      ereturn(escontext, (Datum) 0,
185
0
          (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
186
0
           errmsg("invalid input syntax for type %s: \"%s\"",
187
0
              "smallint", intString)));
188
189
0
    result->values[n] = l;
190
0
    intString = endp;
191
0
  }
192
193
0
  SET_VARSIZE(result, Int2VectorSize(n));
194
0
  result->ndim = 1;
195
0
  result->dataoffset = 0;   /* never any nulls */
196
0
  result->elemtype = INT2OID;
197
0
  result->dim1 = n;
198
0
  result->lbound1 = 0;
199
200
0
  PG_RETURN_POINTER(result);
201
0
}
202
203
/*
204
 *    int2vectorout   - converts internal form to "num num ..."
205
 */
206
Datum
207
int2vectorout(PG_FUNCTION_ARGS)
208
0
{
209
0
  int2vector *int2Array = (int2vector *) PG_GETARG_POINTER(0);
210
0
  int     num,
211
0
        nnums = int2Array->dim1;
212
0
  char     *rp;
213
0
  char     *result;
214
215
  /* assumes sign, 5 digits, ' ' */
216
0
  rp = result = (char *) palloc(nnums * 7 + 1);
217
0
  for (num = 0; num < nnums; num++)
218
0
  {
219
0
    if (num != 0)
220
0
      *rp++ = ' ';
221
0
    rp += pg_itoa(int2Array->values[num], rp);
222
0
  }
223
0
  *rp = '\0';
224
0
  PG_RETURN_CSTRING(result);
225
0
}
226
227
/*
228
 *    int2vectorrecv      - converts external binary format to int2vector
229
 */
230
Datum
231
int2vectorrecv(PG_FUNCTION_ARGS)
232
0
{
233
0
  LOCAL_FCINFO(locfcinfo, 3);
234
0
  StringInfo  buf = (StringInfo) PG_GETARG_POINTER(0);
235
0
  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
0
               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
0
  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
0
        (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION),
264
0
         errmsg("invalid int2vector data")));
265
266
0
  PG_RETURN_POINTER(result);
267
0
}
268
269
/*
270
 *    int2vectorsend      - converts int2vector to binary format
271
 */
272
Datum
273
int2vectorsend(PG_FUNCTION_ARGS)
274
0
{
275
0
  return array_send(fcinfo);
276
0
}
277
278
279
/*****************************************************************************
280
 *   PUBLIC ROUTINES                             *
281
 *****************************************************************************/
282
283
/*
284
 *    int4in      - converts "num" to int4
285
 */
286
Datum
287
int4in(PG_FUNCTION_ARGS)
288
0
{
289
0
  char     *num = PG_GETARG_CSTRING(0);
290
291
0
  PG_RETURN_INT32(pg_strtoint32_safe(num, fcinfo->context));
292
0
}
293
294
/*
295
 *    int4out     - converts int4 to "num"
296
 */
297
Datum
298
int4out(PG_FUNCTION_ARGS)
299
0
{
300
0
  int32   arg1 = PG_GETARG_INT32(0);
301
0
  char     *result = (char *) palloc(12); /* sign, 10 digits, '\0' */
302
303
0
  pg_ltoa(arg1, result);
304
0
  PG_RETURN_CSTRING(result);
305
0
}
306
307
/*
308
 *    int4recv      - converts external binary format to int4
309
 */
310
Datum
311
int4recv(PG_FUNCTION_ARGS)
312
0
{
313
0
  StringInfo  buf = (StringInfo) PG_GETARG_POINTER(0);
314
315
0
  PG_RETURN_INT32((int32) pq_getmsgint(buf, sizeof(int32)));
316
0
}
317
318
/*
319
 *    int4send      - converts int4 to binary format
320
 */
321
Datum
322
int4send(PG_FUNCTION_ARGS)
323
0
{
324
0
  int32   arg1 = PG_GETARG_INT32(0);
325
0
  StringInfoData buf;
326
327
0
  pq_begintypsend(&buf);
328
0
  pq_sendint32(&buf, arg1);
329
0
  PG_RETURN_BYTEA_P(pq_endtypsend(&buf));
330
0
}
331
332
333
/*
334
 *    ===================
335
 *    CONVERSION ROUTINES
336
 *    ===================
337
 */
338
339
Datum
340
i2toi4(PG_FUNCTION_ARGS)
341
0
{
342
0
  int16   arg1 = PG_GETARG_INT16(0);
343
344
0
  PG_RETURN_INT32((int32) arg1);
345
0
}
346
347
Datum
348
i4toi2(PG_FUNCTION_ARGS)
349
0
{
350
0
  int32   arg1 = PG_GETARG_INT32(0);
351
352
0
  if (unlikely(arg1 < SHRT_MIN) || unlikely(arg1 > SHRT_MAX))
353
0
    ereport(ERROR,
354
0
        (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
355
0
         errmsg("smallint out of range")));
356
357
0
  PG_RETURN_INT16((int16) arg1);
358
0
}
359
360
/* Cast int4 -> bool */
361
Datum
362
int4_bool(PG_FUNCTION_ARGS)
363
0
{
364
0
  if (PG_GETARG_INT32(0) == 0)
365
0
    PG_RETURN_BOOL(false);
366
0
  else
367
0
    PG_RETURN_BOOL(true);
368
0
}
369
370
/* Cast bool -> int4 */
371
Datum
372
bool_int4(PG_FUNCTION_ARGS)
373
0
{
374
0
  if (PG_GETARG_BOOL(0) == false)
375
0
    PG_RETURN_INT32(0);
376
0
  else
377
0
    PG_RETURN_INT32(1);
378
0
}
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
int4eq(PG_FUNCTION_ARGS)
397
0
{
398
0
  int32   arg1 = PG_GETARG_INT32(0);
399
0
  int32   arg2 = PG_GETARG_INT32(1);
400
401
0
  PG_RETURN_BOOL(arg1 == arg2);
402
0
}
403
404
Datum
405
int4ne(PG_FUNCTION_ARGS)
406
0
{
407
0
  int32   arg1 = PG_GETARG_INT32(0);
408
0
  int32   arg2 = PG_GETARG_INT32(1);
409
410
0
  PG_RETURN_BOOL(arg1 != arg2);
411
0
}
412
413
Datum
414
int4lt(PG_FUNCTION_ARGS)
415
0
{
416
0
  int32   arg1 = PG_GETARG_INT32(0);
417
0
  int32   arg2 = PG_GETARG_INT32(1);
418
419
0
  PG_RETURN_BOOL(arg1 < arg2);
420
0
}
421
422
Datum
423
int4le(PG_FUNCTION_ARGS)
424
0
{
425
0
  int32   arg1 = PG_GETARG_INT32(0);
426
0
  int32   arg2 = PG_GETARG_INT32(1);
427
428
0
  PG_RETURN_BOOL(arg1 <= arg2);
429
0
}
430
431
Datum
432
int4gt(PG_FUNCTION_ARGS)
433
0
{
434
0
  int32   arg1 = PG_GETARG_INT32(0);
435
0
  int32   arg2 = PG_GETARG_INT32(1);
436
437
0
  PG_RETURN_BOOL(arg1 > arg2);
438
0
}
439
440
Datum
441
int4ge(PG_FUNCTION_ARGS)
442
0
{
443
0
  int32   arg1 = PG_GETARG_INT32(0);
444
0
  int32   arg2 = PG_GETARG_INT32(1);
445
446
0
  PG_RETURN_BOOL(arg1 >= arg2);
447
0
}
448
449
Datum
450
int2eq(PG_FUNCTION_ARGS)
451
0
{
452
0
  int16   arg1 = PG_GETARG_INT16(0);
453
0
  int16   arg2 = PG_GETARG_INT16(1);
454
455
0
  PG_RETURN_BOOL(arg1 == arg2);
456
0
}
457
458
Datum
459
int2ne(PG_FUNCTION_ARGS)
460
0
{
461
0
  int16   arg1 = PG_GETARG_INT16(0);
462
0
  int16   arg2 = PG_GETARG_INT16(1);
463
464
0
  PG_RETURN_BOOL(arg1 != arg2);
465
0
}
466
467
Datum
468
int2lt(PG_FUNCTION_ARGS)
469
0
{
470
0
  int16   arg1 = PG_GETARG_INT16(0);
471
0
  int16   arg2 = PG_GETARG_INT16(1);
472
473
0
  PG_RETURN_BOOL(arg1 < arg2);
474
0
}
475
476
Datum
477
int2le(PG_FUNCTION_ARGS)
478
0
{
479
0
  int16   arg1 = PG_GETARG_INT16(0);
480
0
  int16   arg2 = PG_GETARG_INT16(1);
481
482
0
  PG_RETURN_BOOL(arg1 <= arg2);
483
0
}
484
485
Datum
486
int2gt(PG_FUNCTION_ARGS)
487
0
{
488
0
  int16   arg1 = PG_GETARG_INT16(0);
489
0
  int16   arg2 = PG_GETARG_INT16(1);
490
491
0
  PG_RETURN_BOOL(arg1 > arg2);
492
0
}
493
494
Datum
495
int2ge(PG_FUNCTION_ARGS)
496
0
{
497
0
  int16   arg1 = PG_GETARG_INT16(0);
498
0
  int16   arg2 = PG_GETARG_INT16(1);
499
500
0
  PG_RETURN_BOOL(arg1 >= arg2);
501
0
}
502
503
Datum
504
int24eq(PG_FUNCTION_ARGS)
505
0
{
506
0
  int16   arg1 = PG_GETARG_INT16(0);
507
0
  int32   arg2 = PG_GETARG_INT32(1);
508
509
0
  PG_RETURN_BOOL(arg1 == arg2);
510
0
}
511
512
Datum
513
int24ne(PG_FUNCTION_ARGS)
514
0
{
515
0
  int16   arg1 = PG_GETARG_INT16(0);
516
0
  int32   arg2 = PG_GETARG_INT32(1);
517
518
0
  PG_RETURN_BOOL(arg1 != arg2);
519
0
}
520
521
Datum
522
int24lt(PG_FUNCTION_ARGS)
523
0
{
524
0
  int16   arg1 = PG_GETARG_INT16(0);
525
0
  int32   arg2 = PG_GETARG_INT32(1);
526
527
0
  PG_RETURN_BOOL(arg1 < arg2);
528
0
}
529
530
Datum
531
int24le(PG_FUNCTION_ARGS)
532
0
{
533
0
  int16   arg1 = PG_GETARG_INT16(0);
534
0
  int32   arg2 = PG_GETARG_INT32(1);
535
536
0
  PG_RETURN_BOOL(arg1 <= arg2);
537
0
}
538
539
Datum
540
int24gt(PG_FUNCTION_ARGS)
541
0
{
542
0
  int16   arg1 = PG_GETARG_INT16(0);
543
0
  int32   arg2 = PG_GETARG_INT32(1);
544
545
0
  PG_RETURN_BOOL(arg1 > arg2);
546
0
}
547
548
Datum
549
int24ge(PG_FUNCTION_ARGS)
550
0
{
551
0
  int16   arg1 = PG_GETARG_INT16(0);
552
0
  int32   arg2 = PG_GETARG_INT32(1);
553
554
0
  PG_RETURN_BOOL(arg1 >= arg2);
555
0
}
556
557
Datum
558
int42eq(PG_FUNCTION_ARGS)
559
0
{
560
0
  int32   arg1 = PG_GETARG_INT32(0);
561
0
  int16   arg2 = PG_GETARG_INT16(1);
562
563
0
  PG_RETURN_BOOL(arg1 == arg2);
564
0
}
565
566
Datum
567
int42ne(PG_FUNCTION_ARGS)
568
0
{
569
0
  int32   arg1 = PG_GETARG_INT32(0);
570
0
  int16   arg2 = PG_GETARG_INT16(1);
571
572
0
  PG_RETURN_BOOL(arg1 != arg2);
573
0
}
574
575
Datum
576
int42lt(PG_FUNCTION_ARGS)
577
0
{
578
0
  int32   arg1 = PG_GETARG_INT32(0);
579
0
  int16   arg2 = PG_GETARG_INT16(1);
580
581
0
  PG_RETURN_BOOL(arg1 < arg2);
582
0
}
583
584
Datum
585
int42le(PG_FUNCTION_ARGS)
586
0
{
587
0
  int32   arg1 = PG_GETARG_INT32(0);
588
0
  int16   arg2 = PG_GETARG_INT16(1);
589
590
0
  PG_RETURN_BOOL(arg1 <= arg2);
591
0
}
592
593
Datum
594
int42gt(PG_FUNCTION_ARGS)
595
0
{
596
0
  int32   arg1 = PG_GETARG_INT32(0);
597
0
  int16   arg2 = PG_GETARG_INT16(1);
598
599
0
  PG_RETURN_BOOL(arg1 > arg2);
600
0
}
601
602
Datum
603
int42ge(PG_FUNCTION_ARGS)
604
0
{
605
0
  int32   arg1 = PG_GETARG_INT32(0);
606
0
  int16   arg2 = PG_GETARG_INT16(1);
607
608
0
  PG_RETURN_BOOL(arg1 >= arg2);
609
0
}
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
in_range_int4_int4(PG_FUNCTION_ARGS)
624
0
{
625
0
  int32   val = PG_GETARG_INT32(0);
626
0
  int32   base = PG_GETARG_INT32(1);
627
0
  int32   offset = PG_GETARG_INT32(2);
628
0
  bool    sub = PG_GETARG_BOOL(3);
629
0
  bool    less = PG_GETARG_BOOL(4);
630
0
  int32   sum;
631
632
0
  if (offset < 0)
633
0
    ereport(ERROR,
634
0
        (errcode(ERRCODE_INVALID_PRECEDING_OR_FOLLOWING_SIZE),
635
0
         errmsg("invalid preceding or following size in window function")));
636
637
0
  if (sub)
638
0
    offset = -offset;   /* cannot overflow */
639
640
0
  if (unlikely(pg_add_s32_overflow(base, offset, &sum)))
641
0
  {
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
0
    PG_RETURN_BOOL(sub ? !less : less);
648
0
  }
649
650
0
  if (less)
651
0
    PG_RETURN_BOOL(val <= sum);
652
0
  else
653
0
    PG_RETURN_BOOL(val >= sum);
654
0
}
655
656
Datum
657
in_range_int4_int2(PG_FUNCTION_ARGS)
658
0
{
659
  /* Doesn't seem worth duplicating code for, so just invoke int4_int4 */
660
0
  return DirectFunctionCall5(in_range_int4_int4,
661
0
                 PG_GETARG_DATUM(0),
662
0
                 PG_GETARG_DATUM(1),
663
0
                 Int32GetDatum((int32) PG_GETARG_INT16(2)),
664
0
                 PG_GETARG_DATUM(3),
665
0
                 PG_GETARG_DATUM(4));
666
0
}
667
668
Datum
669
in_range_int4_int8(PG_FUNCTION_ARGS)
670
0
{
671
  /* We must do all the math in int64 */
672
0
  int64   val = (int64) PG_GETARG_INT32(0);
673
0
  int64   base = (int64) PG_GETARG_INT32(1);
674
0
  int64   offset = PG_GETARG_INT64(2);
675
0
  bool    sub = PG_GETARG_BOOL(3);
676
0
  bool    less = PG_GETARG_BOOL(4);
677
0
  int64   sum;
678
679
0
  if (offset < 0)
680
0
    ereport(ERROR,
681
0
        (errcode(ERRCODE_INVALID_PRECEDING_OR_FOLLOWING_SIZE),
682
0
         errmsg("invalid preceding or following size in window function")));
683
684
0
  if (sub)
685
0
    offset = -offset;   /* cannot overflow */
686
687
0
  if (unlikely(pg_add_s64_overflow(base, offset, &sum)))
688
0
  {
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
0
  }
696
697
0
  if (less)
698
0
    PG_RETURN_BOOL(val <= sum);
699
0
  else
700
0
    PG_RETURN_BOOL(val >= sum);
701
0
}
702
703
Datum
704
in_range_int2_int4(PG_FUNCTION_ARGS)
705
0
{
706
  /* We must do all the math in int32 */
707
0
  int32   val = (int32) PG_GETARG_INT16(0);
708
0
  int32   base = (int32) PG_GETARG_INT16(1);
709
0
  int32   offset = PG_GETARG_INT32(2);
710
0
  bool    sub = PG_GETARG_BOOL(3);
711
0
  bool    less = PG_GETARG_BOOL(4);
712
0
  int32   sum;
713
714
0
  if (offset < 0)
715
0
    ereport(ERROR,
716
0
        (errcode(ERRCODE_INVALID_PRECEDING_OR_FOLLOWING_SIZE),
717
0
         errmsg("invalid preceding or following size in window function")));
718
719
0
  if (sub)
720
0
    offset = -offset;   /* cannot overflow */
721
722
0
  if (unlikely(pg_add_s32_overflow(base, offset, &sum)))
723
0
  {
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
0
    PG_RETURN_BOOL(sub ? !less : less);
730
0
  }
731
732
0
  if (less)
733
0
    PG_RETURN_BOOL(val <= sum);
734
0
  else
735
0
    PG_RETURN_BOOL(val >= sum);
736
0
}
737
738
Datum
739
in_range_int2_int2(PG_FUNCTION_ARGS)
740
0
{
741
  /* Doesn't seem worth duplicating code for, so just invoke int2_int4 */
742
0
  return DirectFunctionCall5(in_range_int2_int4,
743
0
                 PG_GETARG_DATUM(0),
744
0
                 PG_GETARG_DATUM(1),
745
0
                 Int32GetDatum((int32) PG_GETARG_INT16(2)),
746
0
                 PG_GETARG_DATUM(3),
747
0
                 PG_GETARG_DATUM(4));
748
0
}
749
750
Datum
751
in_range_int2_int8(PG_FUNCTION_ARGS)
752
0
{
753
  /* Doesn't seem worth duplicating code for, so just invoke int4_int8 */
754
0
  return DirectFunctionCall5(in_range_int4_int8,
755
0
                 Int32GetDatum((int32) PG_GETARG_INT16(0)),
756
0
                 Int32GetDatum((int32) PG_GETARG_INT16(1)),
757
0
                 PG_GETARG_DATUM(2),
758
0
                 PG_GETARG_DATUM(3),
759
0
                 PG_GETARG_DATUM(4));
760
0
}
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
int4um(PG_FUNCTION_ARGS)
772
0
{
773
0
  int32   arg = PG_GETARG_INT32(0);
774
775
0
  if (unlikely(arg == PG_INT32_MIN))
776
0
    ereport(ERROR,
777
0
        (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
778
0
         errmsg("integer out of range")));
779
0
  PG_RETURN_INT32(-arg);
780
0
}
781
782
Datum
783
int4up(PG_FUNCTION_ARGS)
784
0
{
785
0
  int32   arg = PG_GETARG_INT32(0);
786
787
0
  PG_RETURN_INT32(arg);
788
0
}
789
790
Datum
791
int4pl(PG_FUNCTION_ARGS)
792
0
{
793
0
  int32   arg1 = PG_GETARG_INT32(0);
794
0
  int32   arg2 = PG_GETARG_INT32(1);
795
0
  int32   result;
796
797
0
  if (unlikely(pg_add_s32_overflow(arg1, arg2, &result)))
798
0
    ereport(ERROR,
799
0
        (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
800
0
         errmsg("integer out of range")));
801
0
  PG_RETURN_INT32(result);
802
0
}
803
804
Datum
805
int4mi(PG_FUNCTION_ARGS)
806
0
{
807
0
  int32   arg1 = PG_GETARG_INT32(0);
808
0
  int32   arg2 = PG_GETARG_INT32(1);
809
0
  int32   result;
810
811
0
  if (unlikely(pg_sub_s32_overflow(arg1, arg2, &result)))
812
0
    ereport(ERROR,
813
0
        (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
814
0
         errmsg("integer out of range")));
815
0
  PG_RETURN_INT32(result);
816
0
}
817
818
Datum
819
int4mul(PG_FUNCTION_ARGS)
820
0
{
821
0
  int32   arg1 = PG_GETARG_INT32(0);
822
0
  int32   arg2 = PG_GETARG_INT32(1);
823
0
  int32   result;
824
825
0
  if (unlikely(pg_mul_s32_overflow(arg1, arg2, &result)))
826
0
    ereport(ERROR,
827
0
        (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
828
0
         errmsg("integer out of range")));
829
0
  PG_RETURN_INT32(result);
830
0
}
831
832
Datum
833
int4div(PG_FUNCTION_ARGS)
834
0
{
835
0
  int32   arg1 = PG_GETARG_INT32(0);
836
0
  int32   arg2 = PG_GETARG_INT32(1);
837
0
  int32   result;
838
839
0
  if (arg2 == 0)
840
0
  {
841
0
    ereport(ERROR,
842
0
        (errcode(ERRCODE_DIVISION_BY_ZERO),
843
0
         errmsg("division by zero")));
844
    /* ensure compiler realizes we mustn't reach the division (gcc bug) */
845
0
    PG_RETURN_NULL();
846
0
  }
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
0
  if (arg2 == -1)
855
0
  {
856
0
    if (unlikely(arg1 == PG_INT32_MIN))
857
0
      ereport(ERROR,
858
0
          (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
859
0
           errmsg("integer out of range")));
860
0
    result = -arg1;
861
0
    PG_RETURN_INT32(result);
862
0
  }
863
864
  /* No overflow is possible */
865
866
0
  result = arg1 / arg2;
867
868
0
  PG_RETURN_INT32(result);
869
0
}
870
871
Datum
872
int4inc(PG_FUNCTION_ARGS)
873
0
{
874
0
  int32   arg = PG_GETARG_INT32(0);
875
0
  int32   result;
876
877
0
  if (unlikely(pg_add_s32_overflow(arg, 1, &result)))
878
0
    ereport(ERROR,
879
0
        (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
880
0
         errmsg("integer out of range")));
881
882
0
  PG_RETURN_INT32(result);
883
0
}
884
885
Datum
886
int2um(PG_FUNCTION_ARGS)
887
0
{
888
0
  int16   arg = PG_GETARG_INT16(0);
889
890
0
  if (unlikely(arg == PG_INT16_MIN))
891
0
    ereport(ERROR,
892
0
        (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
893
0
         errmsg("smallint out of range")));
894
0
  PG_RETURN_INT16(-arg);
895
0
}
896
897
Datum
898
int2up(PG_FUNCTION_ARGS)
899
0
{
900
0
  int16   arg = PG_GETARG_INT16(0);
901
902
0
  PG_RETURN_INT16(arg);
903
0
}
904
905
Datum
906
int2pl(PG_FUNCTION_ARGS)
907
0
{
908
0
  int16   arg1 = PG_GETARG_INT16(0);
909
0
  int16   arg2 = PG_GETARG_INT16(1);
910
0
  int16   result;
911
912
0
  if (unlikely(pg_add_s16_overflow(arg1, arg2, &result)))
913
0
    ereport(ERROR,
914
0
        (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
915
0
         errmsg("smallint out of range")));
916
0
  PG_RETURN_INT16(result);
917
0
}
918
919
Datum
920
int2mi(PG_FUNCTION_ARGS)
921
0
{
922
0
  int16   arg1 = PG_GETARG_INT16(0);
923
0
  int16   arg2 = PG_GETARG_INT16(1);
924
0
  int16   result;
925
926
0
  if (unlikely(pg_sub_s16_overflow(arg1, arg2, &result)))
927
0
    ereport(ERROR,
928
0
        (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
929
0
         errmsg("smallint out of range")));
930
0
  PG_RETURN_INT16(result);
931
0
}
932
933
Datum
934
int2mul(PG_FUNCTION_ARGS)
935
0
{
936
0
  int16   arg1 = PG_GETARG_INT16(0);
937
0
  int16   arg2 = PG_GETARG_INT16(1);
938
0
  int16   result;
939
940
0
  if (unlikely(pg_mul_s16_overflow(arg1, arg2, &result)))
941
0
    ereport(ERROR,
942
0
        (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
943
0
         errmsg("smallint out of range")));
944
945
0
  PG_RETURN_INT16(result);
946
0
}
947
948
Datum
949
int2div(PG_FUNCTION_ARGS)
950
0
{
951
0
  int16   arg1 = PG_GETARG_INT16(0);
952
0
  int16   arg2 = PG_GETARG_INT16(1);
953
0
  int16   result;
954
955
0
  if (arg2 == 0)
956
0
  {
957
0
    ereport(ERROR,
958
0
        (errcode(ERRCODE_DIVISION_BY_ZERO),
959
0
         errmsg("division by zero")));
960
    /* ensure compiler realizes we mustn't reach the division (gcc bug) */
961
0
    PG_RETURN_NULL();
962
0
  }
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
0
  if (arg2 == -1)
971
0
  {
972
0
    if (unlikely(arg1 == PG_INT16_MIN))
973
0
      ereport(ERROR,
974
0
          (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
975
0
           errmsg("smallint out of range")));
976
0
    result = -arg1;
977
0
    PG_RETURN_INT16(result);
978
0
  }
979
980
  /* No overflow is possible */
981
982
0
  result = arg1 / arg2;
983
984
0
  PG_RETURN_INT16(result);
985
0
}
986
987
Datum
988
int24pl(PG_FUNCTION_ARGS)
989
0
{
990
0
  int16   arg1 = PG_GETARG_INT16(0);
991
0
  int32   arg2 = PG_GETARG_INT32(1);
992
0
  int32   result;
993
994
0
  if (unlikely(pg_add_s32_overflow((int32) arg1, arg2, &result)))
995
0
    ereport(ERROR,
996
0
        (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
997
0
         errmsg("integer out of range")));
998
0
  PG_RETURN_INT32(result);
999
0
}
1000
1001
Datum
1002
int24mi(PG_FUNCTION_ARGS)
1003
0
{
1004
0
  int16   arg1 = PG_GETARG_INT16(0);
1005
0
  int32   arg2 = PG_GETARG_INT32(1);
1006
0
  int32   result;
1007
1008
0
  if (unlikely(pg_sub_s32_overflow((int32) arg1, arg2, &result)))
1009
0
    ereport(ERROR,
1010
0
        (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1011
0
         errmsg("integer out of range")));
1012
0
  PG_RETURN_INT32(result);
1013
0
}
1014
1015
Datum
1016
int24mul(PG_FUNCTION_ARGS)
1017
0
{
1018
0
  int16   arg1 = PG_GETARG_INT16(0);
1019
0
  int32   arg2 = PG_GETARG_INT32(1);
1020
0
  int32   result;
1021
1022
0
  if (unlikely(pg_mul_s32_overflow((int32) arg1, arg2, &result)))
1023
0
    ereport(ERROR,
1024
0
        (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1025
0
         errmsg("integer out of range")));
1026
0
  PG_RETURN_INT32(result);
1027
0
}
1028
1029
Datum
1030
int24div(PG_FUNCTION_ARGS)
1031
0
{
1032
0
  int16   arg1 = PG_GETARG_INT16(0);
1033
0
  int32   arg2 = PG_GETARG_INT32(1);
1034
1035
0
  if (unlikely(arg2 == 0))
1036
0
  {
1037
0
    ereport(ERROR,
1038
0
        (errcode(ERRCODE_DIVISION_BY_ZERO),
1039
0
         errmsg("division by zero")));
1040
    /* ensure compiler realizes we mustn't reach the division (gcc bug) */
1041
0
    PG_RETURN_NULL();
1042
0
  }
1043
1044
  /* No overflow is possible */
1045
0
  PG_RETURN_INT32((int32) arg1 / arg2);
1046
0
}
1047
1048
Datum
1049
int42pl(PG_FUNCTION_ARGS)
1050
0
{
1051
0
  int32   arg1 = PG_GETARG_INT32(0);
1052
0
  int16   arg2 = PG_GETARG_INT16(1);
1053
0
  int32   result;
1054
1055
0
  if (unlikely(pg_add_s32_overflow(arg1, (int32) arg2, &result)))
1056
0
    ereport(ERROR,
1057
0
        (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1058
0
         errmsg("integer out of range")));
1059
0
  PG_RETURN_INT32(result);
1060
0
}
1061
1062
Datum
1063
int42mi(PG_FUNCTION_ARGS)
1064
0
{
1065
0
  int32   arg1 = PG_GETARG_INT32(0);
1066
0
  int16   arg2 = PG_GETARG_INT16(1);
1067
0
  int32   result;
1068
1069
0
  if (unlikely(pg_sub_s32_overflow(arg1, (int32) arg2, &result)))
1070
0
    ereport(ERROR,
1071
0
        (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1072
0
         errmsg("integer out of range")));
1073
0
  PG_RETURN_INT32(result);
1074
0
}
1075
1076
Datum
1077
int42mul(PG_FUNCTION_ARGS)
1078
0
{
1079
0
  int32   arg1 = PG_GETARG_INT32(0);
1080
0
  int16   arg2 = PG_GETARG_INT16(1);
1081
0
  int32   result;
1082
1083
0
  if (unlikely(pg_mul_s32_overflow(arg1, (int32) arg2, &result)))
1084
0
    ereport(ERROR,
1085
0
        (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1086
0
         errmsg("integer out of range")));
1087
0
  PG_RETURN_INT32(result);
1088
0
}
1089
1090
Datum
1091
int42div(PG_FUNCTION_ARGS)
1092
0
{
1093
0
  int32   arg1 = PG_GETARG_INT32(0);
1094
0
  int16   arg2 = PG_GETARG_INT16(1);
1095
0
  int32   result;
1096
1097
0
  if (unlikely(arg2 == 0))
1098
0
  {
1099
0
    ereport(ERROR,
1100
0
        (errcode(ERRCODE_DIVISION_BY_ZERO),
1101
0
         errmsg("division by zero")));
1102
    /* ensure compiler realizes we mustn't reach the division (gcc bug) */
1103
0
    PG_RETURN_NULL();
1104
0
  }
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
0
  if (arg2 == -1)
1113
0
  {
1114
0
    if (unlikely(arg1 == PG_INT32_MIN))
1115
0
      ereport(ERROR,
1116
0
          (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1117
0
           errmsg("integer out of range")));
1118
0
    result = -arg1;
1119
0
    PG_RETURN_INT32(result);
1120
0
  }
1121
1122
  /* No overflow is possible */
1123
1124
0
  result = arg1 / arg2;
1125
1126
0
  PG_RETURN_INT32(result);
1127
0
}
1128
1129
Datum
1130
int4mod(PG_FUNCTION_ARGS)
1131
0
{
1132
0
  int32   arg1 = PG_GETARG_INT32(0);
1133
0
  int32   arg2 = PG_GETARG_INT32(1);
1134
1135
0
  if (unlikely(arg2 == 0))
1136
0
  {
1137
0
    ereport(ERROR,
1138
0
        (errcode(ERRCODE_DIVISION_BY_ZERO),
1139
0
         errmsg("division by zero")));
1140
    /* ensure compiler realizes we mustn't reach the division (gcc bug) */
1141
0
    PG_RETURN_NULL();
1142
0
  }
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
0
  if (arg2 == -1)
1150
0
    PG_RETURN_INT32(0);
1151
1152
  /* No overflow is possible */
1153
1154
0
  PG_RETURN_INT32(arg1 % arg2);
1155
0
}
1156
1157
Datum
1158
int2mod(PG_FUNCTION_ARGS)
1159
0
{
1160
0
  int16   arg1 = PG_GETARG_INT16(0);
1161
0
  int16   arg2 = PG_GETARG_INT16(1);
1162
1163
0
  if (unlikely(arg2 == 0))
1164
0
  {
1165
0
    ereport(ERROR,
1166
0
        (errcode(ERRCODE_DIVISION_BY_ZERO),
1167
0
         errmsg("division by zero")));
1168
    /* ensure compiler realizes we mustn't reach the division (gcc bug) */
1169
0
    PG_RETURN_NULL();
1170
0
  }
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
0
  if (arg2 == -1)
1179
0
    PG_RETURN_INT16(0);
1180
1181
  /* No overflow is possible */
1182
1183
0
  PG_RETURN_INT16(arg1 % arg2);
1184
0
}
1185
1186
1187
/* int[24]abs()
1188
 * Absolute value
1189
 */
1190
Datum
1191
int4abs(PG_FUNCTION_ARGS)
1192
0
{
1193
0
  int32   arg1 = PG_GETARG_INT32(0);
1194
0
  int32   result;
1195
1196
0
  if (unlikely(arg1 == PG_INT32_MIN))
1197
0
    ereport(ERROR,
1198
0
        (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1199
0
         errmsg("integer out of range")));
1200
0
  result = (arg1 < 0) ? -arg1 : arg1;
1201
0
  PG_RETURN_INT32(result);
1202
0
}
1203
1204
Datum
1205
int2abs(PG_FUNCTION_ARGS)
1206
0
{
1207
0
  int16   arg1 = PG_GETARG_INT16(0);
1208
0
  int16   result;
1209
1210
0
  if (unlikely(arg1 == PG_INT16_MIN))
1211
0
    ereport(ERROR,
1212
0
        (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1213
0
         errmsg("smallint out of range")));
1214
0
  result = (arg1 < 0) ? -arg1 : arg1;
1215
0
  PG_RETURN_INT16(result);
1216
0
}
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
int4gcd_internal(int32 arg1, int32 arg2)
1234
0
{
1235
0
  int32   swap;
1236
0
  int32   a1,
1237
0
        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
0
  a1 = (arg1 < 0) ? arg1 : -arg1;
1249
0
  a2 = (arg2 < 0) ? arg2 : -arg2;
1250
0
  if (a1 > a2)
1251
0
  {
1252
0
    swap = arg1;
1253
0
    arg1 = arg2;
1254
0
    arg2 = swap;
1255
0
  }
1256
1257
  /* Special care needs to be taken with INT_MIN.  See comments above. */
1258
0
  if (arg1 == PG_INT32_MIN)
1259
0
  {
1260
0
    if (arg2 == 0 || arg2 == PG_INT32_MIN)
1261
0
      ereport(ERROR,
1262
0
          (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1263
0
           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
0
    if (arg2 == -1)
1272
0
      return 1;
1273
0
  }
1274
1275
  /* Use the Euclidean algorithm to find the GCD */
1276
0
  while (arg2 != 0)
1277
0
  {
1278
0
    swap = arg2;
1279
0
    arg2 = arg1 % arg2;
1280
0
    arg1 = swap;
1281
0
  }
1282
1283
  /*
1284
   * Make sure the result is positive. (We know we don't have INT_MIN
1285
   * anymore).
1286
   */
1287
0
  if (arg1 < 0)
1288
0
    arg1 = -arg1;
1289
1290
0
  return arg1;
1291
0
}
1292
1293
Datum
1294
int4gcd(PG_FUNCTION_ARGS)
1295
0
{
1296
0
  int32   arg1 = PG_GETARG_INT32(0);
1297
0
  int32   arg2 = PG_GETARG_INT32(1);
1298
0
  int32   result;
1299
1300
0
  result = int4gcd_internal(arg1, arg2);
1301
1302
0
  PG_RETURN_INT32(result);
1303
0
}
1304
1305
/*
1306
 * Least Common Multiple
1307
 */
1308
Datum
1309
int4lcm(PG_FUNCTION_ARGS)
1310
0
{
1311
0
  int32   arg1 = PG_GETARG_INT32(0);
1312
0
  int32   arg2 = PG_GETARG_INT32(1);
1313
0
  int32   gcd;
1314
0
  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
0
  if (arg1 == 0 || arg2 == 0)
1322
0
    PG_RETURN_INT32(0);
1323
1324
  /* lcm(x, y) = abs(x / gcd(x, y) * y) */
1325
0
  gcd = int4gcd_internal(arg1, arg2);
1326
0
  arg1 = arg1 / gcd;
1327
1328
0
  if (unlikely(pg_mul_s32_overflow(arg1, arg2, &result)))
1329
0
    ereport(ERROR,
1330
0
        (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1331
0
         errmsg("integer out of range")));
1332
1333
  /* If the result is INT_MIN, it cannot be represented. */
1334
0
  if (unlikely(result == PG_INT32_MIN))
1335
0
    ereport(ERROR,
1336
0
        (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1337
0
         errmsg("integer out of range")));
1338
1339
0
  if (result < 0)
1340
0
    result = -result;
1341
1342
0
  PG_RETURN_INT32(result);
1343
0
}
1344
1345
Datum
1346
int2larger(PG_FUNCTION_ARGS)
1347
0
{
1348
0
  int16   arg1 = PG_GETARG_INT16(0);
1349
0
  int16   arg2 = PG_GETARG_INT16(1);
1350
1351
0
  PG_RETURN_INT16((arg1 > arg2) ? arg1 : arg2);
1352
0
}
1353
1354
Datum
1355
int2smaller(PG_FUNCTION_ARGS)
1356
0
{
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
0
}
1362
1363
Datum
1364
int4larger(PG_FUNCTION_ARGS)
1365
0
{
1366
0
  int32   arg1 = PG_GETARG_INT32(0);
1367
0
  int32   arg2 = PG_GETARG_INT32(1);
1368
1369
0
  PG_RETURN_INT32((arg1 > arg2) ? arg1 : arg2);
1370
0
}
1371
1372
Datum
1373
int4smaller(PG_FUNCTION_ARGS)
1374
0
{
1375
0
  int32   arg1 = PG_GETARG_INT32(0);
1376
0
  int32   arg2 = PG_GETARG_INT32(1);
1377
1378
0
  PG_RETURN_INT32((arg1 < arg2) ? arg1 : arg2);
1379
0
}
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
int4and(PG_FUNCTION_ARGS)
1394
0
{
1395
0
  int32   arg1 = PG_GETARG_INT32(0);
1396
0
  int32   arg2 = PG_GETARG_INT32(1);
1397
1398
0
  PG_RETURN_INT32(arg1 & arg2);
1399
0
}
1400
1401
Datum
1402
int4or(PG_FUNCTION_ARGS)
1403
0
{
1404
0
  int32   arg1 = PG_GETARG_INT32(0);
1405
0
  int32   arg2 = PG_GETARG_INT32(1);
1406
1407
0
  PG_RETURN_INT32(arg1 | arg2);
1408
0
}
1409
1410
Datum
1411
int4xor(PG_FUNCTION_ARGS)
1412
0
{
1413
0
  int32   arg1 = PG_GETARG_INT32(0);
1414
0
  int32   arg2 = PG_GETARG_INT32(1);
1415
1416
0
  PG_RETURN_INT32(arg1 ^ arg2);
1417
0
}
1418
1419
Datum
1420
int4shl(PG_FUNCTION_ARGS)
1421
0
{
1422
0
  int32   arg1 = PG_GETARG_INT32(0);
1423
0
  int32   arg2 = PG_GETARG_INT32(1);
1424
1425
0
  PG_RETURN_INT32(arg1 << arg2);
1426
0
}
1427
1428
Datum
1429
int4shr(PG_FUNCTION_ARGS)
1430
0
{
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
0
}
1436
1437
Datum
1438
int4not(PG_FUNCTION_ARGS)
1439
0
{
1440
0
  int32   arg1 = PG_GETARG_INT32(0);
1441
1442
0
  PG_RETURN_INT32(~arg1);
1443
0
}
1444
1445
Datum
1446
int2and(PG_FUNCTION_ARGS)
1447
0
{
1448
0
  int16   arg1 = PG_GETARG_INT16(0);
1449
0
  int16   arg2 = PG_GETARG_INT16(1);
1450
1451
0
  PG_RETURN_INT16(arg1 & arg2);
1452
0
}
1453
1454
Datum
1455
int2or(PG_FUNCTION_ARGS)
1456
0
{
1457
0
  int16   arg1 = PG_GETARG_INT16(0);
1458
0
  int16   arg2 = PG_GETARG_INT16(1);
1459
1460
0
  PG_RETURN_INT16(arg1 | arg2);
1461
0
}
1462
1463
Datum
1464
int2xor(PG_FUNCTION_ARGS)
1465
0
{
1466
0
  int16   arg1 = PG_GETARG_INT16(0);
1467
0
  int16   arg2 = PG_GETARG_INT16(1);
1468
1469
0
  PG_RETURN_INT16(arg1 ^ arg2);
1470
0
}
1471
1472
Datum
1473
int2not(PG_FUNCTION_ARGS)
1474
0
{
1475
0
  int16   arg1 = PG_GETARG_INT16(0);
1476
1477
0
  PG_RETURN_INT16(~arg1);
1478
0
}
1479
1480
1481
Datum
1482
int2shl(PG_FUNCTION_ARGS)
1483
0
{
1484
0
  int16   arg1 = PG_GETARG_INT16(0);
1485
0
  int32   arg2 = PG_GETARG_INT32(1);
1486
1487
0
  PG_RETURN_INT16(arg1 << arg2);
1488
0
}
1489
1490
Datum
1491
int2shr(PG_FUNCTION_ARGS)
1492
0
{
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
0
}
1498
1499
/*
1500
 * non-persistent numeric series generator
1501
 */
1502
Datum
1503
generate_series_int4(PG_FUNCTION_ARGS)
1504
0
{
1505
0
  return generate_series_step_int4(fcinfo);
1506
0
}
1507
1508
Datum
1509
generate_series_step_int4(PG_FUNCTION_ARGS)
1510
0
{
1511
0
  FuncCallContext *funcctx;
1512
0
  generate_series_fctx *fctx;
1513
0
  int32   result;
1514
0
  MemoryContext oldcontext;
1515
1516
  /* stuff done only on the first call of the function */
1517
0
  if (SRF_IS_FIRSTCALL())
1518
0
  {
1519
0
    int32   start = PG_GETARG_INT32(0);
1520
0
    int32   finish = PG_GETARG_INT32(1);
1521
0
    int32   step = 1;
1522
1523
    /* see if we were given an explicit step size */
1524
0
    if (PG_NARGS() == 3)
1525
0
      step = PG_GETARG_INT32(2);
1526
0
    if (step == 0)
1527
0
      ereport(ERROR,
1528
0
          (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1529
0
           errmsg("step size cannot equal zero")));
1530
1531
    /* create a function context for cross-call persistence */
1532
0
    funcctx = SRF_FIRSTCALL_INIT();
1533
1534
    /*
1535
     * switch to memory context appropriate for multiple function calls
1536
     */
1537
0
    oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
1538
1539
    /* allocate memory for user context */
1540
0
    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
0
    fctx->current = start;
1547
0
    fctx->finish = finish;
1548
0
    fctx->step = step;
1549
1550
0
    funcctx->user_fctx = fctx;
1551
0
    MemoryContextSwitchTo(oldcontext);
1552
0
  }
1553
1554
  /* stuff done on every call of the function */
1555
0
  funcctx = SRF_PERCALL_SETUP();
1556
1557
  /*
1558
   * get the saved state and use current as the result for this iteration
1559
   */
1560
0
  fctx = funcctx->user_fctx;
1561
0
  result = fctx->current;
1562
1563
0
  if ((fctx->step > 0 && fctx->current <= fctx->finish) ||
1564
0
    (fctx->step < 0 && fctx->current >= fctx->finish))
1565
0
  {
1566
    /*
1567
     * Increment current in preparation for next iteration. If next-value
1568
     * computation overflows, this is the final result.
1569
     */
1570
0
    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
0
    SRF_RETURN_NEXT(funcctx, Int32GetDatum(result));
1575
0
  }
1576
0
  else
1577
    /* do when there is no more left */
1578
0
    SRF_RETURN_DONE(funcctx);
1579
0
}
1580
1581
/*
1582
 * Planner support function for generate_series(int4, int4 [, int4])
1583
 */
1584
Datum
1585
generate_series_int4_support(PG_FUNCTION_ARGS)
1586
0
{
1587
0
  Node     *rawreq = (Node *) PG_GETARG_POINTER(0);
1588
0
  Node     *ret = NULL;
1589
1590
0
  if (IsA(rawreq, SupportRequestRows))
1591
0
  {
1592
    /* Try to estimate the number of rows returned */
1593
0
    SupportRequestRows *req = (SupportRequestRows *) rawreq;
1594
1595
0
    if (is_funcclause(req->node)) /* be paranoid */
1596
0
    {
1597
0
      List     *args = ((FuncExpr *) req->node)->args;
1598
0
      Node     *arg1,
1599
0
             *arg2,
1600
0
             *arg3;
1601
1602
      /* We can use estimated argument values here */
1603
0
      arg1 = estimate_expression_value(req->root, linitial(args));
1604
0
      arg2 = estimate_expression_value(req->root, lsecond(args));
1605
0
      if (list_length(args) >= 3)
1606
0
        arg3 = estimate_expression_value(req->root, lthird(args));
1607
0
      else
1608
0
        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
0
      if ((IsA(arg1, Const) &&
1617
0
         ((Const *) arg1)->constisnull) ||
1618
0
        (IsA(arg2, Const) &&
1619
0
         ((Const *) arg2)->constisnull) ||
1620
0
        (arg3 != NULL && IsA(arg3, Const) &&
1621
0
         ((Const *) arg3)->constisnull))
1622
0
      {
1623
0
        req->rows = 0;
1624
0
        ret = (Node *) req;
1625
0
      }
1626
0
      else if (IsA(arg1, Const) &&
1627
0
           IsA(arg2, Const) &&
1628
0
           (arg3 == NULL || IsA(arg3, Const)))
1629
0
      {
1630
0
        double    start,
1631
0
              finish,
1632
0
              step;
1633
1634
0
        start = DatumGetInt32(((Const *) arg1)->constvalue);
1635
0
        finish = DatumGetInt32(((Const *) arg2)->constvalue);
1636
0
        step = arg3 ? DatumGetInt32(((Const *) arg3)->constvalue) : 1;
1637
1638
        /* This equation works for either sign of step */
1639
0
        if (step != 0)
1640
0
        {
1641
0
          req->rows = floor((finish - start + step) / step);
1642
0
          ret = (Node *) req;
1643
0
        }
1644
0
      }
1645
0
    }
1646
0
  }
1647
1648
0
  PG_RETURN_POINTER(ret);
1649
0
}