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