Skip to content
Snippets Groups Projects
int.c 16.3 KiB
Newer Older
/*-------------------------------------------------------------------------
 *
 *	  Functions for the built-in integer types (except int8).
Bruce Momjian's avatar
Bruce Momjian committed
 * Portions Copyright (c) 1996-2000, PostgreSQL, Inc
 * Portions Copyright (c) 1994, Regents of the University of California
 *	  $Header: /cvsroot/pgsql/src/backend/utils/adt/int.c,v 1.43 2000/10/24 20:14:35 petere Exp $
 *
 *-------------------------------------------------------------------------
 */
/*
 * OLD COMMENTS
 *		 int2in, int2out, int2vectorin, int2vectorout, int4in, int4out
 *		 itoi, int2_text, int4_text
 *		Boolean operators:
 *		 inteq, intne, intlt, intle, intgt, intge
 *		Arithmetic operators:
 *		 intpl, intmi, int4mul, intdiv
 *		Arithmetic operators:
 *		 intmod, int4fac
Bruce Momjian's avatar
Bruce Momjian committed

#include "postgres.h"
Bruce Momjian's avatar
Bruce Momjian committed
#include "utils/builtins.h"
#ifndef SHRT_MAX
#define SHRT_MAX (0x7FFF)
#endif
#ifndef SHRT_MIN
#define SHRT_MIN (-0x8000)
#endif

/*****************************************************************************
 *	 USER I/O ROUTINES														 *
 *****************************************************************************/

/*
 *		int2in			- converts "num" to short
	char	   *num = PG_GETARG_CSTRING(0);

	PG_RETURN_INT16(pg_atoi(num, sizeof(int16), '\0'));
 *		int2out			- converts short to "num"
Datum
int2out(PG_FUNCTION_ARGS)
	int16		arg1 = PG_GETARG_INT16(0);
	char	   *result = (char *) palloc(7); /* sign, 5 digits, '\0' */
 *		int2vectorin			- converts "num num ..." to internal form
 *		Note: Fills any missing slots with zeroes.
Datum
int2vectorin(PG_FUNCTION_ARGS)
	char	   *intString = PG_GETARG_CSTRING(0);
	int16	   *result = (int16 *) palloc(sizeof(int16[INDEX_MAX_KEYS]));
	int			slot;
	for (slot = 0; *intString && slot < INDEX_MAX_KEYS; slot++)
		if (sscanf(intString, "%hd", &result[slot]) != 1)
			break;
		while (*intString && isspace((int) *intString))
		while (*intString && !isspace((int) *intString))
			intString++;
	while (*intString && isspace((int) *intString))
		elog(ERROR, "int2vector value has too many values");
	while (slot < INDEX_MAX_KEYS)
		result[slot++] = 0;

 *		int2vectorout		- converts internal form to "num num ..."
Datum
int2vectorout(PG_FUNCTION_ARGS)
	int16	   *int2Array = (int16 *) PG_GETARG_POINTER(0);
	/* find last non-zero value in vector */
	for (maxnum = INDEX_MAX_KEYS - 1; maxnum >= 0; maxnum--)
		if (int2Array[maxnum] != 0)
			break;

	/* assumes sign, 5 digits, ' ' */
	rp = result = (char *) palloc((maxnum + 1) * 7 + 1);
	for (num = 0; num <= maxnum; num++)
/*
 * We don't have a complete set of int2vector support routines,
 * but we need int2vectoreq for catcache indexing.
 */
Datum
int2vectoreq(PG_FUNCTION_ARGS)
	int16	   *arg1 = (int16 *) PG_GETARG_POINTER(0);
	int16	   *arg2 = (int16 *) PG_GETARG_POINTER(1);

	PG_RETURN_BOOL(memcmp(arg1, arg2, INDEX_MAX_KEYS * sizeof(int16)) == 0);
/*
 * Type int44 has no real-world use, but the regression tests use it.
 * It's a four-element vector of int4's.
 */
 *		int44in			- converts "num num ..." to internal form
 *		Note: Fills any missing positions with zeroes.
	char	   *input_string = PG_GETARG_CSTRING(0);
	int32	   *result = (int32 *) palloc(4 * sizeof(int32));
	int			i;

	i = sscanf(input_string,
			   "%d, %d, %d, %d",
			   &result[0],
			   &result[1],
			   &result[2],
			   &result[3]);
 *		int44out		- converts internal form to "num num ..."
Datum
int44out(PG_FUNCTION_ARGS)
	int32	   *an_array = (int32 *) PG_GETARG_POINTER(0);
	char	   *result = (char *) palloc(16 * 4); /* Allow 14 digits + sign */
	walk = result;
	for (i = 0; i < 4; i++)
		while (*++walk != '\0')
			;
		*walk++ = ' ';
	*--walk = '\0';
	PG_RETURN_CSTRING(result);
/*****************************************************************************
 *	 PUBLIC ROUTINES														 *
 *****************************************************************************/

/*
 *		int4in			- converts "num" to int4
	char	   *num = PG_GETARG_CSTRING(0);

	PG_RETURN_INT32(pg_atoi(num, sizeof(int32), '\0'));
 *		int4out			- converts int4 to "num"
	int32		arg1 = PG_GETARG_INT32(0);
	char	   *result = (char *) palloc(12); /* sign, 10 digits, '\0' */
 *		===================
 *		CONVERSION ROUTINES
 *		===================
	int16		arg1 = PG_GETARG_INT16(0);

	PG_RETURN_INT32((int32) arg1);
	int32		arg1 = PG_GETARG_INT32(0);

		elog(ERROR, "i4toi2: '%d' causes int2 underflow", arg1);
		elog(ERROR, "i4toi2: '%d' causes int2 overflow", arg1);
	PG_RETURN_INT16((int16) arg1);
Datum
int2_text(PG_FUNCTION_ARGS)
	int16		arg1 = PG_GETARG_INT16(0);
	text	   *result = (text *) palloc(7+VARHDRSZ); /* sign,5 digits, '\0' */
	pg_itoa(arg1, VARDATA(result));
Jan Wieck's avatar
Jan Wieck committed
	VARATT_SIZEP(result) = strlen(VARDATA(result)) + VARHDRSZ;
Datum
text_int2(PG_FUNCTION_ARGS)
	text	   *string = PG_GETARG_TEXT_P(0);
	Datum		result;
	len = VARSIZE(string) - VARHDRSZ;
	memcpy(str, VARDATA(string), len);
	result = DirectFunctionCall1(int2in, CStringGetDatum(str));
	return result;
Datum
int4_text(PG_FUNCTION_ARGS)
	int32		arg1 = PG_GETARG_INT32(0);
	text	   *result = (text *) palloc(12+VARHDRSZ); /* sign,10 digits,'\0' */
	pg_ltoa(arg1, VARDATA(result));
Jan Wieck's avatar
Jan Wieck committed
	VARATT_SIZEP(result) = strlen(VARDATA(result)) + VARHDRSZ;
Datum
text_int4(PG_FUNCTION_ARGS)
	text	   *string = PG_GETARG_TEXT_P(0);
	Datum		result;
	len = VARSIZE(string) - VARHDRSZ;
	memcpy(str, VARDATA(string), len);
	result = DirectFunctionCall1(int4in, CStringGetDatum(str));
	return result;
 *		============================
 *		COMPARISON OPERATOR ROUTINES
 *		============================
 *		inteq			- returns 1 iff arg1 == arg2
 *		intne			- returns 1 iff arg1 != arg2
 *		intlt			- returns 1 iff arg1 < arg2
 *		intle			- returns 1 iff arg1 <= arg2
 *		intgt			- returns 1 iff arg1 > arg2
 *		intge			- returns 1 iff arg1 >= arg2
	int32		arg1 = PG_GETARG_INT32(0);
	int32		arg2 = PG_GETARG_INT32(1);

	PG_RETURN_BOOL(arg1 == arg2);
	int32		arg1 = PG_GETARG_INT32(0);
	int32		arg2 = PG_GETARG_INT32(1);

	PG_RETURN_BOOL(arg1 != arg2);
	int32		arg1 = PG_GETARG_INT32(0);
	int32		arg2 = PG_GETARG_INT32(1);

	PG_RETURN_BOOL(arg1 < arg2);
	int32		arg1 = PG_GETARG_INT32(0);
	int32		arg2 = PG_GETARG_INT32(1);

	PG_RETURN_BOOL(arg1 <= arg2);
	int32		arg1 = PG_GETARG_INT32(0);
	int32		arg2 = PG_GETARG_INT32(1);

	PG_RETURN_BOOL(arg1 > arg2);
	int32		arg1 = PG_GETARG_INT32(0);
	int32		arg2 = PG_GETARG_INT32(1);

	PG_RETURN_BOOL(arg1 >= arg2);
	int16		arg1 = PG_GETARG_INT16(0);
	int16		arg2 = PG_GETARG_INT16(1);

	PG_RETURN_BOOL(arg1 == arg2);
	int16		arg1 = PG_GETARG_INT16(0);
	int16		arg2 = PG_GETARG_INT16(1);

	PG_RETURN_BOOL(arg1 != arg2);
	int16		arg1 = PG_GETARG_INT16(0);
	int16		arg2 = PG_GETARG_INT16(1);

	PG_RETURN_BOOL(arg1 < arg2);
	int16		arg1 = PG_GETARG_INT16(0);
	int16		arg2 = PG_GETARG_INT16(1);

	PG_RETURN_BOOL(arg1 <= arg2);
	int16		arg1 = PG_GETARG_INT16(0);
	int16		arg2 = PG_GETARG_INT16(1);

	PG_RETURN_BOOL(arg1 > arg2);
	int16		arg1 = PG_GETARG_INT16(0);
	int16		arg2 = PG_GETARG_INT16(1);

	PG_RETURN_BOOL(arg1 >= arg2);
	int16		arg1 = PG_GETARG_INT16(0);
	int32		arg2 = PG_GETARG_INT32(1);

	PG_RETURN_BOOL(arg1 == arg2);
	int16		arg1 = PG_GETARG_INT16(0);
	int32		arg2 = PG_GETARG_INT32(1);

	PG_RETURN_BOOL(arg1 != arg2);
	int16		arg1 = PG_GETARG_INT16(0);
	int32		arg2 = PG_GETARG_INT32(1);

	PG_RETURN_BOOL(arg1 < arg2);
	int16		arg1 = PG_GETARG_INT16(0);
	int32		arg2 = PG_GETARG_INT32(1);

	PG_RETURN_BOOL(arg1 <= arg2);
	int16		arg1 = PG_GETARG_INT16(0);
	int32		arg2 = PG_GETARG_INT32(1);

	PG_RETURN_BOOL(arg1 > arg2);
	int16		arg1 = PG_GETARG_INT16(0);
	int32		arg2 = PG_GETARG_INT32(1);

	PG_RETURN_BOOL(arg1 >= arg2);
	int32		arg1 = PG_GETARG_INT32(0);
	int16		arg2 = PG_GETARG_INT16(1);

	PG_RETURN_BOOL(arg1 == arg2);
	int32		arg1 = PG_GETARG_INT32(0);
	int16		arg2 = PG_GETARG_INT16(1);

	PG_RETURN_BOOL(arg1 != arg2);
	int32		arg1 = PG_GETARG_INT32(0);
	int16		arg2 = PG_GETARG_INT16(1);

	PG_RETURN_BOOL(arg1 < arg2);
	int32		arg1 = PG_GETARG_INT32(0);
	int16		arg2 = PG_GETARG_INT16(1);

	PG_RETURN_BOOL(arg1 <= arg2);
	int32		arg1 = PG_GETARG_INT32(0);
	int16		arg2 = PG_GETARG_INT16(1);

	PG_RETURN_BOOL(arg1 > arg2);
	int32		arg1 = PG_GETARG_INT32(0);
	int16		arg2 = PG_GETARG_INT16(1);

	PG_RETURN_BOOL(arg1 >= arg2);
 *		int[24]pl		- returns arg1 + arg2
 *		int[24]mi		- returns arg1 - arg2
 *		int[24]mul		- returns arg1 * arg2
 *		int[24]div		- returns arg1 / arg2
	int32		arg = PG_GETARG_INT32(0);

	PG_RETURN_INT32(-arg);
	int32		arg1 = PG_GETARG_INT32(0);
	int32		arg2 = PG_GETARG_INT32(1);

	PG_RETURN_INT32(arg1 + arg2);
	int32		arg1 = PG_GETARG_INT32(0);
	int32		arg2 = PG_GETARG_INT32(1);

	PG_RETURN_INT32(arg1 - arg2);
	int32		arg1 = PG_GETARG_INT32(0);
	int32		arg2 = PG_GETARG_INT32(1);

	PG_RETURN_INT32(arg1 * arg2);
	int32		arg1 = PG_GETARG_INT32(0);
	int32		arg2 = PG_GETARG_INT32(1);

	PG_RETURN_INT32(arg1 / arg2);
	int32		arg = PG_GETARG_INT32(0);

	PG_RETURN_INT32(arg + 1);
	int16		arg = PG_GETARG_INT16(0);

	PG_RETURN_INT16(-arg);
	int16		arg1 = PG_GETARG_INT16(0);
	int16		arg2 = PG_GETARG_INT16(1);

	PG_RETURN_INT16(arg1 + arg2);
	int16		arg1 = PG_GETARG_INT16(0);
	int16		arg2 = PG_GETARG_INT16(1);

	PG_RETURN_INT16(arg1 - arg2);
	int16		arg1 = PG_GETARG_INT16(0);
	int16		arg2 = PG_GETARG_INT16(1);

	PG_RETURN_INT16(arg1 * arg2);
	int16		arg1 = PG_GETARG_INT16(0);
	int16		arg2 = PG_GETARG_INT16(1);

	PG_RETURN_INT16(arg1 / arg2);
	int16		arg1 = PG_GETARG_INT16(0);
	int32		arg2 = PG_GETARG_INT32(1);

	PG_RETURN_INT32(arg1 + arg2);
	int16		arg1 = PG_GETARG_INT16(0);
	int32		arg2 = PG_GETARG_INT32(1);

	PG_RETURN_INT32(arg1 - arg2);
Datum
int24mul(PG_FUNCTION_ARGS)
	int16		arg1 = PG_GETARG_INT16(0);
	int32		arg2 = PG_GETARG_INT32(1);

	PG_RETURN_INT32(arg1 * arg2);
Datum
int24div(PG_FUNCTION_ARGS)
	int16		arg1 = PG_GETARG_INT16(0);
	int32		arg2 = PG_GETARG_INT32(1);

	PG_RETURN_INT32(arg1 / arg2);
	int32		arg1 = PG_GETARG_INT32(0);
	int16		arg2 = PG_GETARG_INT16(1);

	PG_RETURN_INT32(arg1 + arg2);
	int32		arg1 = PG_GETARG_INT32(0);
	int16		arg2 = PG_GETARG_INT16(1);

	PG_RETURN_INT32(arg1 - arg2);
Datum
int42mul(PG_FUNCTION_ARGS)
	int32		arg1 = PG_GETARG_INT32(0);
	int16		arg2 = PG_GETARG_INT16(1);

	PG_RETURN_INT32(arg1 * arg2);
Datum
int42div(PG_FUNCTION_ARGS)
	int32		arg1 = PG_GETARG_INT32(0);
	int16		arg2 = PG_GETARG_INT16(1);

	PG_RETURN_INT32(arg1 / arg2);
	int32		arg1 = PG_GETARG_INT32(0);
	int32		arg2 = PG_GETARG_INT32(1);

	PG_RETURN_INT32(arg1 % arg2);
	int16		arg1 = PG_GETARG_INT16(0);
	int16		arg2 = PG_GETARG_INT16(1);

	PG_RETURN_INT16(arg1 % arg2);
Datum
int24mod(PG_FUNCTION_ARGS)
	int16		arg1 = PG_GETARG_INT16(0);
	int32		arg2 = PG_GETARG_INT32(1);

	PG_RETURN_INT32(arg1 % arg2);
Datum
int42mod(PG_FUNCTION_ARGS)
	int32		arg1 = PG_GETARG_INT32(0);
	int16		arg2 = PG_GETARG_INT16(1);

	PG_RETURN_INT32(arg1 % arg2);
	int32		arg1 = PG_GETARG_INT32(0);

	if (arg1 < 1)
		result = 0;
	else
		for (result = 1; arg1 > 0; --arg1)
			result *= arg1;
	int16		arg1 = PG_GETARG_INT16(0);

	if (arg1 < 1)
		result = 0;
	else
		for (result = 1; arg1 > 0; --arg1)
			result *= arg1;
	int32		arg1 = PG_GETARG_INT32(0);

	PG_RETURN_INT32((arg1 < 0) ? -arg1 : arg1);
	int16		arg1 = PG_GETARG_INT16(0);

	PG_RETURN_INT16((arg1 < 0) ? -arg1 : arg1);
Datum
int2larger(PG_FUNCTION_ARGS)
	int16		arg1 = PG_GETARG_INT16(0);
	int16		arg2 = PG_GETARG_INT16(1);

	PG_RETURN_INT16((arg1 > arg2) ? arg1 : arg2);
Datum
int2smaller(PG_FUNCTION_ARGS)
	int16		arg1 = PG_GETARG_INT16(0);
	int16		arg2 = PG_GETARG_INT16(1);

	PG_RETURN_INT16((arg1 < arg2) ? arg1 : arg2);
Datum
int4larger(PG_FUNCTION_ARGS)
	int32		arg1 = PG_GETARG_INT32(0);
	int32		arg2 = PG_GETARG_INT32(1);

	PG_RETURN_INT32((arg1 > arg2) ? arg1 : arg2);
Datum
int4smaller(PG_FUNCTION_ARGS)
	int32		arg1 = PG_GETARG_INT32(0);
	int32		arg2 = PG_GETARG_INT32(1);

	PG_RETURN_INT32((arg1 < arg2) ? arg1 : arg2);

/* Binary arithmetics
 *
 *		int[24]and		- returns arg1 & arg2
 *		int[24]or		- returns arg1 | arg2
 *		int[24]xor		- returns arg1 # arg2
 *		int[24]not		- returns ~arg1
 *		int[24]shl		- returns arg1 << arg2
 *		int[24]shr		- returns arg1 >> arg2
 */

Datum
int4and(PG_FUNCTION_ARGS)
{
	int32		arg1 = PG_GETARG_INT32(0);
	int32		arg2 = PG_GETARG_INT32(1);

	PG_RETURN_INT32(arg1 & arg2);
}

Datum
int4or(PG_FUNCTION_ARGS)
{
	int32		arg1 = PG_GETARG_INT32(0);
	int32		arg2 = PG_GETARG_INT32(1);

	PG_RETURN_INT32(arg1 | arg2);
}

Datum
int4xor(PG_FUNCTION_ARGS)
{
	int32		arg1 = PG_GETARG_INT32(0);
	int32		arg2 = PG_GETARG_INT32(1);

	PG_RETURN_INT32(arg1 ^ arg2);
}

Datum
int4shl(PG_FUNCTION_ARGS)
{
	int32		arg1 = PG_GETARG_INT32(0);
	int32		arg2 = PG_GETARG_INT32(1);

	PG_RETURN_INT32(arg1 << arg2);
}

Datum
int4shr(PG_FUNCTION_ARGS)
{
	int32		arg1 = PG_GETARG_INT32(0);
	int32		arg2 = PG_GETARG_INT32(1);

	PG_RETURN_INT32(arg1 >> arg2);
}

Datum
int4not(PG_FUNCTION_ARGS)
{
	int32		arg1 = PG_GETARG_INT32(0);

	PG_RETURN_INT32(~arg1);
}

Datum
int2and(PG_FUNCTION_ARGS)
{
	int16		arg1 = PG_GETARG_INT16(0);
	int16		arg2 = PG_GETARG_INT16(1);

	PG_RETURN_INT16(arg1 & arg2);
}

Datum
int2or(PG_FUNCTION_ARGS)
{
	int16		arg1 = PG_GETARG_INT16(0);
	int16		arg2 = PG_GETARG_INT16(1);

	PG_RETURN_INT16(arg1 | arg2);
}

Datum
int2xor(PG_FUNCTION_ARGS)
{
	int16		arg1 = PG_GETARG_INT16(0);
	int16		arg2 = PG_GETARG_INT16(1);

	PG_RETURN_INT16(arg1 ^ arg2);
}

Datum
int2not(PG_FUNCTION_ARGS)
{
	int16		arg1 = PG_GETARG_INT16(0);

	PG_RETURN_INT16(~arg1);
}


Datum
int2shl(PG_FUNCTION_ARGS)
{
	int16		arg1 = PG_GETARG_INT16(0);
	int32		arg2 = PG_GETARG_INT32(1);

	PG_RETURN_INT16(arg1 << arg2);
}

Datum
int2shr(PG_FUNCTION_ARGS)
{
	int16		arg1 = PG_GETARG_INT16(0);
	int32		arg2 = PG_GETARG_INT32(1);

	PG_RETURN_INT16(arg1 >> arg2);
}