| /* $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 | |
| } |