int8.c 13.4 KB
Newer Older
1 2
/*-------------------------------------------------------------------------
 *
3
 * int8.c
4 5
 *	  Internal 64-bit integer operations
 *
6
 * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
7 8 9
 * Portions Copyright (c) 1994, Regents of the University of California
 *
 * IDENTIFICATION
10
 *	  $Header: /cvsroot/pgsql/src/backend/utils/adt/int8.c,v 1.35 2001/10/25 14:10:06 tgl Exp $
11
 *
12 13
 *-------------------------------------------------------------------------
 */
14 15
#include "postgres.h"

16 17 18 19
#include <ctype.h>
#include <time.h>
#include <math.h>
#include <float.h>
20 21
#include <limits.h>

22 23
#include "utils/int8.h"

24
/* this should be set in pg_config.h, but just in case it wasn't: */
25 26 27 28
#ifndef INT64_FORMAT
#define INT64_FORMAT "%ld"
#endif

29 30
#define MAXINT8LEN		25

31 32 33 34 35 36 37 38 39 40 41 42 43
#ifndef INT_MAX
#define INT_MAX (0x7FFFFFFFL)
#endif
#ifndef INT_MIN
#define INT_MIN (-INT_MAX-1)
#endif
#ifndef SHRT_MAX
#define SHRT_MAX (0x7FFF)
#endif
#ifndef SHRT_MIN
#define SHRT_MIN (-SHRT_MAX-1)
#endif

44 45 46 47 48 49 50 51 52 53 54 55 56

/***********************************************************************
 **
 **		Routines for 64-bit integers.
 **
 ***********************************************************************/

/*----------------------------------------------------------
 * Formatting and conversion routines.
 *---------------------------------------------------------*/

/* int8in()
 */
57 58
Datum
int8in(PG_FUNCTION_ARGS)
59
{
60 61
	char	   *str = PG_GETARG_CSTRING(0);
	int64		result;
62 63 64
	char	   *ptr = str;
	int64		tmp = 0;
	int			sign = 1;
65

Bruce Momjian's avatar
Bruce Momjian committed
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++;
Bruce Momjian's avatar
Bruce Momjian committed
72
	if (*ptr == '-')			/* handle sign */
73 74 75
		sign = -1, ptr++;
	else if (*ptr == '+')
		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 85
		tmp = newtmp;
	}
Bruce Momjian's avatar
Bruce Momjian committed
86
	if (*ptr)					/* trailing junk? */
87
		elog(ERROR, "Bad int8 external representation \"%s\"", str);
88

89
	result = (sign < 0) ? -tmp : tmp;
90

91 92
	PG_RETURN_INT64(result);
}
93 94 95 96


/* int8out()
 */
97 98
Datum
int8out(PG_FUNCTION_ARGS)
99
{
100
	int64		val = PG_GETARG_INT64(0);
101 102 103 104
	char	   *result;
	int			len;
	char		buf[MAXINT8LEN + 1];

105
	if ((len = snprintf(buf, MAXINT8LEN, INT64_FORMAT, val)) < 0)
106
		elog(ERROR, "Unable to format int8");
107

108 109 110
	result = pstrdup(buf);
	PG_RETURN_CSTRING(result);
}
111 112 113


/*----------------------------------------------------------
114
 *	Relational operators for int8s, including cross-data-type comparisons.
115 116 117 118 119
 *---------------------------------------------------------*/

/* int8relop()
 * Is val1 relop val2?
 */
120 121
Datum
int8eq(PG_FUNCTION_ARGS)
122
{
123 124
	int64		val1 = PG_GETARG_INT64(0);
	int64		val2 = PG_GETARG_INT64(1);
125

126 127
	PG_RETURN_BOOL(val1 == val2);
}
128

129 130
Datum
int8ne(PG_FUNCTION_ARGS)
131
{
132 133
	int64		val1 = PG_GETARG_INT64(0);
	int64		val2 = PG_GETARG_INT64(1);
134

135 136
	PG_RETURN_BOOL(val1 != val2);
}
137

138 139
Datum
int8lt(PG_FUNCTION_ARGS)
140
{
141 142
	int64		val1 = PG_GETARG_INT64(0);
	int64		val2 = PG_GETARG_INT64(1);
143

144 145
	PG_RETURN_BOOL(val1 < val2);
}
146

147 148
Datum
int8gt(PG_FUNCTION_ARGS)
149
{
150 151
	int64		val1 = PG_GETARG_INT64(0);
	int64		val2 = PG_GETARG_INT64(1);
152

153 154
	PG_RETURN_BOOL(val1 > val2);
}
155

156 157
Datum
int8le(PG_FUNCTION_ARGS)
158
{
159 160
	int64		val1 = PG_GETARG_INT64(0);
	int64		val2 = PG_GETARG_INT64(1);
161

162 163
	PG_RETURN_BOOL(val1 <= val2);
}
164

165 166
Datum
int8ge(PG_FUNCTION_ARGS)
167
{
168 169
	int64		val1 = PG_GETARG_INT64(0);
	int64		val2 = PG_GETARG_INT64(1);
170

171 172
	PG_RETURN_BOOL(val1 >= val2);
}
173 174 175 176

/* int84relop()
 * Is 64-bit val1 relop 32-bit val2?
 */
177 178
Datum
int84eq(PG_FUNCTION_ARGS)
179
{
180 181
	int64		val1 = PG_GETARG_INT64(0);
	int32		val2 = PG_GETARG_INT32(1);
182

183 184
	PG_RETURN_BOOL(val1 == val2);
}
185

186 187
Datum
int84ne(PG_FUNCTION_ARGS)
188
{
189 190
	int64		val1 = PG_GETARG_INT64(0);
	int32		val2 = PG_GETARG_INT32(1);
191

192 193
	PG_RETURN_BOOL(val1 != val2);
}
194

195 196
Datum
int84lt(PG_FUNCTION_ARGS)
197
{
198 199
	int64		val1 = PG_GETARG_INT64(0);
	int32		val2 = PG_GETARG_INT32(1);
200

201 202
	PG_RETURN_BOOL(val1 < val2);
}
203

204 205
Datum
int84gt(PG_FUNCTION_ARGS)
206
{
207 208
	int64		val1 = PG_GETARG_INT64(0);
	int32		val2 = PG_GETARG_INT32(1);
209

210 211
	PG_RETURN_BOOL(val1 > val2);
}
212

213 214
Datum
int84le(PG_FUNCTION_ARGS)
215
{
216 217
	int64		val1 = PG_GETARG_INT64(0);
	int32		val2 = PG_GETARG_INT32(1);
218

219 220
	PG_RETURN_BOOL(val1 <= val2);
}
221

222 223
Datum
int84ge(PG_FUNCTION_ARGS)
224
{
225 226
	int64		val1 = PG_GETARG_INT64(0);
	int32		val2 = PG_GETARG_INT32(1);
227

228 229
	PG_RETURN_BOOL(val1 >= val2);
}
230 231 232 233

/* int48relop()
 * Is 32-bit val1 relop 64-bit val2?
 */
234 235
Datum
int48eq(PG_FUNCTION_ARGS)
236
{
237 238
	int32		val1 = PG_GETARG_INT32(0);
	int64		val2 = PG_GETARG_INT64(1);
239

240 241
	PG_RETURN_BOOL(val1 == val2);
}
242

243 244
Datum
int48ne(PG_FUNCTION_ARGS)
245
{
246 247
	int32		val1 = PG_GETARG_INT32(0);
	int64		val2 = PG_GETARG_INT64(1);
248

249 250
	PG_RETURN_BOOL(val1 != val2);
}
251

252 253
Datum
int48lt(PG_FUNCTION_ARGS)
254
{
255 256
	int32		val1 = PG_GETARG_INT32(0);
	int64		val2 = PG_GETARG_INT64(1);
257

258 259
	PG_RETURN_BOOL(val1 < val2);
}
260

261 262
Datum
int48gt(PG_FUNCTION_ARGS)
263
{
264 265
	int32		val1 = PG_GETARG_INT32(0);
	int64		val2 = PG_GETARG_INT64(1);
266

267 268
	PG_RETURN_BOOL(val1 > val2);
}
269

270 271
Datum
int48le(PG_FUNCTION_ARGS)
272
{
273 274
	int32		val1 = PG_GETARG_INT32(0);
	int64		val2 = PG_GETARG_INT64(1);
275

276 277
	PG_RETURN_BOOL(val1 <= val2);
}
278

279 280
Datum
int48ge(PG_FUNCTION_ARGS)
281
{
282 283
	int32		val1 = PG_GETARG_INT32(0);
	int64		val2 = PG_GETARG_INT64(1);
284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397

	PG_RETURN_BOOL(val1 >= val2);
}

/* int82relop()
 * Is 64-bit val1 relop 16-bit val2?
 */
Datum
int82eq(PG_FUNCTION_ARGS)
{
	int64		val1 = PG_GETARG_INT64(0);
	int16		val2 = PG_GETARG_INT16(1);

	PG_RETURN_BOOL(val1 == val2);
}

Datum
int82ne(PG_FUNCTION_ARGS)
{
	int64		val1 = PG_GETARG_INT64(0);
	int16		val2 = PG_GETARG_INT16(1);

	PG_RETURN_BOOL(val1 != val2);
}

Datum
int82lt(PG_FUNCTION_ARGS)
{
	int64		val1 = PG_GETARG_INT64(0);
	int16		val2 = PG_GETARG_INT16(1);

	PG_RETURN_BOOL(val1 < val2);
}

Datum
int82gt(PG_FUNCTION_ARGS)
{
	int64		val1 = PG_GETARG_INT64(0);
	int16		val2 = PG_GETARG_INT16(1);

	PG_RETURN_BOOL(val1 > val2);
}

Datum
int82le(PG_FUNCTION_ARGS)
{
	int64		val1 = PG_GETARG_INT64(0);
	int16		val2 = PG_GETARG_INT16(1);

	PG_RETURN_BOOL(val1 <= val2);
}

Datum
int82ge(PG_FUNCTION_ARGS)
{
	int64		val1 = PG_GETARG_INT64(0);
	int16		val2 = PG_GETARG_INT16(1);

	PG_RETURN_BOOL(val1 >= val2);
}

/* int28relop()
 * Is 16-bit val1 relop 64-bit val2?
 */
Datum
int28eq(PG_FUNCTION_ARGS)
{
	int16		val1 = PG_GETARG_INT16(0);
	int64		val2 = PG_GETARG_INT64(1);

	PG_RETURN_BOOL(val1 == val2);
}

Datum
int28ne(PG_FUNCTION_ARGS)
{
	int16		val1 = PG_GETARG_INT16(0);
	int64		val2 = PG_GETARG_INT64(1);

	PG_RETURN_BOOL(val1 != val2);
}

Datum
int28lt(PG_FUNCTION_ARGS)
{
	int16		val1 = PG_GETARG_INT16(0);
	int64		val2 = PG_GETARG_INT64(1);

	PG_RETURN_BOOL(val1 < val2);
}

Datum
int28gt(PG_FUNCTION_ARGS)
{
	int16		val1 = PG_GETARG_INT16(0);
	int64		val2 = PG_GETARG_INT64(1);

	PG_RETURN_BOOL(val1 > val2);
}

Datum
int28le(PG_FUNCTION_ARGS)
{
	int16		val1 = PG_GETARG_INT16(0);
	int64		val2 = PG_GETARG_INT64(1);

	PG_RETURN_BOOL(val1 <= val2);
}

Datum
int28ge(PG_FUNCTION_ARGS)
{
	int16		val1 = PG_GETARG_INT16(0);
	int64		val2 = PG_GETARG_INT64(1);
398

399 400
	PG_RETURN_BOOL(val1 >= val2);
}
401 402 403 404 405 406


/*----------------------------------------------------------
 *	Arithmetic operators on 64-bit integers.
 *---------------------------------------------------------*/

407 408
Datum
int8um(PG_FUNCTION_ARGS)
409
{
410
	int64		val = PG_GETARG_INT64(0);
411

412
	PG_RETURN_INT64(-val);
413
}
414

415 416 417 418 419 420 421 422
Datum
int8up(PG_FUNCTION_ARGS)
{
	int64		val = PG_GETARG_INT64(0);

	PG_RETURN_INT64(val);
}

423 424
Datum
int8pl(PG_FUNCTION_ARGS)
425
{
426 427
	int64		val1 = PG_GETARG_INT64(0);
	int64		val2 = PG_GETARG_INT64(1);
428

429 430
	PG_RETURN_INT64(val1 + val2);
}
431

432 433
Datum
int8mi(PG_FUNCTION_ARGS)
434
{
435 436
	int64		val1 = PG_GETARG_INT64(0);
	int64		val2 = PG_GETARG_INT64(1);
437

438 439
	PG_RETURN_INT64(val1 - val2);
}
440

441 442
Datum
int8mul(PG_FUNCTION_ARGS)
443
{
444 445
	int64		val1 = PG_GETARG_INT64(0);
	int64		val2 = PG_GETARG_INT64(1);
446

447 448
	PG_RETURN_INT64(val1 * val2);
}
449

450 451
Datum
int8div(PG_FUNCTION_ARGS)
452
{
453 454
	int64		val1 = PG_GETARG_INT64(0);
	int64		val2 = PG_GETARG_INT64(1);
455

456 457
	PG_RETURN_INT64(val1 / val2);
}
458

459 460 461
/* int8abs()
 * Absolute value
 */
462 463
Datum
int8abs(PG_FUNCTION_ARGS)
464
{
465
	int64		arg1 = PG_GETARG_INT64(0);
466

467
	PG_RETURN_INT64((arg1 < 0) ? -arg1 : arg1);
468 469 470 471 472
}

/* int8mod()
 * Modulo operation.
 */
473 474
Datum
int8mod(PG_FUNCTION_ARGS)
475
{
476 477 478
	int64		val1 = PG_GETARG_INT64(0);
	int64		val2 = PG_GETARG_INT64(1);
	int64		result;
479

480 481 482
	result = val1 / val2;
	result *= val2;
	result = val1 - result;
483

484 485
	PG_RETURN_INT64(result);
}
486 487 488 489

/* int8fac()
 * Factorial
 */
490 491
Datum
int8fac(PG_FUNCTION_ARGS)
492
{
493 494
	int64		arg1 = PG_GETARG_INT64(0);
	int64		result;
495
	int64		i;
496

497 498
	if (arg1 < 1)
		result = 0;
499
	else
500 501
		for (i = arg1, result = 1; i > 0; --i)
			result *= i;
502

503
	PG_RETURN_INT64(result);
504 505
}

506 507 508 509 510 511 512 513
Datum
int8inc(PG_FUNCTION_ARGS)
{
	int64		arg = PG_GETARG_INT64(0);

	PG_RETURN_INT64(arg + 1);
}

514 515
Datum
int8larger(PG_FUNCTION_ARGS)
516
{
517 518 519
	int64		val1 = PG_GETARG_INT64(0);
	int64		val2 = PG_GETARG_INT64(1);
	int64		result;
520

521
	result = ((val1 > val2) ? val1 : val2);
522

523 524
	PG_RETURN_INT64(result);
}
525

526 527
Datum
int8smaller(PG_FUNCTION_ARGS)
528
{
529 530 531
	int64		val1 = PG_GETARG_INT64(0);
	int64		val2 = PG_GETARG_INT64(1);
	int64		result;
532

533
	result = ((val1 < val2) ? val1 : val2);
534

535 536
	PG_RETURN_INT64(result);
}
537

538 539
Datum
int84pl(PG_FUNCTION_ARGS)
540
{
541 542
	int64		val1 = PG_GETARG_INT64(0);
	int32		val2 = PG_GETARG_INT32(1);
543

544 545
	PG_RETURN_INT64(val1 + val2);
}
546

547 548
Datum
int84mi(PG_FUNCTION_ARGS)
549
{
550 551
	int64		val1 = PG_GETARG_INT64(0);
	int32		val2 = PG_GETARG_INT32(1);
552

553 554
	PG_RETURN_INT64(val1 - val2);
}
555

556 557
Datum
int84mul(PG_FUNCTION_ARGS)
558
{
559 560
	int64		val1 = PG_GETARG_INT64(0);
	int32		val2 = PG_GETARG_INT32(1);
561

562 563
	PG_RETURN_INT64(val1 * val2);
}
564

565 566
Datum
int84div(PG_FUNCTION_ARGS)
567
{
568 569
	int64		val1 = PG_GETARG_INT64(0);
	int32		val2 = PG_GETARG_INT32(1);
570

571 572
	PG_RETURN_INT64(val1 / val2);
}
573

574 575
Datum
int48pl(PG_FUNCTION_ARGS)
576
{
577 578
	int32		val1 = PG_GETARG_INT32(0);
	int64		val2 = PG_GETARG_INT64(1);
579

580 581
	PG_RETURN_INT64(val1 + val2);
}
582

583 584
Datum
int48mi(PG_FUNCTION_ARGS)
585
{
586 587
	int32		val1 = PG_GETARG_INT32(0);
	int64		val2 = PG_GETARG_INT64(1);
588

589 590
	PG_RETURN_INT64(val1 - val2);
}
591

592 593
Datum
int48mul(PG_FUNCTION_ARGS)
594
{
595 596
	int32		val1 = PG_GETARG_INT32(0);
	int64		val2 = PG_GETARG_INT64(1);
597

598 599
	PG_RETURN_INT64(val1 * val2);
}
600

601 602
Datum
int48div(PG_FUNCTION_ARGS)
603
{
604 605
	int32		val1 = PG_GETARG_INT32(0);
	int64		val2 = PG_GETARG_INT64(1);
606

607 608
	PG_RETURN_INT64(val1 / val2);
}
609

610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671
/* Binary arithmetics
 *
 *		int8and		- returns arg1 & arg2
 *		int8or		- returns arg1 | arg2
 *		int8xor		- returns arg1 # arg2
 *		int8not		- returns ~arg1
 *		int8shl		- returns arg1 << arg2
 *		int8shr		- returns arg1 >> arg2
 */

Datum
int8and(PG_FUNCTION_ARGS)
{
	int64		arg1 = PG_GETARG_INT64(0);
	int64		arg2 = PG_GETARG_INT64(1);

	PG_RETURN_INT64(arg1 & arg2);
}

Datum
int8or(PG_FUNCTION_ARGS)
{
	int64		arg1 = PG_GETARG_INT64(0);
	int64		arg2 = PG_GETARG_INT64(1);

	PG_RETURN_INT64(arg1 | arg2);
}

Datum
int8xor(PG_FUNCTION_ARGS)
{
	int64		arg1 = PG_GETARG_INT64(0);
	int64		arg2 = PG_GETARG_INT64(1);

	PG_RETURN_INT64(arg1 ^ arg2);
}

Datum
int8not(PG_FUNCTION_ARGS)
{
	int64		arg1 = PG_GETARG_INT64(0);

	PG_RETURN_INT64(~arg1);
}

Datum
int8shl(PG_FUNCTION_ARGS)
{
	int64		arg1 = PG_GETARG_INT64(0);
	int32		arg2 = PG_GETARG_INT32(1);

	PG_RETURN_INT64(arg1 << arg2);
}

Datum
int8shr(PG_FUNCTION_ARGS)
{
	int64		arg1 = PG_GETARG_INT64(0);
	int32		arg2 = PG_GETARG_INT32(1);

	PG_RETURN_INT64(arg1 >> arg2);
}
672 673 674 675 676

/*----------------------------------------------------------
 *	Conversion operators.
 *---------------------------------------------------------*/

677 678
Datum
int48(PG_FUNCTION_ARGS)
679
{
680
	int32		val = PG_GETARG_INT32(0);
681

682 683
	PG_RETURN_INT64((int64) val);
}
684

685 686
Datum
int84(PG_FUNCTION_ARGS)
687
{
688
	int64		val = PG_GETARG_INT64(0);
689 690
	int32		result;

691
	result = (int32) val;
692

693 694 695 696
	/* Test for overflow by reverse-conversion. */
	if ((int64) result != val)
		elog(ERROR, "int8 conversion to int4 is out of range");

697 698
	PG_RETURN_INT32(result);
}
699

700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722
Datum
int28(PG_FUNCTION_ARGS)
{
	int16		val = PG_GETARG_INT16(0);

	PG_RETURN_INT64((int64) val);
}

Datum
int82(PG_FUNCTION_ARGS)
{
	int64		val = PG_GETARG_INT64(0);
	int16		result;

	result = (int16) val;

	/* Test for overflow by reverse-conversion. */
	if ((int64) result != val)
		elog(ERROR, "int8 conversion to int2 is out of range");

	PG_RETURN_INT16(result);
}

723 724
Datum
i8tod(PG_FUNCTION_ARGS)
725
{
726 727
	int64		val = PG_GETARG_INT64(0);
	float8		result;
728

729
	result = val;
730

731 732
	PG_RETURN_FLOAT8(result);
}
733 734 735 736

/* dtoi8()
 * Convert double float to 8-byte integer.
 */
737 738
Datum
dtoi8(PG_FUNCTION_ARGS)
739
{
740 741
	float8		val = PG_GETARG_FLOAT8(0);
	int64		result;
742

743 744
	/* Round val to nearest integer (but it's still in float form) */
	val = rint(val);
745

746
	/*
747 748 749
	 * Does it fit in an int64?  Avoid assuming that we have handy
	 * constants defined for the range boundaries, instead test for
	 * overflow by reverse-conversion.
750
	 */
751
	result = (int64) val;
752

753 754 755
	if ((float8) result != val)
		elog(ERROR, "Floating point conversion to int8 is out of range");

756 757
	PG_RETURN_INT64(result);
}
758 759 760

/* text_int8()
 */
761 762
Datum
text_int8(PG_FUNCTION_ARGS)
763
{
764
	text	   *str = PG_GETARG_TEXT_P(0);
765 766
	int			len;
	char	   *s;
767
	Datum		result;
768 769

	len = (VARSIZE(str) - VARHDRSZ);
Bruce Momjian's avatar
Bruce Momjian committed
770
	s = palloc(len + 1);
771
	memcpy(s, VARDATA(str), len);
Bruce Momjian's avatar
Bruce Momjian committed
772
	*(s + len) = '\0';
773

774 775 776 777 778 779
	result = DirectFunctionCall1(int8in, CStringGetDatum(s));

	pfree(s);

	return result;
}
780 781 782 783


/* int8_text()
 */
784 785
Datum
int8_text(PG_FUNCTION_ARGS)
786
{
787 788
	/* val is int64, but easier to leave it as Datum */
	Datum		val = PG_GETARG_DATUM(0);
789
	char	   *s;
790 791
	int			len;
	text	   *result;
792

793
	s = DatumGetCString(DirectFunctionCall1(int8out, val));
794 795
	len = strlen(s);

796
	result = (text *) palloc(VARHDRSZ + len);
797

Jan Wieck's avatar
TOAST  
Jan Wieck committed
798
	VARATT_SIZEP(result) = len + VARHDRSZ;
799
	memcpy(VARDATA(result), s, len);
800

801 802 803 804
	pfree(s);

	PG_RETURN_TEXT_P(result);
}