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