⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 float.c

📁 PostgreSQL7.4.6 for Linux
💻 C
📖 第 1 页 / 共 3 页
字号:
/*------------------------------------------------------------------------- * * float.c *	  Functions for the built-in floating-point types. * * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * * * IDENTIFICATION *	  $Header: /cvsroot/pgsql/src/backend/utils/adt/float.c,v 1.94 2003/09/25 06:58:03 petere Exp $ * *------------------------------------------------------------------------- *//*---------- * OLD COMMENTS *		Basic float4 ops: *		 float4in, float4out, float4recv, float4send *		 float4abs, float4um, float4up *		Basic float8 ops: *		 float8in, float8out, float8recv, float8send *		 float8abs, float8um, float8up *		Arithmetic operators: *		 float4pl, float4mi, float4mul, float4div *		 float8pl, float8mi, float8mul, float8div *		Comparison operators: *		 float4eq, float4ne, float4lt, float4le, float4gt, float4ge, float4cmp *		 float8eq, float8ne, float8lt, float8le, float8gt, float8ge, float8cmp *		Conversion routines: *		 ftod, dtof, i4tod, dtoi4, i2tod, dtoi2, itof, ftoi, i2tof, ftoi2 * *		Random float8 ops: *		 dround, dtrunc, dsqrt, dcbrt, dpow, dexp, dlog1 *		Arithmetic operators: *		 float48pl, float48mi, float48mul, float48div *		 float84pl, float84mi, float84mul, float84div *		Comparison operators: *		 float48eq, float48ne, float48lt, float48le, float48gt, float48ge *		 float84eq, float84ne, float84lt, float84le, float84gt, float84ge * *		(You can do the arithmetic and comparison stuff using conversion *		 routines, but then you pay the overhead of invoking a separate *		 conversion function...) * * XXX GLUESOME STUFF. FIX IT! -AY '94 * *		Added some additional conversion routines and cleaned up *		 a bit of the existing code. Need to change the error checking *		 for calls to pow(), exp() since on some machines (my Linux box *		 included) these routines do not set errno. - tgl 97/05/10 *---------- */#include "postgres.h"#include <ctype.h>#include <errno.h>#include <float.h>				/* faked on sunos4 */#include <math.h>#include <limits.h>/* for finite() on Solaris */#ifdef HAVE_IEEEFP_H#include <ieeefp.h>#endif#include "catalog/pg_type.h"#include "fmgr.h"#include "libpq/pqformat.h"#include "utils/array.h"#include "utils/builtins.h"#ifndef HAVE_CBRTstatic double cbrt(double x);#endif   /* HAVE_CBRT */#ifndef M_PI/* from my RH5.2 gcc math.h file - thomas 2000-04-03 */#define M_PI 3.14159265358979323846#endif#ifndef NAN#define NAN		(0.0/0.0)#endif#ifndef SHRT_MAX#define SHRT_MAX 32767#endif#ifndef SHRT_MIN#define SHRT_MIN (-32768)#endif/* not sure what the following should be, but better to make it over-sufficient */#define MAXFLOATWIDTH	64#define MAXDOUBLEWIDTH	128/* ========== USER I/O ROUTINES ========== */#define FLOAT4_MAX		 FLT_MAX#define FLOAT4_MIN		 FLT_MIN#define FLOAT8_MAX		 DBL_MAX#define FLOAT8_MIN		 DBL_MIN/* Configurable GUC parameter */int			extra_float_digits = 0;		/* Added to DBL_DIG or FLT_DIG */static void CheckFloat4Val(double val);static void CheckFloat8Val(double val);static int	float4_cmp_internal(float4 a, float4 b);static int	float8_cmp_internal(float8 a, float8 b);/* * check to see if a float4 val is outside of * the FLOAT4_MIN, FLOAT4_MAX bounds. * * raise an ereport warning if it is*/static voidCheckFloat4Val(double val){	/*	 * defining unsafe floats's will make float4 and float8 ops faster at	 * the cost of safety, of course!	 */#ifdef UNSAFE_FLOATS	return;#else	if (fabs(val) > FLOAT4_MAX)		ereport(ERROR,				(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),				 errmsg("type \"real\" value out of range: overflow")));	if (val != 0.0 && fabs(val) < FLOAT4_MIN)		ereport(ERROR,				(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),				 errmsg("type \"real\" value out of range: underflow")));	return;#endif   /* UNSAFE_FLOATS */}/* * check to see if a float8 val is outside of * the FLOAT8_MIN, FLOAT8_MAX bounds. * * raise an ereport error if it is */static voidCheckFloat8Val(double val){	/*	 * defining unsafe floats's will make float4 and float8 ops faster at	 * the cost of safety, of course!	 */#ifdef UNSAFE_FLOATS	return;#else	if (fabs(val) > FLOAT8_MAX)		ereport(ERROR,				(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),				 errmsg("type \"double precision\" value out of range: overflow")));	if (val != 0.0 && fabs(val) < FLOAT8_MIN)		ereport(ERROR,				(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),				 errmsg("type \"double precision\" value out of range: underflow")));#endif   /* UNSAFE_FLOATS */}/* *		float4in		- converts "num" to float *						  restricted syntax: *						  {<sp>} [+|-] {digit} [.{digit}] [<exp>] *						  where <sp> is a space, digit is 0-9, *						  <exp> is "e" or "E" followed by an integer. */Datumfloat4in(PG_FUNCTION_ARGS){	char	   *num = PG_GETARG_CSTRING(0);	double		val;	char	   *endptr;	errno = 0;	val = strtod(num, &endptr);	if (*endptr != '\0')	{		/*		 * XXX we should accept "Infinity" and "-Infinity" too, but what		 * are the correct values to assign?  HUGE_VAL will provoke an		 * error from CheckFloat4Val.		 */		if (strcasecmp(num, "NaN") == 0)			val = NAN;		else			ereport(ERROR,					(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),					 errmsg("invalid input syntax for type real: \"%s\"",							num)));	}	else	{		if (errno == ERANGE)			ereport(ERROR,					(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),					 errmsg("\"%s\" is out of range for type real", num)));	}	/*	 * if we get here, we have a legal double, still need to check to see	 * if it's a legal float	 */	CheckFloat4Val(val);	PG_RETURN_FLOAT4((float4) val);}/* *		float4out		- converts a float4 number to a string *						  using a standard output format */Datumfloat4out(PG_FUNCTION_ARGS){	float4		num = PG_GETARG_FLOAT4(0);	char	   *ascii = (char *) palloc(MAXFLOATWIDTH + 1);	int			infflag;	int			ndig;	if (isnan(num))		PG_RETURN_CSTRING(strcpy(ascii, "NaN"));	infflag = isinf(num);	if (infflag > 0)		PG_RETURN_CSTRING(strcpy(ascii, "Infinity"));	if (infflag < 0)		PG_RETURN_CSTRING(strcpy(ascii, "-Infinity"));	ndig = FLT_DIG + extra_float_digits;	if (ndig < 1)		ndig = 1;	sprintf(ascii, "%.*g", ndig, num);	PG_RETURN_CSTRING(ascii);}/* *		float4recv			- converts external binary format to float4 */Datumfloat4recv(PG_FUNCTION_ARGS){	StringInfo	buf = (StringInfo) PG_GETARG_POINTER(0);	PG_RETURN_FLOAT4(pq_getmsgfloat4(buf));}/* *		float4send			- converts float4 to binary format */Datumfloat4send(PG_FUNCTION_ARGS){	float4		num = PG_GETARG_FLOAT4(0);	StringInfoData buf;	pq_begintypsend(&buf);	pq_sendfloat4(&buf, num);	PG_RETURN_BYTEA_P(pq_endtypsend(&buf));}/* *		float8in		- converts "num" to float8 *						  restricted syntax: *						  {<sp>} [+|-] {digit} [.{digit}] [<exp>] *						  where <sp> is a space, digit is 0-9, *						  <exp> is "e" or "E" followed by an integer. */Datumfloat8in(PG_FUNCTION_ARGS){	char	   *num = PG_GETARG_CSTRING(0);	double		val;	char	   *endptr;	errno = 0;	val = strtod(num, &endptr);	if (*endptr != '\0')	{		if (strcasecmp(num, "NaN") == 0)			val = NAN;		else if (strcasecmp(num, "Infinity") == 0)			val = HUGE_VAL;		else if (strcasecmp(num, "-Infinity") == 0)			val = -HUGE_VAL;		else			ereport(ERROR,					(errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),					 errmsg("invalid input syntax for type double precision: \"%s\"",							num)));	}	else	{		if (errno == ERANGE)			ereport(ERROR,					(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),					 errmsg("\"%s\" is out of range for type double precision", num)));	}	CheckFloat8Val(val);	PG_RETURN_FLOAT8(val);}/* *		float8out		- converts float8 number to a string *						  using a standard output format */Datumfloat8out(PG_FUNCTION_ARGS){	float8		num = PG_GETARG_FLOAT8(0);	char	   *ascii = (char *) palloc(MAXDOUBLEWIDTH + 1);	int			infflag;	int			ndig;	if (isnan(num))		PG_RETURN_CSTRING(strcpy(ascii, "NaN"));	infflag = isinf(num);	if (infflag > 0)		PG_RETURN_CSTRING(strcpy(ascii, "Infinity"));	if (infflag < 0)		PG_RETURN_CSTRING(strcpy(ascii, "-Infinity"));	ndig = DBL_DIG + extra_float_digits;	if (ndig < 1)		ndig = 1;	sprintf(ascii, "%.*g", ndig, num);	PG_RETURN_CSTRING(ascii);}/* *		float8recv			- converts external binary format to float8 */Datumfloat8recv(PG_FUNCTION_ARGS){	StringInfo	buf = (StringInfo) PG_GETARG_POINTER(0);	PG_RETURN_FLOAT8(pq_getmsgfloat8(buf));}/* *		float8send			- converts float8 to binary format */Datumfloat8send(PG_FUNCTION_ARGS){	float8		num = PG_GETARG_FLOAT8(0);	StringInfoData buf;	pq_begintypsend(&buf);	pq_sendfloat8(&buf, num);	PG_RETURN_BYTEA_P(pq_endtypsend(&buf));}/* ========== PUBLIC ROUTINES ========== *//* *		====================== *		FLOAT4 BASE OPERATIONS *		====================== *//* *		float4abs		- returns |arg1| (absolute value) */Datumfloat4abs(PG_FUNCTION_ARGS){	float4		arg1 = PG_GETARG_FLOAT4(0);	PG_RETURN_FLOAT4((float4) fabs(arg1));}/* *		float4um		- returns -arg1 (unary minus) */Datumfloat4um(PG_FUNCTION_ARGS){	float4		arg1 = PG_GETARG_FLOAT4(0);	PG_RETURN_FLOAT4((float4) -arg1);}Datumfloat4up(PG_FUNCTION_ARGS){	float4		arg = PG_GETARG_FLOAT4(0);	PG_RETURN_FLOAT4(arg);}Datumfloat4larger(PG_FUNCTION_ARGS){	float4		arg1 = PG_GETARG_FLOAT4(0);	float4		arg2 = PG_GETARG_FLOAT4(1);	float4		result;	if (float4_cmp_internal(arg1, arg2) > 0)		result = arg1;	else		result = arg2;	PG_RETURN_FLOAT4(result);}Datumfloat4smaller(PG_FUNCTION_ARGS){	float4		arg1 = PG_GETARG_FLOAT4(0);	float4		arg2 = PG_GETARG_FLOAT4(1);	float4		result;	if (float4_cmp_internal(arg1, arg2) < 0)		result = arg1;	else		result = arg2;	PG_RETURN_FLOAT4(result);}/* *		====================== *		FLOAT8 BASE OPERATIONS *		====================== *//* *		float8abs		- returns |arg1| (absolute value) */Datumfloat8abs(PG_FUNCTION_ARGS){	float8		arg1 = PG_GETARG_FLOAT8(0);	float8		result;	result = fabs(arg1);	CheckFloat8Val(result);	PG_RETURN_FLOAT8(result);}/* *		float8um		- returns -arg1 (unary minus) */Datumfloat8um(PG_FUNCTION_ARGS){	float8		arg1 = PG_GETARG_FLOAT8(0);	float8		result;	result = ((arg1 != 0) ? -(arg1) : arg1);	CheckFloat8Val(result);	PG_RETURN_FLOAT8(result);}Datumfloat8up(PG_FUNCTION_ARGS){	float8		arg = PG_GETARG_FLOAT8(0);	PG_RETURN_FLOAT8(arg);}Datumfloat8larger(PG_FUNCTION_ARGS){	float8		arg1 = PG_GETARG_FLOAT8(0);	float8		arg2 = PG_GETARG_FLOAT8(1);	float8		result;	if (float8_cmp_internal(arg1, arg2) > 0)		result = arg1;	else		result = arg2;	PG_RETURN_FLOAT8(result);}Datumfloat8smaller(PG_FUNCTION_ARGS){	float8		arg1 = PG_GETARG_FLOAT8(0);	float8		arg2 = PG_GETARG_FLOAT8(1);	float8		result;	if (float8_cmp_internal(arg1, arg2) < 0)		result = arg1;	else		result = arg2;	PG_RETURN_FLOAT8(result);}/* *		==================== *		ARITHMETIC OPERATORS *		==================== *//* *		float4pl		- returns arg1 + arg2 *		float4mi		- returns arg1 - arg2 *		float4mul		- returns arg1 * arg2 *		float4div		- returns arg1 / arg2 */Datumfloat4pl(PG_FUNCTION_ARGS){	float4		arg1 = PG_GETARG_FLOAT4(0);	float4		arg2 = PG_GETARG_FLOAT4(1);	double		result;	result = arg1 + arg2;	CheckFloat4Val(result);	PG_RETURN_FLOAT4((float4) result);}Datumfloat4mi(PG_FUNCTION_ARGS){	float4		arg1 = PG_GETARG_FLOAT4(0);	float4		arg2 = PG_GETARG_FLOAT4(1);	double		result;	result = arg1 - arg2;	CheckFloat4Val(result);	PG_RETURN_FLOAT4((float4) result);}Datumfloat4mul(PG_FUNCTION_ARGS){	float4		arg1 = PG_GETARG_FLOAT4(0);	float4		arg2 = PG_GETARG_FLOAT4(1);	double		result;	result = arg1 * arg2;	CheckFloat4Val(result);	PG_RETURN_FLOAT4((float4) result);}Datumfloat4div(PG_FUNCTION_ARGS){	float4		arg1 = PG_GETARG_FLOAT4(0);	float4		arg2 = PG_GETARG_FLOAT4(1);	double		result;	if (arg2 == 0.0)		ereport(ERROR,				(errcode(ERRCODE_DIVISION_BY_ZERO),				 errmsg("division by zero")));	/* Do division in float8, then check for overflow */	result = (float8) arg1 / (float8) arg2;	CheckFloat4Val(result);	PG_RETURN_FLOAT4((float4) result);}/* *		float8pl		- returns arg1 + arg2 *		float8mi		- returns arg1 - arg2 *		float8mul		- returns arg1 * arg2 *		float8div		- returns arg1 / arg2 */Datumfloat8pl(PG_FUNCTION_ARGS){	float8		arg1 = PG_GETARG_FLOAT8(0);	float8		arg2 = PG_GETARG_FLOAT8(1);	float8		result;	result = arg1 + arg2;	CheckFloat8Val(result);	PG_RETURN_FLOAT8(result);}Datumfloat8mi(PG_FUNCTION_ARGS){	float8		arg1 = PG_GETARG_FLOAT8(0);	float8		arg2 = PG_GETARG_FLOAT8(1);	float8		result;	result = arg1 - arg2;	CheckFloat8Val(result);	PG_RETURN_FLOAT8(result);}Datumfloat8mul(PG_FUNCTION_ARGS){	float8		arg1 = PG_GETARG_FLOAT8(0);	float8		arg2 = PG_GETARG_FLOAT8(1);	float8		result;	result = arg1 * arg2;	CheckFloat8Val(result);	PG_RETURN_FLOAT8(result);}Datumfloat8div(PG_FUNCTION_ARGS){	float8		arg1 = PG_GETARG_FLOAT8(0);	float8		arg2 = PG_GETARG_FLOAT8(1);	float8		result;	if (arg2 == 0.0)		ereport(ERROR,				(errcode(ERRCODE_DIVISION_BY_ZERO),				 errmsg("division by zero")));	result = arg1 / arg2;	CheckFloat8Val(result);	PG_RETURN_FLOAT8(result);}/* *		==================== *		COMPARISON OPERATORS *		==================== *//* *		float4{eq,ne,lt,le,gt,ge}		- float4/float4 comparison operations */static intfloat4_cmp_internal(float4 a, float4 b){	/*	 * We consider all NANs to be equal and larger than any non-NAN. This	 * is somewhat arbitrary; the important thing is to have a consistent	 * sort order.	 */	if (isnan(a))	{		if (isnan(b))			return 0;			/* NAN = NAN */		else			return 1;			/* NAN > non-NAN */	}	else if (isnan(b))	{		return -1;				/* non-NAN < NAN */	}	else	{		if (a > b)			return 1;		else if (a < b)			return -1;		else			return 0;	}}Datumfloat4eq(PG_FUNCTION_ARGS){	float4		arg1 = PG_GETARG_FLOAT4(0);	float4		arg2 = PG_GETARG_FLOAT4(1);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -