greenplumn strtof 源码

  • 2022-08-18
  • 浏览 (549)

greenplumn strtof 代码

文件路径:/src/port/strtof.c

/*-------------------------------------------------------------------------
 *
 * strtof.c
 *
 * Portions Copyright (c) 2019, PostgreSQL Global Development Group
 *
 *
 * IDENTIFICATION
 *	  src/port/strtof.c
 *
 *-------------------------------------------------------------------------
 */

#include "c.h"

#include <float.h>
#include <math.h>

#ifndef HAVE_STRTOF
/*
 * strtof() is part of C99; this version is only for the benefit of obsolete
 * platforms. As such, it is known to return incorrect values for edge cases,
 * which have to be allowed for in variant files for regression test results
 * for any such platform.
 */

float
strtof(const char *nptr, char **endptr)
{
	int			caller_errno = errno;
	double		dresult;
	float		fresult;

	errno = 0;
	dresult = strtod(nptr, endptr);
	fresult = (float) dresult;

	if (errno == 0)
	{
		/*
		 * Value might be in-range for double but not float.
		 */
		if (dresult != 0 && fresult == 0)
			caller_errno = ERANGE;	/* underflow */
		if (!isinf(dresult) && isinf(fresult))
			caller_errno = ERANGE;	/* overflow */
	}
	else
		caller_errno = errno;

	errno = caller_errno;
	return fresult;
}

#elif HAVE_BUGGY_STRTOF
/*
 * On Windows, there's a slightly different problem: VS2013 has a strtof()
 * that returns the correct results for valid input, but may fail to report an
 * error for underflow or overflow, returning 0 instead. Work around that by
 * trying strtod() when strtof() returns 0.0 or [+-]Inf, and calling it an
 * error if the result differs. Also, strtof() doesn't handle subnormal input
 * well, so prefer to round the strtod() result in such cases. (Normally we'd
 * just say "too bad" if strtof() doesn't support subnormals, but since we're
 * already in here fixing stuff, we might as well do the best fix we can.)
 *
 * Cygwin has a strtof() which is literally just (float)strtod(), which means
 * we can't avoid the double-rounding problem; but using this wrapper does get
 * us proper over/underflow checks. (Also, if they fix their strtof(), the
 * wrapper doesn't break anything.)
 *
 * Test results on Mingw suggest that it has the same problem, though looking
 * at the code I can't figure out why.
 */
float
pg_strtof(const char *nptr, char **endptr)
{
	int			caller_errno = errno;
	float		fresult;

	errno = 0;
	fresult = (strtof) (nptr, endptr);
	if (errno)
	{
		/* On error, just return the error to the caller. */
		return fresult;
	}
	else if ((*endptr == nptr) || isnan(fresult) ||
			 ((fresult >= FLT_MIN || fresult <= -FLT_MIN) && !isinf(fresult)))
	{
		/*
		 * If we got nothing parseable, or if we got a non-0 non-subnormal
		 * finite value (or NaN) without error, then return that to the caller
		 * without error.
		 */
		errno = caller_errno;
		return fresult;
	}
	else
	{
		/*
		 * Try again. errno is already 0 here.
		 */
		double		dresult = strtod(nptr, NULL);

		if (errno)
		{
			/* On error, just return the error */
			return fresult;
		}
		else if ((dresult == 0.0 && fresult == 0.0) ||
				 (isinf(dresult) && isinf(fresult) && (fresult == dresult)))
		{
			/* both values are 0 or infinities of the same sign */
			errno = caller_errno;
			return fresult;
		}
		else if ((dresult > 0 && dresult <= FLT_MIN && (float) dresult != 0.0) ||
				 (dresult < 0 && dresult >= -FLT_MIN && (float) dresult != 0.0))
		{
			/* subnormal but nonzero value */
			errno = caller_errno;
			return (float) dresult;
		}
		else
		{
			errno = ERANGE;
			return fresult;
		}
	}
}

#endif

相关信息

greenplumn 源码目录

相关文章

greenplumn chklocale 源码

greenplumn crypt 源码

greenplumn dirent 源码

greenplumn dirmod 源码

greenplumn dlopen 源码

greenplumn erand48 源码

greenplumn fls 源码

greenplumn fseeko 源码

greenplumn getaddrinfo 源码

greenplumn getopt 源码

0  赞