]> granicus.if.org Git - postgresql/blob - src/backend/utils/adt/int8.c
33e0b41fe5940e8541f6f9c4df4a3fd9fd8c2435
[postgresql] / src / backend / utils / adt / int8.c
1 /*-------------------------------------------------------------------------
2  *
3  * int8.c
4  *        Internal 64-bit integer operations
5  *
6  * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
7  * Portions Copyright (c) 1994, Regents of the University of California
8  *
9  * IDENTIFICATION
10  *        $Header: /cvsroot/pgsql/src/backend/utils/adt/int8.c,v 1.40 2002/06/20 20:29:37 momjian Exp $
11  *
12  *-------------------------------------------------------------------------
13  */
14 #include "postgres.h"
15
16 #include <ctype.h>
17 #include <time.h>
18 #include <math.h>
19 #include <float.h>
20 #include <limits.h>
21
22 #include "utils/int8.h"
23
24
25 #define MAXINT8LEN              25
26
27 #ifndef INT_MAX
28 #define INT_MAX (0x7FFFFFFFL)
29 #endif
30 #ifndef INT_MIN
31 #define INT_MIN (-INT_MAX-1)
32 #endif
33 #ifndef SHRT_MAX
34 #define SHRT_MAX (0x7FFF)
35 #endif
36 #ifndef SHRT_MIN
37 #define SHRT_MIN (-SHRT_MAX-1)
38 #endif
39
40
41 /***********************************************************************
42  **
43  **             Routines for 64-bit integers.
44  **
45  ***********************************************************************/
46
47 /*----------------------------------------------------------
48  * Formatting and conversion routines.
49  *---------------------------------------------------------*/
50
51 /* int8in()
52  */
53 Datum
54 int8in(PG_FUNCTION_ARGS)
55 {
56         char       *str = PG_GETARG_CSTRING(0);
57         int64           result;
58         char       *ptr = str;
59         int64           tmp = 0;
60         int                     sign = 1;
61
62         /*
63          * Do our own scan, rather than relying on sscanf which might be
64          * broken for long long.
65          */
66         while (*ptr && isspace((unsigned char) *ptr))           /* skip leading spaces */
67                 ptr++;
68         /* handle sign */
69         if (*ptr == '-')
70         {
71                 ptr++;
72                 sign = -1;
73                 /*
74                  * Do an explicit check for INT64_MIN.  Ugly though this is, it's
75                  * cleaner than trying to get the loop below to handle it portably.
76                  */
77 #ifndef INT64_IS_BUSTED
78                 if (strcmp(ptr, "9223372036854775808") == 0)
79                 {
80                         result = - INT64CONST(0x7fffffffffffffff) - 1;
81                         PG_RETURN_INT64(result);
82                 }
83 #endif
84         }
85         else if (*ptr == '+')
86                 ptr++;
87         if (!isdigit((unsigned char) *ptr)) /* require at least one digit */
88                 elog(ERROR, "Bad int8 external representation \"%s\"", str);
89         while (*ptr && isdigit((unsigned char) *ptr))           /* process digits */
90         {
91                 int64           newtmp = tmp * 10 + (*ptr++ - '0');
92
93                 if ((newtmp / 10) != tmp)               /* overflow? */
94                         elog(ERROR, "int8 value out of range: \"%s\"", str);
95                 tmp = newtmp;
96         }
97         if (*ptr)                                       /* trailing junk? */
98                 elog(ERROR, "Bad int8 external representation \"%s\"", str);
99
100         result = (sign < 0) ? -tmp : tmp;
101
102         PG_RETURN_INT64(result);
103 }
104
105
106 /* int8out()
107  */
108 Datum
109 int8out(PG_FUNCTION_ARGS)
110 {
111         int64           val = PG_GETARG_INT64(0);
112         char       *result;
113         int                     len;
114         char            buf[MAXINT8LEN + 1];
115
116         if ((len = snprintf(buf, MAXINT8LEN, INT64_FORMAT, val)) < 0)
117                 elog(ERROR, "Unable to format int8");
118
119         result = pstrdup(buf);
120         PG_RETURN_CSTRING(result);
121 }
122
123
124 /*----------------------------------------------------------
125  *      Relational operators for int8s, including cross-data-type comparisons.
126  *---------------------------------------------------------*/
127
128 /* int8relop()
129  * Is val1 relop val2?
130  */
131 Datum
132 int8eq(PG_FUNCTION_ARGS)
133 {
134         int64           val1 = PG_GETARG_INT64(0);
135         int64           val2 = PG_GETARG_INT64(1);
136
137         PG_RETURN_BOOL(val1 == val2);
138 }
139
140 Datum
141 int8ne(PG_FUNCTION_ARGS)
142 {
143         int64           val1 = PG_GETARG_INT64(0);
144         int64           val2 = PG_GETARG_INT64(1);
145
146         PG_RETURN_BOOL(val1 != val2);
147 }
148
149 Datum
150 int8lt(PG_FUNCTION_ARGS)
151 {
152         int64           val1 = PG_GETARG_INT64(0);
153         int64           val2 = PG_GETARG_INT64(1);
154
155         PG_RETURN_BOOL(val1 < val2);
156 }
157
158 Datum
159 int8gt(PG_FUNCTION_ARGS)
160 {
161         int64           val1 = PG_GETARG_INT64(0);
162         int64           val2 = PG_GETARG_INT64(1);
163
164         PG_RETURN_BOOL(val1 > val2);
165 }
166
167 Datum
168 int8le(PG_FUNCTION_ARGS)
169 {
170         int64           val1 = PG_GETARG_INT64(0);
171         int64           val2 = PG_GETARG_INT64(1);
172
173         PG_RETURN_BOOL(val1 <= val2);
174 }
175
176 Datum
177 int8ge(PG_FUNCTION_ARGS)
178 {
179         int64           val1 = PG_GETARG_INT64(0);
180         int64           val2 = PG_GETARG_INT64(1);
181
182         PG_RETURN_BOOL(val1 >= val2);
183 }
184
185 /* int84relop()
186  * Is 64-bit val1 relop 32-bit val2?
187  */
188 Datum
189 int84eq(PG_FUNCTION_ARGS)
190 {
191         int64           val1 = PG_GETARG_INT64(0);
192         int32           val2 = PG_GETARG_INT32(1);
193
194         PG_RETURN_BOOL(val1 == val2);
195 }
196
197 Datum
198 int84ne(PG_FUNCTION_ARGS)
199 {
200         int64           val1 = PG_GETARG_INT64(0);
201         int32           val2 = PG_GETARG_INT32(1);
202
203         PG_RETURN_BOOL(val1 != val2);
204 }
205
206 Datum
207 int84lt(PG_FUNCTION_ARGS)
208 {
209         int64           val1 = PG_GETARG_INT64(0);
210         int32           val2 = PG_GETARG_INT32(1);
211
212         PG_RETURN_BOOL(val1 < val2);
213 }
214
215 Datum
216 int84gt(PG_FUNCTION_ARGS)
217 {
218         int64           val1 = PG_GETARG_INT64(0);
219         int32           val2 = PG_GETARG_INT32(1);
220
221         PG_RETURN_BOOL(val1 > val2);
222 }
223
224 Datum
225 int84le(PG_FUNCTION_ARGS)
226 {
227         int64           val1 = PG_GETARG_INT64(0);
228         int32           val2 = PG_GETARG_INT32(1);
229
230         PG_RETURN_BOOL(val1 <= val2);
231 }
232
233 Datum
234 int84ge(PG_FUNCTION_ARGS)
235 {
236         int64           val1 = PG_GETARG_INT64(0);
237         int32           val2 = PG_GETARG_INT32(1);
238
239         PG_RETURN_BOOL(val1 >= val2);
240 }
241
242 /* int48relop()
243  * Is 32-bit val1 relop 64-bit val2?
244  */
245 Datum
246 int48eq(PG_FUNCTION_ARGS)
247 {
248         int32           val1 = PG_GETARG_INT32(0);
249         int64           val2 = PG_GETARG_INT64(1);
250
251         PG_RETURN_BOOL(val1 == val2);
252 }
253
254 Datum
255 int48ne(PG_FUNCTION_ARGS)
256 {
257         int32           val1 = PG_GETARG_INT32(0);
258         int64           val2 = PG_GETARG_INT64(1);
259
260         PG_RETURN_BOOL(val1 != val2);
261 }
262
263 Datum
264 int48lt(PG_FUNCTION_ARGS)
265 {
266         int32           val1 = PG_GETARG_INT32(0);
267         int64           val2 = PG_GETARG_INT64(1);
268
269         PG_RETURN_BOOL(val1 < val2);
270 }
271
272 Datum
273 int48gt(PG_FUNCTION_ARGS)
274 {
275         int32           val1 = PG_GETARG_INT32(0);
276         int64           val2 = PG_GETARG_INT64(1);
277
278         PG_RETURN_BOOL(val1 > val2);
279 }
280
281 Datum
282 int48le(PG_FUNCTION_ARGS)
283 {
284         int32           val1 = PG_GETARG_INT32(0);
285         int64           val2 = PG_GETARG_INT64(1);
286
287         PG_RETURN_BOOL(val1 <= val2);
288 }
289
290 Datum
291 int48ge(PG_FUNCTION_ARGS)
292 {
293         int32           val1 = PG_GETARG_INT32(0);
294         int64           val2 = PG_GETARG_INT64(1);
295
296         PG_RETURN_BOOL(val1 >= val2);
297 }
298
299 /* int82relop()
300  * Is 64-bit val1 relop 16-bit val2?
301  */
302 Datum
303 int82eq(PG_FUNCTION_ARGS)
304 {
305         int64           val1 = PG_GETARG_INT64(0);
306         int16           val2 = PG_GETARG_INT16(1);
307
308         PG_RETURN_BOOL(val1 == val2);
309 }
310
311 Datum
312 int82ne(PG_FUNCTION_ARGS)
313 {
314         int64           val1 = PG_GETARG_INT64(0);
315         int16           val2 = PG_GETARG_INT16(1);
316
317         PG_RETURN_BOOL(val1 != val2);
318 }
319
320 Datum
321 int82lt(PG_FUNCTION_ARGS)
322 {
323         int64           val1 = PG_GETARG_INT64(0);
324         int16           val2 = PG_GETARG_INT16(1);
325
326         PG_RETURN_BOOL(val1 < val2);
327 }
328
329 Datum
330 int82gt(PG_FUNCTION_ARGS)
331 {
332         int64           val1 = PG_GETARG_INT64(0);
333         int16           val2 = PG_GETARG_INT16(1);
334
335         PG_RETURN_BOOL(val1 > val2);
336 }
337
338 Datum
339 int82le(PG_FUNCTION_ARGS)
340 {
341         int64           val1 = PG_GETARG_INT64(0);
342         int16           val2 = PG_GETARG_INT16(1);
343
344         PG_RETURN_BOOL(val1 <= val2);
345 }
346
347 Datum
348 int82ge(PG_FUNCTION_ARGS)
349 {
350         int64           val1 = PG_GETARG_INT64(0);
351         int16           val2 = PG_GETARG_INT16(1);
352
353         PG_RETURN_BOOL(val1 >= val2);
354 }
355
356 /* int28relop()
357  * Is 16-bit val1 relop 64-bit val2?
358  */
359 Datum
360 int28eq(PG_FUNCTION_ARGS)
361 {
362         int16           val1 = PG_GETARG_INT16(0);
363         int64           val2 = PG_GETARG_INT64(1);
364
365         PG_RETURN_BOOL(val1 == val2);
366 }
367
368 Datum
369 int28ne(PG_FUNCTION_ARGS)
370 {
371         int16           val1 = PG_GETARG_INT16(0);
372         int64           val2 = PG_GETARG_INT64(1);
373
374         PG_RETURN_BOOL(val1 != val2);
375 }
376
377 Datum
378 int28lt(PG_FUNCTION_ARGS)
379 {
380         int16           val1 = PG_GETARG_INT16(0);
381         int64           val2 = PG_GETARG_INT64(1);
382
383         PG_RETURN_BOOL(val1 < val2);
384 }
385
386 Datum
387 int28gt(PG_FUNCTION_ARGS)
388 {
389         int16           val1 = PG_GETARG_INT16(0);
390         int64           val2 = PG_GETARG_INT64(1);
391
392         PG_RETURN_BOOL(val1 > val2);
393 }
394
395 Datum
396 int28le(PG_FUNCTION_ARGS)
397 {
398         int16           val1 = PG_GETARG_INT16(0);
399         int64           val2 = PG_GETARG_INT64(1);
400
401         PG_RETURN_BOOL(val1 <= val2);
402 }
403
404 Datum
405 int28ge(PG_FUNCTION_ARGS)
406 {
407         int16           val1 = PG_GETARG_INT16(0);
408         int64           val2 = PG_GETARG_INT64(1);
409
410         PG_RETURN_BOOL(val1 >= val2);
411 }
412
413
414 /*----------------------------------------------------------
415  *      Arithmetic operators on 64-bit integers.
416  *---------------------------------------------------------*/
417
418 Datum
419 int8um(PG_FUNCTION_ARGS)
420 {
421         int64           val = PG_GETARG_INT64(0);
422
423         PG_RETURN_INT64(-val);
424 }
425
426 Datum
427 int8up(PG_FUNCTION_ARGS)
428 {
429         int64           val = PG_GETARG_INT64(0);
430
431         PG_RETURN_INT64(val);
432 }
433
434 Datum
435 int8pl(PG_FUNCTION_ARGS)
436 {
437         int64           val1 = PG_GETARG_INT64(0);
438         int64           val2 = PG_GETARG_INT64(1);
439
440         PG_RETURN_INT64(val1 + val2);
441 }
442
443 Datum
444 int8mi(PG_FUNCTION_ARGS)
445 {
446         int64           val1 = PG_GETARG_INT64(0);
447         int64           val2 = PG_GETARG_INT64(1);
448
449         PG_RETURN_INT64(val1 - val2);
450 }
451
452 Datum
453 int8mul(PG_FUNCTION_ARGS)
454 {
455         int64           val1 = PG_GETARG_INT64(0);
456         int64           val2 = PG_GETARG_INT64(1);
457
458         PG_RETURN_INT64(val1 * val2);
459 }
460
461 Datum
462 int8div(PG_FUNCTION_ARGS)
463 {
464         int64           val1 = PG_GETARG_INT64(0);
465         int64           val2 = PG_GETARG_INT64(1);
466
467         PG_RETURN_INT64(val1 / val2);
468 }
469
470 /* int8abs()
471  * Absolute value
472  */
473 Datum
474 int8abs(PG_FUNCTION_ARGS)
475 {
476         int64           arg1 = PG_GETARG_INT64(0);
477
478         PG_RETURN_INT64((arg1 < 0) ? -arg1 : arg1);
479 }
480
481 /* int8mod()
482  * Modulo operation.
483  */
484 Datum
485 int8mod(PG_FUNCTION_ARGS)
486 {
487         int64           val1 = PG_GETARG_INT64(0);
488         int64           val2 = PG_GETARG_INT64(1);
489         int64           result;
490
491         result = val1 / val2;
492         result *= val2;
493         result = val1 - result;
494
495         PG_RETURN_INT64(result);
496 }
497
498 /* int8fac()
499  * Factorial
500  */
501 Datum
502 int8fac(PG_FUNCTION_ARGS)
503 {
504         int64           arg1 = PG_GETARG_INT64(0);
505         int64           result;
506         int64           i;
507
508         if (arg1 == 0)
509                 result = 1;
510         else if (arg1 < 1)
511                 result = 0;
512         else
513                 for (i = arg1, result = 1; i > 0; --i)
514                         result *= i;
515
516         PG_RETURN_INT64(result);
517 }
518
519 Datum
520 int8inc(PG_FUNCTION_ARGS)
521 {
522         int64           arg = PG_GETARG_INT64(0);
523
524         PG_RETURN_INT64(arg + 1);
525 }
526
527 Datum
528 int8larger(PG_FUNCTION_ARGS)
529 {
530         int64           val1 = PG_GETARG_INT64(0);
531         int64           val2 = PG_GETARG_INT64(1);
532         int64           result;
533
534         result = ((val1 > val2) ? val1 : val2);
535
536         PG_RETURN_INT64(result);
537 }
538
539 Datum
540 int8smaller(PG_FUNCTION_ARGS)
541 {
542         int64           val1 = PG_GETARG_INT64(0);
543         int64           val2 = PG_GETARG_INT64(1);
544         int64           result;
545
546         result = ((val1 < val2) ? val1 : val2);
547
548         PG_RETURN_INT64(result);
549 }
550
551 Datum
552 int84pl(PG_FUNCTION_ARGS)
553 {
554         int64           val1 = PG_GETARG_INT64(0);
555         int32           val2 = PG_GETARG_INT32(1);
556
557         PG_RETURN_INT64(val1 + val2);
558 }
559
560 Datum
561 int84mi(PG_FUNCTION_ARGS)
562 {
563         int64           val1 = PG_GETARG_INT64(0);
564         int32           val2 = PG_GETARG_INT32(1);
565
566         PG_RETURN_INT64(val1 - val2);
567 }
568
569 Datum
570 int84mul(PG_FUNCTION_ARGS)
571 {
572         int64           val1 = PG_GETARG_INT64(0);
573         int32           val2 = PG_GETARG_INT32(1);
574
575         PG_RETURN_INT64(val1 * val2);
576 }
577
578 Datum
579 int84div(PG_FUNCTION_ARGS)
580 {
581         int64           val1 = PG_GETARG_INT64(0);
582         int32           val2 = PG_GETARG_INT32(1);
583
584         PG_RETURN_INT64(val1 / val2);
585 }
586
587 Datum
588 int48pl(PG_FUNCTION_ARGS)
589 {
590         int32           val1 = PG_GETARG_INT32(0);
591         int64           val2 = PG_GETARG_INT64(1);
592
593         PG_RETURN_INT64(val1 + val2);
594 }
595
596 Datum
597 int48mi(PG_FUNCTION_ARGS)
598 {
599         int32           val1 = PG_GETARG_INT32(0);
600         int64           val2 = PG_GETARG_INT64(1);
601
602         PG_RETURN_INT64(val1 - val2);
603 }
604
605 Datum
606 int48mul(PG_FUNCTION_ARGS)
607 {
608         int32           val1 = PG_GETARG_INT32(0);
609         int64           val2 = PG_GETARG_INT64(1);
610
611         PG_RETURN_INT64(val1 * val2);
612 }
613
614 Datum
615 int48div(PG_FUNCTION_ARGS)
616 {
617         int32           val1 = PG_GETARG_INT32(0);
618         int64           val2 = PG_GETARG_INT64(1);
619
620         PG_RETURN_INT64(val1 / val2);
621 }
622
623 /* Binary arithmetics
624  *
625  *              int8and         - returns arg1 & arg2
626  *              int8or          - returns arg1 | arg2
627  *              int8xor         - returns arg1 # arg2
628  *              int8not         - returns ~arg1
629  *              int8shl         - returns arg1 << arg2
630  *              int8shr         - returns arg1 >> arg2
631  */
632
633 Datum
634 int8and(PG_FUNCTION_ARGS)
635 {
636         int64           arg1 = PG_GETARG_INT64(0);
637         int64           arg2 = PG_GETARG_INT64(1);
638
639         PG_RETURN_INT64(arg1 & arg2);
640 }
641
642 Datum
643 int8or(PG_FUNCTION_ARGS)
644 {
645         int64           arg1 = PG_GETARG_INT64(0);
646         int64           arg2 = PG_GETARG_INT64(1);
647
648         PG_RETURN_INT64(arg1 | arg2);
649 }
650
651 Datum
652 int8xor(PG_FUNCTION_ARGS)
653 {
654         int64           arg1 = PG_GETARG_INT64(0);
655         int64           arg2 = PG_GETARG_INT64(1);
656
657         PG_RETURN_INT64(arg1 ^ arg2);
658 }
659
660 Datum
661 int8not(PG_FUNCTION_ARGS)
662 {
663         int64           arg1 = PG_GETARG_INT64(0);
664
665         PG_RETURN_INT64(~arg1);
666 }
667
668 Datum
669 int8shl(PG_FUNCTION_ARGS)
670 {
671         int64           arg1 = PG_GETARG_INT64(0);
672         int32           arg2 = PG_GETARG_INT32(1);
673
674         PG_RETURN_INT64(arg1 << arg2);
675 }
676
677 Datum
678 int8shr(PG_FUNCTION_ARGS)
679 {
680         int64           arg1 = PG_GETARG_INT64(0);
681         int32           arg2 = PG_GETARG_INT32(1);
682
683         PG_RETURN_INT64(arg1 >> arg2);
684 }
685
686 /*----------------------------------------------------------
687  *      Conversion operators.
688  *---------------------------------------------------------*/
689
690 Datum
691 int48(PG_FUNCTION_ARGS)
692 {
693         int32           val = PG_GETARG_INT32(0);
694
695         PG_RETURN_INT64((int64) val);
696 }
697
698 Datum
699 int84(PG_FUNCTION_ARGS)
700 {
701         int64           val = PG_GETARG_INT64(0);
702         int32           result;
703
704         result = (int32) val;
705
706         /* Test for overflow by reverse-conversion. */
707         if ((int64) result != val)
708                 elog(ERROR, "int8 conversion to int4 is out of range");
709
710         PG_RETURN_INT32(result);
711 }
712
713 Datum
714 int28(PG_FUNCTION_ARGS)
715 {
716         int16           val = PG_GETARG_INT16(0);
717
718         PG_RETURN_INT64((int64) val);
719 }
720
721 Datum
722 int82(PG_FUNCTION_ARGS)
723 {
724         int64           val = PG_GETARG_INT64(0);
725         int16           result;
726
727         result = (int16) val;
728
729         /* Test for overflow by reverse-conversion. */
730         if ((int64) result != val)
731                 elog(ERROR, "int8 conversion to int2 is out of range");
732
733         PG_RETURN_INT16(result);
734 }
735
736 Datum
737 i8tod(PG_FUNCTION_ARGS)
738 {
739         int64           val = PG_GETARG_INT64(0);
740         float8          result;
741
742         result = val;
743
744         PG_RETURN_FLOAT8(result);
745 }
746
747 /* dtoi8()
748  * Convert double float to 8-byte integer.
749  */
750 Datum
751 dtoi8(PG_FUNCTION_ARGS)
752 {
753         float8          val = PG_GETARG_FLOAT8(0);
754         int64           result;
755
756         /* Round val to nearest integer (but it's still in float form) */
757         val = rint(val);
758
759         /*
760          * Does it fit in an int64?  Avoid assuming that we have handy
761          * constants defined for the range boundaries, instead test for
762          * overflow by reverse-conversion.
763          */
764         result = (int64) val;
765
766         if ((float8) result != val)
767                 elog(ERROR, "Floating point conversion to int8 is out of range");
768
769         PG_RETURN_INT64(result);
770 }
771
772 /* text_int8()
773  */
774 Datum
775 text_int8(PG_FUNCTION_ARGS)
776 {
777         text       *str = PG_GETARG_TEXT_P(0);
778         int                     len;
779         char       *s;
780         Datum           result;
781
782         len = (VARSIZE(str) - VARHDRSZ);
783         s = palloc(len + 1);
784         memcpy(s, VARDATA(str), len);
785         *(s + len) = '\0';
786
787         result = DirectFunctionCall1(int8in, CStringGetDatum(s));
788
789         pfree(s);
790
791         return result;
792 }
793
794
795 /* int8_text()
796  */
797 Datum
798 int8_text(PG_FUNCTION_ARGS)
799 {
800         /* val is int64, but easier to leave it as Datum */
801         Datum           val = PG_GETARG_DATUM(0);
802         char       *s;
803         int                     len;
804         text       *result;
805
806         s = DatumGetCString(DirectFunctionCall1(int8out, val));
807         len = strlen(s);
808
809         result = (text *) palloc(VARHDRSZ + len);
810
811         VARATT_SIZEP(result) = len + VARHDRSZ;
812         memcpy(VARDATA(result), s, len);
813
814         pfree(s);
815
816         PG_RETURN_TEXT_P(result);
817 }