1 /*-------------------------------------------------------------------------
4 * Internal 64-bit integer operations
6 * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
7 * Portions Copyright (c) 1994, Regents of the University of California
10 * $Header: /cvsroot/pgsql/src/backend/utils/adt/int8.c,v 1.45 2003/07/27 04:53:06 tgl Exp $
12 *-------------------------------------------------------------------------
19 #include "libpq/pqformat.h"
20 #include "utils/int8.h"
26 /***********************************************************************
28 ** Routines for 64-bit integers.
30 ***********************************************************************/
32 /*----------------------------------------------------------
33 * Formatting and conversion routines.
34 *---------------------------------------------------------*/
37 * scanint8 --- try to parse a string into an int8.
39 * If errorOK is false, ereport a useful error message if the string is bad.
40 * If errorOK is true, just return "false" for bad input.
43 scanint8(const char *str, bool errorOK, int64 *result)
45 const char *ptr = str;
50 * Do our own scan, rather than relying on sscanf which might be
51 * broken for long long.
54 /* skip leading spaces */
55 while (*ptr && isspace((unsigned char) *ptr))
65 * Do an explicit check for INT64_MIN. Ugly though this is, it's
66 * cleaner than trying to get the loop below to handle it
69 #ifndef INT64_IS_BUSTED
70 if (strcmp(ptr, "9223372036854775808") == 0)
72 *result = -INT64CONST(0x7fffffffffffffff) - 1;
80 /* require at least one digit */
81 if (!isdigit((unsigned char) *ptr))
87 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
88 errmsg("invalid input syntax for int8: \"%s\"", str)));
92 while (*ptr && isdigit((unsigned char) *ptr))
94 int64 newtmp = tmp * 10 + (*ptr++ - '0');
96 if ((newtmp / 10) != tmp) /* overflow? */
102 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
103 errmsg("integer out of range")));
115 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
116 errmsg("invalid input syntax for int8: \"%s\"", str)));
119 *result = (sign < 0) ? -tmp : tmp;
127 int8in(PG_FUNCTION_ARGS)
129 char *str = PG_GETARG_CSTRING(0);
132 (void) scanint8(str, false, &result);
133 PG_RETURN_INT64(result);
140 int8out(PG_FUNCTION_ARGS)
142 int64 val = PG_GETARG_INT64(0);
145 char buf[MAXINT8LEN + 1];
147 if ((len = snprintf(buf, MAXINT8LEN, INT64_FORMAT, val)) < 0)
148 elog(ERROR, "could not format int8");
150 result = pstrdup(buf);
151 PG_RETURN_CSTRING(result);
155 * int8recv - converts external binary format to int8
158 int8recv(PG_FUNCTION_ARGS)
160 StringInfo buf = (StringInfo) PG_GETARG_POINTER(0);
162 PG_RETURN_INT64(pq_getmsgint64(buf));
166 * int8send - converts int8 to binary format
169 int8send(PG_FUNCTION_ARGS)
171 int64 arg1 = PG_GETARG_INT64(0);
174 pq_begintypsend(&buf);
175 pq_sendint64(&buf, arg1);
176 PG_RETURN_BYTEA_P(pq_endtypsend(&buf));
180 /*----------------------------------------------------------
181 * Relational operators for int8s, including cross-data-type comparisons.
182 *---------------------------------------------------------*/
185 * Is val1 relop val2?
188 int8eq(PG_FUNCTION_ARGS)
190 int64 val1 = PG_GETARG_INT64(0);
191 int64 val2 = PG_GETARG_INT64(1);
193 PG_RETURN_BOOL(val1 == val2);
197 int8ne(PG_FUNCTION_ARGS)
199 int64 val1 = PG_GETARG_INT64(0);
200 int64 val2 = PG_GETARG_INT64(1);
202 PG_RETURN_BOOL(val1 != val2);
206 int8lt(PG_FUNCTION_ARGS)
208 int64 val1 = PG_GETARG_INT64(0);
209 int64 val2 = PG_GETARG_INT64(1);
211 PG_RETURN_BOOL(val1 < val2);
215 int8gt(PG_FUNCTION_ARGS)
217 int64 val1 = PG_GETARG_INT64(0);
218 int64 val2 = PG_GETARG_INT64(1);
220 PG_RETURN_BOOL(val1 > val2);
224 int8le(PG_FUNCTION_ARGS)
226 int64 val1 = PG_GETARG_INT64(0);
227 int64 val2 = PG_GETARG_INT64(1);
229 PG_RETURN_BOOL(val1 <= val2);
233 int8ge(PG_FUNCTION_ARGS)
235 int64 val1 = PG_GETARG_INT64(0);
236 int64 val2 = PG_GETARG_INT64(1);
238 PG_RETURN_BOOL(val1 >= val2);
242 * Is 64-bit val1 relop 32-bit val2?
245 int84eq(PG_FUNCTION_ARGS)
247 int64 val1 = PG_GETARG_INT64(0);
248 int32 val2 = PG_GETARG_INT32(1);
250 PG_RETURN_BOOL(val1 == val2);
254 int84ne(PG_FUNCTION_ARGS)
256 int64 val1 = PG_GETARG_INT64(0);
257 int32 val2 = PG_GETARG_INT32(1);
259 PG_RETURN_BOOL(val1 != val2);
263 int84lt(PG_FUNCTION_ARGS)
265 int64 val1 = PG_GETARG_INT64(0);
266 int32 val2 = PG_GETARG_INT32(1);
268 PG_RETURN_BOOL(val1 < val2);
272 int84gt(PG_FUNCTION_ARGS)
274 int64 val1 = PG_GETARG_INT64(0);
275 int32 val2 = PG_GETARG_INT32(1);
277 PG_RETURN_BOOL(val1 > val2);
281 int84le(PG_FUNCTION_ARGS)
283 int64 val1 = PG_GETARG_INT64(0);
284 int32 val2 = PG_GETARG_INT32(1);
286 PG_RETURN_BOOL(val1 <= val2);
290 int84ge(PG_FUNCTION_ARGS)
292 int64 val1 = PG_GETARG_INT64(0);
293 int32 val2 = PG_GETARG_INT32(1);
295 PG_RETURN_BOOL(val1 >= val2);
299 * Is 32-bit val1 relop 64-bit val2?
302 int48eq(PG_FUNCTION_ARGS)
304 int32 val1 = PG_GETARG_INT32(0);
305 int64 val2 = PG_GETARG_INT64(1);
307 PG_RETURN_BOOL(val1 == val2);
311 int48ne(PG_FUNCTION_ARGS)
313 int32 val1 = PG_GETARG_INT32(0);
314 int64 val2 = PG_GETARG_INT64(1);
316 PG_RETURN_BOOL(val1 != val2);
320 int48lt(PG_FUNCTION_ARGS)
322 int32 val1 = PG_GETARG_INT32(0);
323 int64 val2 = PG_GETARG_INT64(1);
325 PG_RETURN_BOOL(val1 < val2);
329 int48gt(PG_FUNCTION_ARGS)
331 int32 val1 = PG_GETARG_INT32(0);
332 int64 val2 = PG_GETARG_INT64(1);
334 PG_RETURN_BOOL(val1 > val2);
338 int48le(PG_FUNCTION_ARGS)
340 int32 val1 = PG_GETARG_INT32(0);
341 int64 val2 = PG_GETARG_INT64(1);
343 PG_RETURN_BOOL(val1 <= val2);
347 int48ge(PG_FUNCTION_ARGS)
349 int32 val1 = PG_GETARG_INT32(0);
350 int64 val2 = PG_GETARG_INT64(1);
352 PG_RETURN_BOOL(val1 >= val2);
356 * Is 64-bit val1 relop 16-bit val2?
359 int82eq(PG_FUNCTION_ARGS)
361 int64 val1 = PG_GETARG_INT64(0);
362 int16 val2 = PG_GETARG_INT16(1);
364 PG_RETURN_BOOL(val1 == val2);
368 int82ne(PG_FUNCTION_ARGS)
370 int64 val1 = PG_GETARG_INT64(0);
371 int16 val2 = PG_GETARG_INT16(1);
373 PG_RETURN_BOOL(val1 != val2);
377 int82lt(PG_FUNCTION_ARGS)
379 int64 val1 = PG_GETARG_INT64(0);
380 int16 val2 = PG_GETARG_INT16(1);
382 PG_RETURN_BOOL(val1 < val2);
386 int82gt(PG_FUNCTION_ARGS)
388 int64 val1 = PG_GETARG_INT64(0);
389 int16 val2 = PG_GETARG_INT16(1);
391 PG_RETURN_BOOL(val1 > val2);
395 int82le(PG_FUNCTION_ARGS)
397 int64 val1 = PG_GETARG_INT64(0);
398 int16 val2 = PG_GETARG_INT16(1);
400 PG_RETURN_BOOL(val1 <= val2);
404 int82ge(PG_FUNCTION_ARGS)
406 int64 val1 = PG_GETARG_INT64(0);
407 int16 val2 = PG_GETARG_INT16(1);
409 PG_RETURN_BOOL(val1 >= val2);
413 * Is 16-bit val1 relop 64-bit val2?
416 int28eq(PG_FUNCTION_ARGS)
418 int16 val1 = PG_GETARG_INT16(0);
419 int64 val2 = PG_GETARG_INT64(1);
421 PG_RETURN_BOOL(val1 == val2);
425 int28ne(PG_FUNCTION_ARGS)
427 int16 val1 = PG_GETARG_INT16(0);
428 int64 val2 = PG_GETARG_INT64(1);
430 PG_RETURN_BOOL(val1 != val2);
434 int28lt(PG_FUNCTION_ARGS)
436 int16 val1 = PG_GETARG_INT16(0);
437 int64 val2 = PG_GETARG_INT64(1);
439 PG_RETURN_BOOL(val1 < val2);
443 int28gt(PG_FUNCTION_ARGS)
445 int16 val1 = PG_GETARG_INT16(0);
446 int64 val2 = PG_GETARG_INT64(1);
448 PG_RETURN_BOOL(val1 > val2);
452 int28le(PG_FUNCTION_ARGS)
454 int16 val1 = PG_GETARG_INT16(0);
455 int64 val2 = PG_GETARG_INT64(1);
457 PG_RETURN_BOOL(val1 <= val2);
461 int28ge(PG_FUNCTION_ARGS)
463 int16 val1 = PG_GETARG_INT16(0);
464 int64 val2 = PG_GETARG_INT64(1);
466 PG_RETURN_BOOL(val1 >= val2);
470 /*----------------------------------------------------------
471 * Arithmetic operators on 64-bit integers.
472 *---------------------------------------------------------*/
475 int8um(PG_FUNCTION_ARGS)
477 int64 val = PG_GETARG_INT64(0);
479 PG_RETURN_INT64(-val);
483 int8up(PG_FUNCTION_ARGS)
485 int64 val = PG_GETARG_INT64(0);
487 PG_RETURN_INT64(val);
491 int8pl(PG_FUNCTION_ARGS)
493 int64 val1 = PG_GETARG_INT64(0);
494 int64 val2 = PG_GETARG_INT64(1);
496 PG_RETURN_INT64(val1 + val2);
500 int8mi(PG_FUNCTION_ARGS)
502 int64 val1 = PG_GETARG_INT64(0);
503 int64 val2 = PG_GETARG_INT64(1);
505 PG_RETURN_INT64(val1 - val2);
509 int8mul(PG_FUNCTION_ARGS)
511 int64 val1 = PG_GETARG_INT64(0);
512 int64 val2 = PG_GETARG_INT64(1);
514 PG_RETURN_INT64(val1 * val2);
518 int8div(PG_FUNCTION_ARGS)
520 int64 val1 = PG_GETARG_INT64(0);
521 int64 val2 = PG_GETARG_INT64(1);
525 (errcode(ERRCODE_DIVISION_BY_ZERO),
526 errmsg("division by zero")));
528 PG_RETURN_INT64(val1 / val2);
535 int8abs(PG_FUNCTION_ARGS)
537 int64 arg1 = PG_GETARG_INT64(0);
539 PG_RETURN_INT64((arg1 < 0) ? -arg1 : arg1);
546 int8mod(PG_FUNCTION_ARGS)
548 int64 val1 = PG_GETARG_INT64(0);
549 int64 val2 = PG_GETARG_INT64(1);
554 (errcode(ERRCODE_DIVISION_BY_ZERO),
555 errmsg("division by zero")));
557 result = val1 / val2;
559 result = val1 - result;
561 PG_RETURN_INT64(result);
568 int8fac(PG_FUNCTION_ARGS)
570 int64 arg1 = PG_GETARG_INT64(0);
579 for (i = arg1, result = 1; i > 0; --i)
582 PG_RETURN_INT64(result);
586 int8inc(PG_FUNCTION_ARGS)
588 int64 arg = PG_GETARG_INT64(0);
590 PG_RETURN_INT64(arg + 1);
594 int8larger(PG_FUNCTION_ARGS)
596 int64 val1 = PG_GETARG_INT64(0);
597 int64 val2 = PG_GETARG_INT64(1);
600 result = ((val1 > val2) ? val1 : val2);
602 PG_RETURN_INT64(result);
606 int8smaller(PG_FUNCTION_ARGS)
608 int64 val1 = PG_GETARG_INT64(0);
609 int64 val2 = PG_GETARG_INT64(1);
612 result = ((val1 < val2) ? val1 : val2);
614 PG_RETURN_INT64(result);
618 int84pl(PG_FUNCTION_ARGS)
620 int64 val1 = PG_GETARG_INT64(0);
621 int32 val2 = PG_GETARG_INT32(1);
623 PG_RETURN_INT64(val1 + val2);
627 int84mi(PG_FUNCTION_ARGS)
629 int64 val1 = PG_GETARG_INT64(0);
630 int32 val2 = PG_GETARG_INT32(1);
632 PG_RETURN_INT64(val1 - val2);
636 int84mul(PG_FUNCTION_ARGS)
638 int64 val1 = PG_GETARG_INT64(0);
639 int32 val2 = PG_GETARG_INT32(1);
641 PG_RETURN_INT64(val1 * val2);
645 int84div(PG_FUNCTION_ARGS)
647 int64 val1 = PG_GETARG_INT64(0);
648 int32 val2 = PG_GETARG_INT32(1);
652 (errcode(ERRCODE_DIVISION_BY_ZERO),
653 errmsg("division by zero")));
655 PG_RETURN_INT64(val1 / val2);
659 int48pl(PG_FUNCTION_ARGS)
661 int32 val1 = PG_GETARG_INT32(0);
662 int64 val2 = PG_GETARG_INT64(1);
664 PG_RETURN_INT64(val1 + val2);
668 int48mi(PG_FUNCTION_ARGS)
670 int32 val1 = PG_GETARG_INT32(0);
671 int64 val2 = PG_GETARG_INT64(1);
673 PG_RETURN_INT64(val1 - val2);
677 int48mul(PG_FUNCTION_ARGS)
679 int32 val1 = PG_GETARG_INT32(0);
680 int64 val2 = PG_GETARG_INT64(1);
682 PG_RETURN_INT64(val1 * val2);
686 int48div(PG_FUNCTION_ARGS)
688 int32 val1 = PG_GETARG_INT32(0);
689 int64 val2 = PG_GETARG_INT64(1);
693 (errcode(ERRCODE_DIVISION_BY_ZERO),
694 errmsg("division by zero")));
696 PG_RETURN_INT64(val1 / val2);
699 /* Binary arithmetics
701 * int8and - returns arg1 & arg2
702 * int8or - returns arg1 | arg2
703 * int8xor - returns arg1 # arg2
704 * int8not - returns ~arg1
705 * int8shl - returns arg1 << arg2
706 * int8shr - returns arg1 >> arg2
710 int8and(PG_FUNCTION_ARGS)
712 int64 arg1 = PG_GETARG_INT64(0);
713 int64 arg2 = PG_GETARG_INT64(1);
715 PG_RETURN_INT64(arg1 & arg2);
719 int8or(PG_FUNCTION_ARGS)
721 int64 arg1 = PG_GETARG_INT64(0);
722 int64 arg2 = PG_GETARG_INT64(1);
724 PG_RETURN_INT64(arg1 | arg2);
728 int8xor(PG_FUNCTION_ARGS)
730 int64 arg1 = PG_GETARG_INT64(0);
731 int64 arg2 = PG_GETARG_INT64(1);
733 PG_RETURN_INT64(arg1 ^ arg2);
737 int8not(PG_FUNCTION_ARGS)
739 int64 arg1 = PG_GETARG_INT64(0);
741 PG_RETURN_INT64(~arg1);
745 int8shl(PG_FUNCTION_ARGS)
747 int64 arg1 = PG_GETARG_INT64(0);
748 int32 arg2 = PG_GETARG_INT32(1);
750 PG_RETURN_INT64(arg1 << arg2);
754 int8shr(PG_FUNCTION_ARGS)
756 int64 arg1 = PG_GETARG_INT64(0);
757 int32 arg2 = PG_GETARG_INT32(1);
759 PG_RETURN_INT64(arg1 >> arg2);
762 /*----------------------------------------------------------
763 * Conversion operators.
764 *---------------------------------------------------------*/
767 int48(PG_FUNCTION_ARGS)
769 int32 val = PG_GETARG_INT32(0);
771 PG_RETURN_INT64((int64) val);
775 int84(PG_FUNCTION_ARGS)
777 int64 val = PG_GETARG_INT64(0);
780 result = (int32) val;
782 /* Test for overflow by reverse-conversion. */
783 if ((int64) result != val)
785 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
786 errmsg("integer out of range")));
788 PG_RETURN_INT32(result);
792 int28(PG_FUNCTION_ARGS)
794 int16 val = PG_GETARG_INT16(0);
796 PG_RETURN_INT64((int64) val);
800 int82(PG_FUNCTION_ARGS)
802 int64 val = PG_GETARG_INT64(0);
805 result = (int16) val;
807 /* Test for overflow by reverse-conversion. */
808 if ((int64) result != val)
810 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
811 errmsg("integer out of range")));
813 PG_RETURN_INT16(result);
817 i8tod(PG_FUNCTION_ARGS)
819 int64 val = PG_GETARG_INT64(0);
824 PG_RETURN_FLOAT8(result);
828 * Convert float8 to 8-byte integer.
831 dtoi8(PG_FUNCTION_ARGS)
833 float8 val = PG_GETARG_FLOAT8(0);
836 /* Round val to nearest integer (but it's still in float form) */
840 * Does it fit in an int64? Avoid assuming that we have handy
841 * constants defined for the range boundaries, instead test for
842 * overflow by reverse-conversion.
844 result = (int64) val;
846 if ((float8) result != val)
848 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
849 errmsg("integer out of range")));
851 PG_RETURN_INT64(result);
855 i8tof(PG_FUNCTION_ARGS)
857 int64 val = PG_GETARG_INT64(0);
862 PG_RETURN_FLOAT4(result);
866 * Convert float4 to 8-byte integer.
869 ftoi8(PG_FUNCTION_ARGS)
871 float4 val = PG_GETARG_FLOAT4(0);
875 /* Round val to nearest integer (but it's still in float form) */
879 * Does it fit in an int64? Avoid assuming that we have handy
880 * constants defined for the range boundaries, instead test for
881 * overflow by reverse-conversion.
883 result = (int64) dval;
885 if ((float8) result != dval)
887 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
888 errmsg("integer out of range")));
890 PG_RETURN_INT64(result);
894 i8tooid(PG_FUNCTION_ARGS)
896 int64 val = PG_GETARG_INT64(0);
901 /* Test for overflow by reverse-conversion. */
902 if ((int64) result != val)
904 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
905 errmsg("OID out of range")));
907 PG_RETURN_OID(result);
911 oidtoi8(PG_FUNCTION_ARGS)
913 Oid val = PG_GETARG_OID(0);
915 PG_RETURN_INT64((int64) val);
919 text_int8(PG_FUNCTION_ARGS)
921 text *str = PG_GETARG_TEXT_P(0);
926 len = (VARSIZE(str) - VARHDRSZ);
928 memcpy(s, VARDATA(str), len);
931 result = DirectFunctionCall1(int8in, CStringGetDatum(s));
939 int8_text(PG_FUNCTION_ARGS)
941 /* val is int64, but easier to leave it as Datum */
942 Datum val = PG_GETARG_DATUM(0);
947 s = DatumGetCString(DirectFunctionCall1(int8out, val));
950 result = (text *) palloc(VARHDRSZ + len);
952 VARATT_SIZEP(result) = len + VARHDRSZ;
953 memcpy(VARDATA(result), s, len);
957 PG_RETURN_TEXT_P(result);