192b93b37SDavid Schultz /*- 292b93b37SDavid Schultz * Copyright (c) 2003 David Schultz <das@FreeBSD.ORG> 392b93b37SDavid Schultz * All rights reserved. 492b93b37SDavid Schultz * 592b93b37SDavid Schultz * Redistribution and use in source and binary forms, with or without 692b93b37SDavid Schultz * modification, are permitted provided that the following conditions 792b93b37SDavid Schultz * are met: 892b93b37SDavid Schultz * 1. Redistributions of source code must retain the above copyright 992b93b37SDavid Schultz * notice, this list of conditions and the following disclaimer. 1092b93b37SDavid Schultz * 2. Redistributions in binary form must reproduce the above copyright 1192b93b37SDavid Schultz * notice, this list of conditions and the following disclaimer in the 1292b93b37SDavid Schultz * documentation and/or other materials provided with the distribution. 1392b93b37SDavid Schultz * 1492b93b37SDavid Schultz * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1592b93b37SDavid Schultz * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1692b93b37SDavid Schultz * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1792b93b37SDavid Schultz * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 1892b93b37SDavid Schultz * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 1992b93b37SDavid Schultz * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2092b93b37SDavid Schultz * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2192b93b37SDavid Schultz * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2292b93b37SDavid Schultz * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2392b93b37SDavid Schultz * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2492b93b37SDavid Schultz * SUCH DAMAGE. 2592b93b37SDavid Schultz */ 2692b93b37SDavid Schultz 2792b93b37SDavid Schultz #include <sys/cdefs.h> 2892b93b37SDavid Schultz __FBSDID("$FreeBSD$"); 2992b93b37SDavid Schultz 3092b93b37SDavid Schultz #include <float.h> 3192b93b37SDavid Schultz #include <inttypes.h> 3292b93b37SDavid Schultz #include <limits.h> 3392b93b37SDavid Schultz #include <math.h> 3492b93b37SDavid Schultz #include <stdlib.h> 35*f8af09cdSCraig Rodrigues #include "../stdio/floatio.h" 3692b93b37SDavid Schultz #include "fpmath.h" 3792b93b37SDavid Schultz #include "gdtoaimp.h" 3892b93b37SDavid Schultz 3992b93b37SDavid Schultz /* 4092b93b37SDavid Schultz * ldtoa() is a wrapper for gdtoa() that makes it smell like dtoa(), 4192b93b37SDavid Schultz * except that the floating point argument is passed by reference. 4292b93b37SDavid Schultz * When dtoa() is passed a NaN or infinity, it sets expt to 9999. 4392b93b37SDavid Schultz * However, a long double could have a valid exponent of 9999, so we 4492b93b37SDavid Schultz * use INT_MAX in ldtoa() instead. 4592b93b37SDavid Schultz */ 4692b93b37SDavid Schultz char * 4792b93b37SDavid Schultz __ldtoa(long double *ld, int mode, int ndigits, int *decpt, int *sign, 4892b93b37SDavid Schultz char **rve) 4992b93b37SDavid Schultz { 509c90f85aSDavid Schultz FPI fpi = { 5192b93b37SDavid Schultz LDBL_MANT_DIG, /* nbits */ 5292b93b37SDavid Schultz LDBL_MIN_EXP - LDBL_MANT_DIG, /* emin */ 5392b93b37SDavid Schultz LDBL_MAX_EXP - LDBL_MANT_DIG, /* emax */ 549c90f85aSDavid Schultz FLT_ROUNDS, /* rounding */ 5592b93b37SDavid Schultz #ifdef Sudden_Underflow /* unused, but correct anyway */ 5692b93b37SDavid Schultz 1 5792b93b37SDavid Schultz #else 5892b93b37SDavid Schultz 0 5992b93b37SDavid Schultz #endif 6092b93b37SDavid Schultz }; 6192b93b37SDavid Schultz int be, kind; 6292b93b37SDavid Schultz char *ret; 6392b93b37SDavid Schultz union IEEEl2bits u; 6492b93b37SDavid Schultz uint32_t bits[(LDBL_MANT_DIG + 31) / 32]; 653e636fa0SJohn Birrell void *vbits = bits; 6692b93b37SDavid Schultz 6792b93b37SDavid Schultz u.e = *ld; 689c90f85aSDavid Schultz 699c90f85aSDavid Schultz /* 709c90f85aSDavid Schultz * gdtoa doesn't know anything about the sign of the number, so 719c90f85aSDavid Schultz * if the number is negative, we need to swap rounding modes of 729c90f85aSDavid Schultz * 2 (upwards) and 3 (downwards). 739c90f85aSDavid Schultz */ 7492b93b37SDavid Schultz *sign = u.bits.sign; 759c90f85aSDavid Schultz fpi.rounding ^= (fpi.rounding >> 1) & u.bits.sign; 769c90f85aSDavid Schultz 7792b93b37SDavid Schultz be = u.bits.exp - (LDBL_MAX_EXP - 1) - (LDBL_MANT_DIG - 1); 7892b93b37SDavid Schultz LDBL_TO_ARRAY32(u, bits); 7992b93b37SDavid Schultz 8092b93b37SDavid Schultz switch (fpclassify(u.e)) { 8192b93b37SDavid Schultz case FP_NORMAL: 8292b93b37SDavid Schultz kind = STRTOG_Normal; 8392b93b37SDavid Schultz #ifdef LDBL_IMPLICIT_NBIT 8492b93b37SDavid Schultz bits[LDBL_MANT_DIG / 32] |= 1 << ((LDBL_MANT_DIG - 1) % 32); 8592b93b37SDavid Schultz #endif /* LDBL_IMPLICIT_NBIT */ 8692b93b37SDavid Schultz break; 8792b93b37SDavid Schultz case FP_ZERO: 8892b93b37SDavid Schultz kind = STRTOG_Zero; 8992b93b37SDavid Schultz break; 9092b93b37SDavid Schultz case FP_SUBNORMAL: 9192b93b37SDavid Schultz kind = STRTOG_Denormal; 92d784b0c3SDavid Schultz be++; 9392b93b37SDavid Schultz break; 9492b93b37SDavid Schultz case FP_INFINITE: 9592b93b37SDavid Schultz kind = STRTOG_Infinite; 9692b93b37SDavid Schultz break; 9792b93b37SDavid Schultz case FP_NAN: 9892b93b37SDavid Schultz kind = STRTOG_NaN; 9992b93b37SDavid Schultz break; 10092b93b37SDavid Schultz default: 10192b93b37SDavid Schultz abort(); 10292b93b37SDavid Schultz } 10392b93b37SDavid Schultz 1043e636fa0SJohn Birrell ret = gdtoa(&fpi, be, vbits, &kind, mode, ndigits, decpt, rve); 10592b93b37SDavid Schultz if (*decpt == -32768) 10692b93b37SDavid Schultz *decpt = INT_MAX; 10792b93b37SDavid Schultz return ret; 10892b93b37SDavid Schultz } 109