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

📄 float.c

📁 关系型数据库 Postgresql 6.5.2
💻 C
📖 第 1 页 / 共 2 页
字号:
/*------------------------------------------------------------------------- * * float.c *	  Functions for the built-in floating-point types. * * Copyright (c) 1994, Regents of the University of California * * * IDENTIFICATION *	  $Header: /usr/local/cvsroot/pgsql/src/backend/utils/adt/float.c,v 1.42.2.1 1999/08/02 05:24:52 scrappy Exp $ * *------------------------------------------------------------------------- *//* * OLD COMMENTS *		Basic float4 ops: *		 float4in, float4out, float4abs, float4um *		Basic float8 ops: *		 float8in, float8inAd, float8out, float8outAd, float8abs, float8um *		Arithmetic operators: *		 float4pl, float4mi, float4mul, float4div *		 float8pl, float8mi, float8mul, float8div *		Comparison operators: *		 float4eq, float4ne, float4lt, float4le, float4gt, float4ge *		 float8eq, float8ne, float8lt, float8le, float8gt, float8ge *		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 converting...) * * 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 <ctype.h>#include <errno.h>#include <float.h>				/* faked on sunos4 */#include <math.h>#include "postgres.h"#ifdef HAVE_LIMITS_H#include <limits.h>#endif#include "fmgr.h"#include "utils/builtins.h"#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#define FORMAT			'g'		/* use "g" output format as standard								 * format *//* not sure what the following should be, but better to make it over-sufficient */#define MAXFLOATWIDTH	64#define MAXDOUBLEWIDTH	128#if !(NeXT && NX_CURRENT_COMPILER_RELEASE > NX_COMPILER_RELEASE_3_2) /* NS3.3 has conflicting declarations of these in <math.h> */#ifndef atofextern double atof(const char *p);#endif#ifndef HAVE_CBRT#define cbrt my_cbrtstatic double cbrt(double x);#else#if !defined(nextstep)extern double cbrt(double x);#endif#endif#ifndef HAVE_RINT#define rint my_rintstatic double rint(double x);#elseextern double rint(double x);#endif#endif/* ========== USER I/O ROUTINES ========== */#define FLOAT4_MAX		 FLT_MAX#define FLOAT4_MIN		 FLT_MIN#define FLOAT8_MAX		 DBL_MAX#define FLOAT8_MIN		 DBL_MIN/* * if FLOAT8_MIN and FLOAT8_MAX are the limits of the range a * double can store, then how are we ever going to wind up * with something stored in a double that is outside those * limits?	(and similarly for FLOAT4_{MIN,MAX}/float.) * doesn't make sense to me, and it causes a * floating point exception on linuxalpha, so UNSAFE_FLOATS * it is. * (maybe someone wanted to allow for values other than DBL_MIN/ * DBL_MAX for FLOAT8_MIN/FLOAT8_MAX?) *								--djm 12/12/96 * according to Richard Henderson this is a known bug in gcc on * the Alpha.  might as well leave the workaround in * until the distributions are updated. *								--djm 12/16/96 */#if ( defined(linux) && defined(__alpha__) ) && !defined(UNSAFE_FLOATS)#define UNSAFE_FLOATS#endif/*   check to see if a float4 val is outside of   the FLOAT4_MIN, FLOAT4_MAX bounds.   raise an elog 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)		elog(ERROR, "Bad float4 input format -- overflow");	if (val != 0.0 && fabs(val) < FLOAT4_MIN)		elog(ERROR, "Bad float4 input format -- underflow");	return;#endif	 /* UNSAFE_FLOATS */}/*   check to see if a float8 val is outside of   the FLOAT8_MIN, FLOAT8_MAX bounds.   raise an elog warning if it is*/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)		elog(ERROR, "Bad float8 input format -- overflow");	if (val != 0.0 && fabs(val) < FLOAT8_MIN)		elog(ERROR, "Bad float8 input format -- underflow");	return;#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. */float32float4in(char *num){	float32		result = (float32) palloc(sizeof(float32data));	double		val;	char	   *endptr;	errno = 0;	val = strtod(num, &endptr);	if (*endptr != '\0')	{		/* Should we accept "NaN" or "Infinity" for float4? */		elog(ERROR, "Bad float4 input format '%s'", num);	}	else	{		if (errno == ERANGE)			elog(ERROR, "Input '%s' is out of range for float4", num);	}	/*	 * if we get here, we have a legal double, still need to check to see	 * if it's a legal float	 */	CheckFloat4Val(val);	*result = val;	return result;}/* *		float4out		- converts a float4 number to a string *						  using a standard output format */char *float4out(float32 num){	char	   *ascii = (char *) palloc(MAXFLOATWIDTH + 1);	if (!num)		return strcpy(ascii, "(null)");	sprintf(ascii, "%.*g", FLT_DIG, *num);	return ascii;}/* *		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. */float64float8in(char *num){	float64		result = (float64) palloc(sizeof(float64data));	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			elog(ERROR, "Bad float8 input format '%s'", num);	}	else	{		if (errno == ERANGE)			elog(ERROR, "Input '%s' is out of range for float8", num);	}	CheckFloat8Val(val);	*result = val;	return result;}/* *		float8out		- converts float8 number to a string *						  using a standard output format */char *float8out(float64 num){	char	   *ascii = (char *) palloc(MAXDOUBLEWIDTH + 1);	if (!num)		return strcpy(ascii, "(null)");	if (isnan(*num))		return strcpy(ascii, "NaN");	if (isinf(*num))		return strcpy(ascii, "Infinity");	sprintf(ascii, "%.*g", DBL_DIG, *num);	return ascii;}/* ========== PUBLIC ROUTINES ========== *//* *		====================== *		FLOAT4 BASE OPERATIONS *		====================== *//* *		float4abs		- returns a pointer to |arg1| (absolute value) */float32float4abs(float32 arg1){	float32		result;	double		val;	if (!arg1)		return (float32) NULL;	val = fabs(*arg1);	CheckFloat4Val(val);	result = (float32) palloc(sizeof(float32data));	*result = val;	return result;}/* *		float4um		- returns a pointer to -arg1 (unary minus) */float32float4um(float32 arg1){	float32		result;	double		val;	if (!arg1)		return (float32) NULL;	val = ((*arg1 != 0) ? -(*arg1) : *arg1);	CheckFloat4Val(val);	result = (float32) palloc(sizeof(float32data));	*result = val;	return result;}float32float4larger(float32 arg1, float32 arg2){	float32		result;	if (!arg1 || !arg2)		return (float32) NULL;	result = (float32) palloc(sizeof(float32data));	*result = ((*arg1 > *arg2) ? *arg1 : *arg2);	return result;}float32float4smaller(float32 arg1, float32 arg2){	float32		result;	if (!arg1 || !arg2)		return (float32) NULL;	result = (float32) palloc(sizeof(float32data));	*result = ((*arg1 > *arg2) ? *arg2 : *arg1);	return result;}/* *		====================== *		FLOAT8 BASE OPERATIONS *		====================== *//* *		float8abs		- returns a pointer to |arg1| (absolute value) */float64float8abs(float64 arg1){	float64		result;	double		val;	if (!arg1)		return (float64) NULL;	result = (float64) palloc(sizeof(float64data));	val = fabs(*arg1);	CheckFloat8Val(val);	*result = val;	return result;}/* *		float8um		- returns a pointer to -arg1 (unary minus) */float64float8um(float64 arg1){	float64		result;	double		val;	if (!arg1)		return (float64) NULL;	val = ((*arg1 != 0) ? -(*arg1) : *arg1);	CheckFloat8Val(val);	result = (float64) palloc(sizeof(float64data));	*result = val;	return result;}float64float8larger(float64 arg1, float64 arg2){	float64		result;	if (!arg1 || !arg2)		return (float64) NULL;	result = (float64) palloc(sizeof(float64data));	*result = ((*arg1 > *arg2) ? *arg1 : *arg2);	return result;}float64float8smaller(float64 arg1, float64 arg2){	float64		result;	if (!arg1 || !arg2)		return (float64) NULL;	result = (float64) palloc(sizeof(float64data));	*result = ((*arg1 > *arg2) ? *arg2 : *arg1);	return result;}/* *		==================== *		ARITHMETIC OPERATORS *		==================== *//* *		float4pl		- returns a pointer to arg1 + arg2 *		float4mi		- returns a pointer to arg1 - arg2 *		float4mul		- returns a pointer to arg1 * arg2 *		float4div		- returns a pointer to arg1 / arg2 *		float4inc		- returns a poniter to arg1 + 1.0 */float32float4pl(float32 arg1, float32 arg2){	float32		result;	double		val;	if (!arg1 || !arg2)		return (float32) NULL;	val = *arg1 + *arg2;	CheckFloat4Val(val);	result = (float32) palloc(sizeof(float32data));	*result = val;	return result;}float32float4mi(float32 arg1, float32 arg2){	float32		result;	double		val;	if (!arg1 || !arg2)		return (float32) NULL;	val = *arg1 - *arg2;	CheckFloat4Val(val);	result = (float32) palloc(sizeof(float32data));	*result = val;	return result;}float32float4mul(float32 arg1, float32 arg2){	float32		result;	double		val;	if (!arg1 || !arg2)		return (float32) NULL;	val = *arg1 * *arg2;	CheckFloat4Val(val);	result = (float32) palloc(sizeof(float32data));	*result = val;	return result;}float32float4div(float32 arg1, float32 arg2){	float32		result;	double		val;	if (!arg1 || !arg2)		return (float32) NULL;	if (*arg2 == 0.0)		elog(ERROR, "float4div: divide by zero error");	val = *arg1 / *arg2;	CheckFloat4Val(val);	result = (float32) palloc(sizeof(float32data));	*result = *arg1 / *arg2;	return result;}float32float4inc(float32 arg1){	double		val;	if (!arg1)		return (float32) NULL;	val = *arg1 + (float32data) 1.0;	CheckFloat4Val(val);	*arg1 = val;	return arg1;}/* *		float8pl		- returns a pointer to arg1 + arg2 *		float8mi		- returns a pointer to arg1 - arg2 *		float8mul		- returns a pointer to arg1 * arg2 *		float8div		- returns a pointer to arg1 / arg2 *		float8inc		- returns a pointer to arg1 + 1.0 */float64float8pl(float64 arg1, float64 arg2){	float64		result;	double		val;	if (!arg1 || !arg2)		return (float64) NULL;	result = (float64) palloc(sizeof(float64data));	val = *arg1 + *arg2;	CheckFloat8Val(val);	*result = val;	return result;}float64float8mi(float64 arg1, float64 arg2){	float64		result;	double		val;	if (!arg1 || !arg2)		return (float64) NULL;	result = (float64) palloc(sizeof(float64data));	val = *arg1 - *arg2;	CheckFloat8Val(val);	*result = val;	return result;}float64float8mul(float64 arg1, float64 arg2){	float64		result;	double		val;	if (!arg1 || !arg2)		return (float64) NULL;	result = (float64) palloc(sizeof(float64data));	val = *arg1 * *arg2;	CheckFloat8Val(val);	*result = val;	return result;}float64float8div(float64 arg1, float64 arg2){	float64		result;	double		val;	if (!arg1 || !arg2)		return (float64) NULL;	result = (float64) palloc(sizeof(float64data));	if (*arg2 == 0.0)		elog(ERROR, "float8div: divide by zero error");	val = *arg1 / *arg2;	CheckFloat8Val(val);	*result = val;	return result;}float64float8inc(float64 arg1){	double		val;	if (!arg1)		return (float64) NULL;	val = *arg1 + (float64data) 1.0;	CheckFloat8Val(val);	*arg1 = val;	return arg1;}/* *		==================== *		COMPARISON OPERATORS *		==================== *//* *		float4{eq,ne,lt,le,gt,ge}		- float4/float4 comparison operations */boolfloat4eq(float32 arg1, float32 arg2){	if (!arg1 || !arg2)		return 0;	return *arg1 == *arg2;}boolfloat4ne(float32 arg1, float32 arg2){	if (!arg1 || !arg2)		return 0;	return *arg1 != *arg2;}boolfloat4lt(float32 arg1, float32 arg2){	if (!arg1 || !arg2)		return 0;	return *arg1 < *arg2;}boolfloat4le(float32 arg1, float32 arg2){	if (!arg1 || !arg2)		return 0;	return *arg1 <= *arg2;}boolfloat4gt(float32 arg1, float32 arg2){	if (!arg1 || !arg2)		return 0;	return *arg1 > *arg2;}boolfloat4ge(float32 arg1, float32 arg2){	if (!arg1 || !arg2)		return 0;	return *arg1 >= *arg2;}/* *		float8{eq,ne,lt,le,gt,ge}		- float8/float8 comparison operations */boolfloat8eq(float64 arg1, float64 arg2){	if (!arg1 || !arg2)		return 0;	return *arg1 == *arg2;}boolfloat8ne(float64 arg1, float64 arg2){	if (!arg1 || !arg2)		return 0;	return *arg1 != *arg2;}boolfloat8lt(float64 arg1, float64 arg2){	if (!arg1 || !arg2)		return 0;	return *arg1 < *arg2;}boolfloat8le(float64 arg1, float64 arg2){	if (!arg1 || !arg2)		return 0;	return *arg1 <= *arg2;}boolfloat8gt(float64 arg1, float64 arg2){	if (!arg1 || !arg2)		return 0;	return *arg1 > *arg2;}boolfloat8ge(float64 arg1, float64 arg2){	if (!arg1 || !arg2)		return 0;	return *arg1 >= *arg2;}/* *		=================== *		CONVERSION ROUTINES *		=================== *//* *		ftod			- converts a float4 number to a float8 number */float64ftod(float32 num){	float64		result;	if (!num)		return (float64) NULL;	result = (float64) palloc(sizeof(float64data));	*result = *num;	return result;}/* *		dtof			- converts a float8 number to a float4 number */float32dtof(float64 num){	float32		result;	if (!num)		return (float32) NULL;	CheckFloat4Val(*num);	result = (float32) palloc(sizeof(float32data));	*result = *num;	return result;}

⌨️ 快捷键说明

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