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