postgresql/src/backend/utils/adt/int8.c
Tom Lane 0a7fb4e918 First round of changes for new fmgr interface. fmgr itself and the
key call sites are changed, but most called functions are still oldstyle.
An exception is that the PL managers are updated (so, for example, NULL
handling now behaves as expected in plperl and plpgsql functions).
NOTE initdb is forced due to added column in pg_proc.
2000-05-28 17:56:29 +00:00

706 lines
12 KiB
C

/*-------------------------------------------------------------------------
*
* int8.c
* Internal 64-bit integer operations
*
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/utils/adt/int8.c,v 1.19 2000/05/28 17:56:05 tgl Exp $
*
*-------------------------------------------------------------------------
*/
#include <ctype.h>
#include <time.h>
#include <math.h>
#include <float.h>
#include "postgres.h"
#ifdef HAVE_LIMITS_H
#include <limits.h>
#endif
#include "utils/int8.h"
/* this should be set in config.h, but just in case it wasn't: */
#ifndef INT64_FORMAT
#define INT64_FORMAT "%ld"
#endif
#define MAXINT8LEN 25
#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
/***********************************************************************
**
** Routines for 64-bit integers.
**
***********************************************************************/
/*----------------------------------------------------------
* Formatting and conversion routines.
*---------------------------------------------------------*/
/* int8in()
*/
int64 *
int8in(char *str)
{
int64 *result = palloc(sizeof(int64));
char *ptr = str;
int64 tmp = 0;
int sign = 1;
if (!PointerIsValid(str))
elog(ERROR, "Bad (null) int8 external representation");
/*
* Do our own scan, rather than relying on sscanf which might be
* broken for long long.
*/
while (*ptr && isspace(*ptr)) /* skip leading spaces */
ptr++;
if (*ptr == '-') /* handle sign */
sign = -1, ptr++;
else if (*ptr == '+')
ptr++;
if (!isdigit(*ptr)) /* require at least one digit */
elog(ERROR, "Bad int8 external representation \"%s\"", str);
while (*ptr && isdigit(*ptr)) /* process digits */
{
int64 newtmp = tmp * 10 + (*ptr++ - '0');
if ((newtmp / 10) != tmp) /* overflow? */
elog(ERROR, "int8 value out of range: \"%s\"", str);
tmp = newtmp;
}
if (*ptr) /* trailing junk? */
elog(ERROR, "Bad int8 external representation \"%s\"", str);
*result = (sign < 0) ? -tmp : tmp;
return result;
} /* int8in() */
/* int8out()
*/
char *
int8out(int64 *val)
{
char *result;
int len;
char buf[MAXINT8LEN + 1];
if (!PointerIsValid(val))
return NULL;
if ((len = snprintf(buf, MAXINT8LEN, INT64_FORMAT, *val)) < 0)
elog(ERROR, "Unable to format int8");
result = palloc(len + 1);
strcpy(result, buf);
return result;
} /* int8out() */
/*----------------------------------------------------------
* Relational operators for int8s.
*---------------------------------------------------------*/
/* int8relop()
* Is val1 relop val2?
*/
bool
int8eq(int64 *val1, int64 *val2)
{
if (!val1 || !val2)
return 0;
return *val1 == *val2;
} /* int8eq() */
bool
int8ne(int64 *val1, int64 *val2)
{
if (!val1 || !val2)
return 0;
return *val1 != *val2;
} /* int8ne() */
bool
int8lt(int64 *val1, int64 *val2)
{
if (!val1 || !val2)
return 0;
return *val1 < *val2;
} /* int8lt() */
bool
int8gt(int64 *val1, int64 *val2)
{
if (!val1 || !val2)
return 0;
return *val1 > *val2;
} /* int8gt() */
bool
int8le(int64 *val1, int64 *val2)
{
if (!val1 || !val2)
return 0;
return *val1 <= *val2;
} /* int8le() */
bool
int8ge(int64 *val1, int64 *val2)
{
if (!val1 || !val2)
return 0;
return *val1 >= *val2;
} /* int8ge() */
/* int84relop()
* Is 64-bit val1 relop 32-bit val2?
*/
bool
int84eq(int64 *val1, int32 val2)
{
if (!val1)
return 0;
return *val1 == val2;
} /* int84eq() */
bool
int84ne(int64 *val1, int32 val2)
{
if (!val1)
return 0;
return *val1 != val2;
} /* int84ne() */
bool
int84lt(int64 *val1, int32 val2)
{
if (!val1)
return 0;
return *val1 < val2;
} /* int84lt() */
bool
int84gt(int64 *val1, int32 val2)
{
if (!val1)
return 0;
return *val1 > val2;
} /* int84gt() */
bool
int84le(int64 *val1, int32 val2)
{
if (!val1)
return 0;
return *val1 <= val2;
} /* int84le() */
bool
int84ge(int64 *val1, int32 val2)
{
if (!val1)
return 0;
return *val1 >= val2;
} /* int84ge() */
/* int48relop()
* Is 32-bit val1 relop 64-bit val2?
*/
bool
int48eq(int32 val1, int64 *val2)
{
if (!val2)
return 0;
return val1 == *val2;
} /* int48eq() */
bool
int48ne(int32 val1, int64 *val2)
{
if (!val2)
return 0;
return val1 != *val2;
} /* int48ne() */
bool
int48lt(int32 val1, int64 *val2)
{
if (!val2)
return 0;
return val1 < *val2;
} /* int48lt() */
bool
int48gt(int32 val1, int64 *val2)
{
if (!val2)
return 0;
return val1 > *val2;
} /* int48gt() */
bool
int48le(int32 val1, int64 *val2)
{
if (!val2)
return 0;
return val1 <= *val2;
} /* int48le() */
bool
int48ge(int32 val1, int64 *val2)
{
if (!val2)
return 0;
return val1 >= *val2;
} /* int48ge() */
/*----------------------------------------------------------
* Arithmetic operators on 64-bit integers.
*---------------------------------------------------------*/
int64 *
int8um(int64 *val)
{
int64 temp = 0;
int64 *result = palloc(sizeof(int64));
if (!PointerIsValid(val))
return NULL;
result = int8mi(&temp, val);
return result;
} /* int8um() */
int64 *
int8pl(int64 *val1, int64 *val2)
{
int64 *result = palloc(sizeof(int64));
if ((!PointerIsValid(val1)) || (!PointerIsValid(val2)))
return NULL;
*result = *val1 + *val2;
return result;
} /* int8pl() */
int64 *
int8mi(int64 *val1, int64 *val2)
{
int64 *result = palloc(sizeof(int64));
if ((!PointerIsValid(val1)) || (!PointerIsValid(val2)))
return NULL;
*result = *val1 - *val2;
return result;
} /* int8mi() */
int64 *
int8mul(int64 *val1, int64 *val2)
{
int64 *result = palloc(sizeof(int64));
if ((!PointerIsValid(val1)) || (!PointerIsValid(val2)))
return NULL;
*result = *val1 * *val2;
return result;
} /* int8mul() */
int64 *
int8div(int64 *val1, int64 *val2)
{
int64 *result = palloc(sizeof(int64));
if ((!PointerIsValid(val1)) || (!PointerIsValid(val2)))
return NULL;
*result = *val1 / *val2;
return result;
} /* int8div() */
/* int8abs()
* Absolute value
*/
int64 *
int8abs(int64 *arg1)
{
int64 *result;
if (!PointerIsValid(arg1))
return NULL;
result = palloc(sizeof(*result));
*result = ((*arg1 < 0) ? -*arg1 : *arg1);
return result;
}
/* int8mod()
* Modulo operation.
*/
int64 *
int8mod(int64 *val1, int64 *val2)
{
int64 *result;
/* use the divide operation to check params and allocate storage */
result = int8div(val1, val2);
*result *= *val2;
*result = *val1 - *result;
return result;
} /* int8mod() */
/* int8fac()
* Factorial
*/
int64 *
int8fac(int64 *arg1)
{
int64 *result;
int64 i;
if (!PointerIsValid(arg1))
return NULL;
result = palloc(sizeof(*result));
if (*arg1 < 1)
*result = 0;
else
for (i = *arg1, *result = 1; i > 0; --i)
*result *= i;
return result;
}
int64 *
int8larger(int64 *val1, int64 *val2)
{
int64 *result = palloc(sizeof(int64));
if ((!PointerIsValid(val1)) || (!PointerIsValid(val2)))
return NULL;
*result = ((*val1 > *val2) ? *val1 : *val2);
return result;
} /* int8larger() */
int64 *
int8smaller(int64 *val1, int64 *val2)
{
int64 *result = palloc(sizeof(int64));
if ((!PointerIsValid(val1)) || (!PointerIsValid(val2)))
return NULL;
*result = ((*val1 < *val2) ? *val1 : *val2);
return result;
} /* int8smaller() */
int64 *
int84pl(int64 *val1, int32 val2)
{
int64 *result = palloc(sizeof(int64));
if (!PointerIsValid(val1))
return NULL;
*result = *val1 + (int64) val2;
return result;
} /* int84pl() */
int64 *
int84mi(int64 *val1, int32 val2)
{
int64 *result = palloc(sizeof(int64));
if (!PointerIsValid(val1))
return NULL;
*result = *val1 - (int64) val2;
return result;
} /* int84mi() */
int64 *
int84mul(int64 *val1, int32 val2)
{
int64 *result = palloc(sizeof(int64));
if (!PointerIsValid(val1))
return NULL;
*result = *val1 * (int64) val2;
return result;
} /* int84mul() */
int64 *
int84div(int64 *val1, int32 val2)
{
int64 *result = palloc(sizeof(int64));
if (!PointerIsValid(val1))
return NULL;
*result = *val1 / (int64) val2;
return result;
} /* int84div() */
int64 *
int48pl(int32 val1, int64 *val2)
{
int64 *result = palloc(sizeof(int64));
if (!PointerIsValid(val2))
return NULL;
*result = (int64) val1 + *val2;
return result;
} /* int48pl() */
int64 *
int48mi(int32 val1, int64 *val2)
{
int64 *result = palloc(sizeof(int64));
if (!PointerIsValid(val2))
return NULL;
*result = (int64) val1 - *val2;
return result;
} /* int48mi() */
int64 *
int48mul(int32 val1, int64 *val2)
{
int64 *result = palloc(sizeof(int64));
if (!PointerIsValid(val2))
return NULL;
*result = (int64) val1 **val2;
return result;
} /* int48mul() */
int64 *
int48div(int32 val1, int64 *val2)
{
int64 *result = palloc(sizeof(int64));
if (!PointerIsValid(val2))
return NULL;
*result = (int64) val1 / *val2;
return result;
} /* int48div() */
/*----------------------------------------------------------
* Conversion operators.
*---------------------------------------------------------*/
int64 *
int48(int32 val)
{
int64 *result = palloc(sizeof(int64));
*result = val;
return result;
} /* int48() */
int32
int84(int64 *val)
{
int32 result;
if (!PointerIsValid(val))
elog(ERROR, "Invalid (null) int64, can't convert int8 to int4");
if ((*val < INT_MIN) || (*val > INT_MAX))
elog(ERROR, "int8 conversion to int4 is out of range");
result = *val;
return result;
} /* int84() */
#if NOT_USED
int64 *
int2vector (int16 val)
{
int64 *result;
result = palloc(sizeof(int64));
*result = val;
return result;
} /* int2vector() */
int16
int82(int64 *val)
{
int16 result;
if (!PointerIsValid(val))
elog(ERROR, "Invalid (null) int8, can't convert to int2");
if ((*val < SHRT_MIN) || (*val > SHRT_MAX))
elog(ERROR, "int8 conversion to int2 is out of range");
result = *val;
return result;
} /* int82() */
#endif
float64
i8tod(int64 *val)
{
float64 result = palloc(sizeof(float64data));
if (!PointerIsValid(val))
elog(ERROR, "Invalid (null) int8, can't convert to float8");
*result = *val;
return result;
} /* i8tod() */
/* dtoi8()
* Convert double float to 8-byte integer.
* Do a range check before the conversion.
* Note that the comparison probably isn't quite right
* since we only have ~52 bits of precision in a double float
* and so subtracting one from a large number gives the large
* number exactly. However, for some reason the comparison below
* does the right thing on my i686/linux-rh4.2 box.
* - thomas 1998-06-16
*/
int64 *
dtoi8(float64 val)
{
int64 *result = palloc(sizeof(int64));
if (!PointerIsValid(val))
elog(ERROR, "Invalid (null) float8, can't convert to int8");
if ((*val < (-pow(2, 63) + 1)) || (*val > (pow(2, 63) - 1)))
elog(ERROR, "Floating point conversion to int64 is out of range");
*result = *val;
return result;
} /* dtoi8() */
/* text_int8()
*/
int64 *
text_int8(text *str)
{
int len;
char *s;
if (!PointerIsValid(str))
elog(ERROR, "Bad (null) int8 external representation");
len = (VARSIZE(str) - VARHDRSZ);
s = palloc(len + 1);
memmove(s, VARDATA(str), len);
*(s + len) = '\0';
return int8in(s);
} /* text_int8() */
/* int8_text()
*/
text *
int8_text(int64 *val)
{
text *result;
int len;
char *s;
if (!PointerIsValid(val))
return NULL;
s = int8out(val);
len = strlen(s);
result = palloc(VARHDRSZ + len);
VARSIZE(result) = len + VARHDRSZ;
memmove(VARDATA(result), s, len);
return result;
} /* int8_text() */