1113145Sdas/*- 2113145Sdas * Copyright (c) 2003 David Schultz <das@FreeBSD.ORG> 3113145Sdas * All rights reserved. 4113145Sdas * 5113145Sdas * Redistribution and use in source and binary forms, with or without 6113145Sdas * modification, are permitted provided that the following conditions 7113145Sdas * are met: 8113145Sdas * 1. Redistributions of source code must retain the above copyright 9113145Sdas * notice, this list of conditions and the following disclaimer. 10113145Sdas * 2. Redistributions in binary form must reproduce the above copyright 11113145Sdas * notice, this list of conditions and the following disclaimer in the 12113145Sdas * documentation and/or other materials provided with the distribution. 13113145Sdas * 14113145Sdas * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15113145Sdas * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16113145Sdas * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17113145Sdas * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18113145Sdas * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19113145Sdas * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20113145Sdas * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21113145Sdas * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22113145Sdas * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23113145Sdas * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24113145Sdas * SUCH DAMAGE. 25113145Sdas */ 26113145Sdas 27113145Sdas#include <sys/cdefs.h> 28113145Sdas__FBSDID("$FreeBSD$"); 29113145Sdas 30113145Sdas#include <float.h> 31113145Sdas#include <inttypes.h> 32113145Sdas#include <limits.h> 33113145Sdas#include <math.h> 34113145Sdas#include <stdlib.h> 35113145Sdas#include "fpmath.h" 36113145Sdas#include "gdtoaimp.h" 37113145Sdas 38113145Sdas/* 39113145Sdas * ldtoa() is a wrapper for gdtoa() that makes it smell like dtoa(), 40113145Sdas * except that the floating point argument is passed by reference. 41113145Sdas * When dtoa() is passed a NaN or infinity, it sets expt to 9999. 42113145Sdas * However, a long double could have a valid exponent of 9999, so we 43113145Sdas * use INT_MAX in ldtoa() instead. 44113145Sdas */ 45113145Sdaschar * 46113145Sdas__ldtoa(long double *ld, int mode, int ndigits, int *decpt, int *sign, 47113145Sdas char **rve) 48113145Sdas{ 49174204Sdas FPI fpi = { 50113145Sdas LDBL_MANT_DIG, /* nbits */ 51113145Sdas LDBL_MIN_EXP - LDBL_MANT_DIG, /* emin */ 52113145Sdas LDBL_MAX_EXP - LDBL_MANT_DIG, /* emax */ 53174204Sdas FLT_ROUNDS, /* rounding */ 54113145Sdas#ifdef Sudden_Underflow /* unused, but correct anyway */ 55113145Sdas 1 56113145Sdas#else 57113145Sdas 0 58113145Sdas#endif 59113145Sdas }; 60113145Sdas int be, kind; 61113145Sdas char *ret; 62113145Sdas union IEEEl2bits u; 63113145Sdas uint32_t bits[(LDBL_MANT_DIG + 31) / 32]; 64173793Sjb void *vbits = bits; 65113145Sdas 66113145Sdas u.e = *ld; 67174204Sdas 68174204Sdas /* 69174204Sdas * gdtoa doesn't know anything about the sign of the number, so 70174204Sdas * if the number is negative, we need to swap rounding modes of 71174204Sdas * 2 (upwards) and 3 (downwards). 72174204Sdas */ 73113145Sdas *sign = u.bits.sign; 74174204Sdas fpi.rounding ^= (fpi.rounding >> 1) & u.bits.sign; 75174204Sdas 76113145Sdas be = u.bits.exp - (LDBL_MAX_EXP - 1) - (LDBL_MANT_DIG - 1); 77113145Sdas LDBL_TO_ARRAY32(u, bits); 78113145Sdas 79113145Sdas switch (fpclassify(u.e)) { 80113145Sdas case FP_NORMAL: 81113145Sdas kind = STRTOG_Normal; 82113145Sdas#ifdef LDBL_IMPLICIT_NBIT 83113145Sdas bits[LDBL_MANT_DIG / 32] |= 1 << ((LDBL_MANT_DIG - 1) % 32); 84113145Sdas#endif /* LDBL_IMPLICIT_NBIT */ 85113145Sdas break; 86113145Sdas case FP_ZERO: 87113145Sdas kind = STRTOG_Zero; 88113145Sdas break; 89113145Sdas case FP_SUBNORMAL: 90113145Sdas kind = STRTOG_Denormal; 91124652Sdas be++; 92113145Sdas break; 93113145Sdas case FP_INFINITE: 94113145Sdas kind = STRTOG_Infinite; 95113145Sdas break; 96113145Sdas case FP_NAN: 97113145Sdas kind = STRTOG_NaN; 98113145Sdas break; 99113145Sdas default: 100113145Sdas abort(); 101113145Sdas } 102113145Sdas 103173793Sjb ret = gdtoa(&fpi, be, vbits, &kind, mode, ndigits, decpt, rve); 104113145Sdas if (*decpt == -32768) 105113145Sdas *decpt = INT_MAX; 106113145Sdas return ret; 107113145Sdas} 108