_ldtoa.c revision 256281
150472Speter/*- 237Srgrimes * Copyright (c) 2003 David Schultz <das@FreeBSD.ORG> 378822Snik * All rights reserved. 450203Srgrimes * 537Srgrimes * Redistribution and use in source and binary forms, with or without 639161Sobrien * modification, are permitted provided that the following conditions 739490Sobrien * are met: 88571Srgrimes * 1. Redistributions of source code must retain the above copyright 92878Srgrimes * notice, this list of conditions and the following disclaimer. 1072515Sru * 2. Redistributions in binary form must reproduce the above copyright 1172515Sru * notice, this list of conditions and the following disclaimer in the 128571Srgrimes * documentation and/or other materials provided with the distribution. 132878Srgrimes * 148571Srgrimes * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 158571Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1672515Sru * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 172878Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 1872515Sru * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 1972515Sru * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 202878Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2172515Sru * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 222878Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2372515Sru * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2472515Sru * SUCH DAMAGE. 252878Srgrimes */ 262878Srgrimes 2772515Sru#include <sys/cdefs.h> 2872515Sru__FBSDID("$FreeBSD: stable/10/lib/libc/gdtoa/_ldtoa.c 174488 2007-12-09 19:48:57Z das $"); 2972515Sru 3045173Sasami#include <float.h> 3186601Sru#include <inttypes.h> 3285220Sdarrenr#include <limits.h> 3372515Sru#include <math.h> 3472515Sru#include <stdlib.h> 352878Srgrimes#include "fpmath.h" 3698883Ssheldonh#include "gdtoaimp.h" 3798699Sdes 38106403Smarkm/* 39106403Smarkm * ldtoa() is a wrapper for gdtoa() that makes it smell like dtoa(), 40106403Smarkm * except that the floating point argument is passed by reference. 4186601Sru * When dtoa() is passed a NaN or infinity, it sets expt to 9999. 4285484Sru * However, a long double could have a valid exponent of 9999, so we 4380516Smarkm * use INT_MAX in ldtoa() instead. 4439490Sobrien */ 452878Srgrimeschar * 4686601Sru__ldtoa(long double *ld, int mode, int ndigits, int *decpt, int *sign, 472878Srgrimes char **rve) 4812388Sache{ 492878Srgrimes FPI fpi = { 5039490Sobrien LDBL_MANT_DIG, /* nbits */ 512878Srgrimes LDBL_MIN_EXP - LDBL_MANT_DIG, /* emin */ 5239490Sobrien LDBL_MAX_EXP - LDBL_MANT_DIG, /* emax */ 5382191Skuriyama FLT_ROUNDS, /* rounding */ 5482191Skuriyama#ifdef Sudden_Underflow /* unused, but correct anyway */ 5585848Scjc 1 5685916Scjc#else 572878Srgrimes 0 5886601Sru#endif 592878Srgrimes }; 6072515Sru int be, kind; 6186601Sru char *ret; 622878Srgrimes union IEEEl2bits u; 6372515Sru uint32_t bits[(LDBL_MANT_DIG + 31) / 32]; 6441855Speter void *vbits = bits; 652878Srgrimes 6641855Speter u.e = *ld; 672878Srgrimes 6850296Srgrimes /* 6950296Srgrimes * gdtoa doesn't know anything about the sign of the number, so 7041855Speter * if the number is negative, we need to swap rounding modes of 7150296Srgrimes * 2 (upwards) and 3 (downwards). 7250296Srgrimes */ 732878Srgrimes *sign = u.bits.sign; 7486601Sru fpi.rounding ^= (fpi.rounding >> 1) & u.bits.sign; 752878Srgrimes 7672515Sru be = u.bits.exp - (LDBL_MAX_EXP - 1) - (LDBL_MANT_DIG - 1); 7772515Sru LDBL_TO_ARRAY32(u, bits); 788571Srgrimes 792878Srgrimes switch (fpclassify(u.e)) { 8041855Speter case FP_NORMAL: 818571Srgrimes kind = STRTOG_Normal; 82949Snate#ifdef LDBL_IMPLICIT_NBIT 83 bits[LDBL_MANT_DIG / 32] |= 1 << ((LDBL_MANT_DIG - 1) % 32); 84#endif /* LDBL_IMPLICIT_NBIT */ 85 break; 86 case FP_ZERO: 87 kind = STRTOG_Zero; 88 break; 89 case FP_SUBNORMAL: 90 kind = STRTOG_Denormal; 91 be++; 92 break; 93 case FP_INFINITE: 94 kind = STRTOG_Infinite; 95 break; 96 case FP_NAN: 97 kind = STRTOG_NaN; 98 break; 99 default: 100 abort(); 101 } 102 103 ret = gdtoa(&fpi, be, vbits, &kind, mode, ndigits, decpt, rve); 104 if (*decpt == -32768) 105 *decpt = INT_MAX; 106 return ret; 107} 108