/* $NetBSD: ldtoa.c,v 1.4.2.1 2007/05/07 19:49:06 pavel Exp $ */ | |
/*- | |
* Copyright (c) 2003 David Schultz <das@FreeBSD.ORG> | |
* All rights reserved. | |
* | |
* Redistribution and use in source and binary forms, with or without | |
* modification, are permitted provided that the following conditions | |
* are met: | |
* 1. Redistributions of source code must retain the above copyright | |
* notice, this list of conditions and the following disclaimer. | |
* 2. Redistributions in binary form must reproduce the above copyright | |
* notice, this list of conditions and the following disclaimer in the | |
* documentation and/or other materials provided with the distribution. | |
* | |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND | |
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE | |
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | |
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | |
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |
* SUCH DAMAGE. | |
*/ | |
#include <LibConfig.h> | |
#include <sys/EfiCdefs.h> | |
#include <float.h> | |
#include <inttypes.h> | |
#include <limits.h> | |
#include <math.h> | |
#include <stdlib.h> | |
#include <machine/ieee.h> | |
#include "gdtoaimp.h" | |
#if defined(_MSC_VER) | |
/* Disable warnings about conversions to narrower data types, | |
primarily for the fpclassify() macro. | |
*/ | |
#pragma warning ( disable : 4244 ) | |
// Squelch bogus warnings about uninitialized variable use. | |
#pragma warning ( disable : 4700 ) | |
#endif | |
/* | |
* ldtoa() is a wrapper for gdtoa() that makes it smell like dtoa(), | |
* except that the floating point argument is passed by reference. | |
* When dtoa() is passed a NaN or infinity, it sets expt to 9999. | |
* However, a long double could have a valid exponent of 9999, so we | |
* use INT_MAX in ldtoa() instead. | |
*/ | |
char * | |
ldtoa(long double *ld, int mode, int ndigits, int *decpt, int *sign, char **rve) | |
{ | |
#ifdef EXT_EXPBITS | |
static FPI fpi = { | |
LDBL_MANT_DIG, /* nbits */ | |
LDBL_MIN_EXP - LDBL_MANT_DIG, /* emin */ | |
LDBL_MAX_EXP - LDBL_MANT_DIG, /* emax */ | |
FPI_Round_near, /* rounding */ | |
#ifdef Sudden_Underflow /* unused, but correct anyway */ | |
1 | |
#else | |
0 | |
#endif | |
}; | |
int be, kind; | |
char *ret; | |
union ieee_ext_u u; | |
uint32_t bits[(LDBL_MANT_DIG + 31) / 32]; | |
u.extu_ld = *ld; | |
*sign = (int)(u.extu_ext.ext_sign); | |
be = (int)(u.extu_ext.ext_exp - (LDBL_MAX_EXP - 1) - (LDBL_MANT_DIG - 1)); | |
EXT_TO_ARRAY32(u, bits); | |
switch (fpclassify(u.extu_ld)) { | |
case FP_NORMAL: | |
kind = STRTOG_Normal; | |
#ifdef LDBL_IMPLICIT_NBIT | |
bits[LDBL_MANT_DIG / 32] |= 1 << ((LDBL_MANT_DIG - 1) % 32); | |
#endif /* LDBL_IMPLICIT_NBIT */ | |
break; | |
case FP_ZERO: | |
kind = STRTOG_Zero; | |
break; | |
case FP_SUBNORMAL: | |
kind = STRTOG_Denormal; | |
#ifdef LDBL_IMPLICIT_NBIT | |
be++; | |
#endif | |
break; | |
case FP_INFINITE: | |
kind = STRTOG_Infinite; | |
break; | |
case FP_NAN: | |
kind = STRTOG_NaN; | |
break; | |
default: | |
abort(); | |
} | |
ret = gdtoa(&fpi, be, (ULong *)bits, &kind, mode, ndigits, decpt, rve); | |
if (*decpt == -32768) | |
*decpt = INT_MAX; | |
return ret; | |
#else | |
return dtoa((double)*ld, mode, ndigits, decpt, sign, rve); | |
#endif | |
} |