]> granicus.if.org Git - postgresql/blob - src/backend/utils/adt/int8.c
773ec8b193ddec09380acb03a807cc721608911a
[postgresql] / src / backend / utils / adt / int8.c
1 /*-------------------------------------------------------------------------
2  *
3  * int8.c
4  *        Internal 64-bit integer operations
5  *
6  * Portions Copyright (c) 1996-2000, PostgreSQL, Inc
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.23 2000/07/12 22:59:09 petere 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((int) *ptr))             /* skip leading spaces */
71                 ptr++;
72         if (*ptr == '-')                        /* handle sign */
73                 sign = -1, ptr++;
74         else if (*ptr == '+')
75                 ptr++;
76         if (!isdigit((int) *ptr))                       /* require at least one digit */
77                 elog(ERROR, "Bad int8 external representation \"%s\"", str);
78         while (*ptr && isdigit((int) *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.
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
289 /*----------------------------------------------------------
290  *      Arithmetic operators on 64-bit integers.
291  *---------------------------------------------------------*/
292
293 Datum
294 int8um(PG_FUNCTION_ARGS)
295 {
296         int64           val = PG_GETARG_INT64(0);
297
298         PG_RETURN_INT64(- val);
299 }
300
301 Datum
302 int8pl(PG_FUNCTION_ARGS)
303 {
304         int64           val1 = PG_GETARG_INT64(0);
305         int64           val2 = PG_GETARG_INT64(1);
306
307         PG_RETURN_INT64(val1 + val2);
308 }
309
310 Datum
311 int8mi(PG_FUNCTION_ARGS)
312 {
313         int64           val1 = PG_GETARG_INT64(0);
314         int64           val2 = PG_GETARG_INT64(1);
315
316         PG_RETURN_INT64(val1 - val2);
317 }
318
319 Datum
320 int8mul(PG_FUNCTION_ARGS)
321 {
322         int64           val1 = PG_GETARG_INT64(0);
323         int64           val2 = PG_GETARG_INT64(1);
324
325         PG_RETURN_INT64(val1 * val2);
326 }
327
328 Datum
329 int8div(PG_FUNCTION_ARGS)
330 {
331         int64           val1 = PG_GETARG_INT64(0);
332         int64           val2 = PG_GETARG_INT64(1);
333
334         PG_RETURN_INT64(val1 / val2);
335 }
336
337 /* int8abs()
338  * Absolute value
339  */
340 Datum
341 int8abs(PG_FUNCTION_ARGS)
342 {
343         int64           arg1 = PG_GETARG_INT64(0);
344
345         PG_RETURN_INT64((arg1 < 0) ? -arg1 : arg1);
346 }
347
348 /* int8mod()
349  * Modulo operation.
350  */
351 Datum
352 int8mod(PG_FUNCTION_ARGS)
353 {
354         int64           val1 = PG_GETARG_INT64(0);
355         int64           val2 = PG_GETARG_INT64(1);
356         int64           result;
357
358         result = val1 / val2;
359         result *= val2;
360         result = val1 - result;
361
362         PG_RETURN_INT64(result);
363 }
364
365 /* int8fac()
366  * Factorial
367  */
368 Datum
369 int8fac(PG_FUNCTION_ARGS)
370 {
371         int64           arg1 = PG_GETARG_INT64(0);
372         int64           result;
373         int64           i;
374
375         if (arg1 < 1)
376                 result = 0;
377         else
378                 for (i = arg1, result = 1; i > 0; --i)
379                         result *= i;
380
381         PG_RETURN_INT64(result);
382 }
383
384 Datum
385 int8larger(PG_FUNCTION_ARGS)
386 {
387         int64           val1 = PG_GETARG_INT64(0);
388         int64           val2 = PG_GETARG_INT64(1);
389         int64           result;
390
391         result = ((val1 > val2) ? val1 : val2);
392
393         PG_RETURN_INT64(result);
394 }
395
396 Datum
397 int8smaller(PG_FUNCTION_ARGS)
398 {
399         int64           val1 = PG_GETARG_INT64(0);
400         int64           val2 = PG_GETARG_INT64(1);
401         int64           result;
402
403         result = ((val1 < val2) ? val1 : val2);
404
405         PG_RETURN_INT64(result);
406 }
407
408 Datum
409 int84pl(PG_FUNCTION_ARGS)
410 {
411         int64           val1 = PG_GETARG_INT64(0);
412         int32           val2 = PG_GETARG_INT32(1);
413
414         PG_RETURN_INT64(val1 + val2);
415 }
416
417 Datum
418 int84mi(PG_FUNCTION_ARGS)
419 {
420         int64           val1 = PG_GETARG_INT64(0);
421         int32           val2 = PG_GETARG_INT32(1);
422
423         PG_RETURN_INT64(val1 - val2);
424 }
425
426 Datum
427 int84mul(PG_FUNCTION_ARGS)
428 {
429         int64           val1 = PG_GETARG_INT64(0);
430         int32           val2 = PG_GETARG_INT32(1);
431
432         PG_RETURN_INT64(val1 * val2);
433 }
434
435 Datum
436 int84div(PG_FUNCTION_ARGS)
437 {
438         int64           val1 = PG_GETARG_INT64(0);
439         int32           val2 = PG_GETARG_INT32(1);
440
441         PG_RETURN_INT64(val1 / val2);
442 }
443
444 Datum
445 int48pl(PG_FUNCTION_ARGS)
446 {
447         int32           val1 = PG_GETARG_INT32(0);
448         int64           val2 = PG_GETARG_INT64(1);
449
450         PG_RETURN_INT64(val1 + val2);
451 }
452
453 Datum
454 int48mi(PG_FUNCTION_ARGS)
455 {
456         int32           val1 = PG_GETARG_INT32(0);
457         int64           val2 = PG_GETARG_INT64(1);
458
459         PG_RETURN_INT64(val1 - val2);
460 }
461
462 Datum
463 int48mul(PG_FUNCTION_ARGS)
464 {
465         int32           val1 = PG_GETARG_INT32(0);
466         int64           val2 = PG_GETARG_INT64(1);
467
468         PG_RETURN_INT64(val1 * val2);
469 }
470
471 Datum
472 int48div(PG_FUNCTION_ARGS)
473 {
474         int32           val1 = PG_GETARG_INT32(0);
475         int64           val2 = PG_GETARG_INT64(1);
476
477         PG_RETURN_INT64(val1 / val2);
478 }
479
480
481 /*----------------------------------------------------------
482  *      Conversion operators.
483  *---------------------------------------------------------*/
484
485 Datum
486 int48(PG_FUNCTION_ARGS)
487 {
488         int32           val = PG_GETARG_INT32(0);
489
490         PG_RETURN_INT64((int64) val);
491 }
492
493 Datum
494 int84(PG_FUNCTION_ARGS)
495 {
496         int64           val = PG_GETARG_INT64(0);
497         int32           result;
498
499         if ((val < INT_MIN) || (val > INT_MAX))
500                 elog(ERROR, "int8 conversion to int4 is out of range");
501
502         result = (int32) val;
503
504         PG_RETURN_INT32(result);
505 }
506
507 Datum
508 i8tod(PG_FUNCTION_ARGS)
509 {
510         int64           val = PG_GETARG_INT64(0);
511         float8          result;
512
513         result = val;
514
515         PG_RETURN_FLOAT8(result);
516 }
517
518 /* dtoi8()
519  * Convert double float to 8-byte integer.
520  * Do a range check before the conversion.
521  * Note that the comparison probably isn't quite right
522  *      since we only have ~52 bits of precision in a double float
523  *      and so subtracting one from a large number gives the large
524  *      number exactly. However, for some reason the comparison below
525  *      does the right thing on my i686/linux-rh4.2 box.
526  * - thomas 1998-06-16
527  */
528 Datum
529 dtoi8(PG_FUNCTION_ARGS)
530 {
531         float8          val = PG_GETARG_FLOAT8(0);
532         int64           result;
533
534         if ((val < (-pow(2.0, 63.0) + 1)) || (val > (pow(2.0, 63.0) - 1)))
535                 elog(ERROR, "Floating point conversion to int64 is out of range");
536
537         result = (int64) val;
538
539         PG_RETURN_INT64(result);
540 }
541
542 /* text_int8()
543  */
544 Datum
545 text_int8(PG_FUNCTION_ARGS)
546 {
547         text       *str = PG_GETARG_TEXT_P(0);
548         int                     len;
549         char       *s;
550         Datum           result;
551
552         len = (VARSIZE(str) - VARHDRSZ);
553         s = palloc(len + 1);
554         memcpy(s, VARDATA(str), len);
555         *(s + len) = '\0';
556
557         result = DirectFunctionCall1(int8in, CStringGetDatum(s));
558
559         pfree(s);
560
561         return result;
562 }
563
564
565 /* int8_text()
566  */
567 Datum
568 int8_text(PG_FUNCTION_ARGS)
569 {
570         /* val is int64, but easier to leave it as Datum */
571         Datum           val = PG_GETARG_DATUM(0);
572         char       *s;
573         int                     len;
574         text       *result;
575
576         s = DatumGetCString(DirectFunctionCall1(int8out, val));
577         len = strlen(s);
578
579         result = (text *) palloc(VARHDRSZ + len);
580
581         VARATT_SIZEP(result) = len + VARHDRSZ;
582         memcpy(VARDATA(result), s, len);
583
584         pfree(s);
585
586         PG_RETURN_TEXT_P(result);
587 }