xref: /freebsd/lib/libc/gdtoa/_ldtoa.c (revision 559a218c)
192b93b37SDavid Schultz /*-
24d846d26SWarner Losh  * SPDX-License-Identifier: BSD-2-Clause
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 <float.h>
3092b93b37SDavid Schultz #include <inttypes.h>
3192b93b37SDavid Schultz #include <limits.h>
3292b93b37SDavid Schultz #include <math.h>
3392b93b37SDavid Schultz #include <stdlib.h>
34f8af09cdSCraig Rodrigues #include "../stdio/floatio.h"
3592b93b37SDavid Schultz #include "fpmath.h"
3692b93b37SDavid Schultz #include "gdtoaimp.h"
3792b93b37SDavid Schultz 
3892b93b37SDavid Schultz /*
3992b93b37SDavid Schultz  * ldtoa() is a wrapper for gdtoa() that makes it smell like dtoa(),
4092b93b37SDavid Schultz  * except that the floating point argument is passed by reference.
4192b93b37SDavid Schultz  * When dtoa() is passed a NaN or infinity, it sets expt to 9999.
4292b93b37SDavid Schultz  * However, a long double could have a valid exponent of 9999, so we
4392b93b37SDavid Schultz  * use INT_MAX in ldtoa() instead.
4492b93b37SDavid Schultz  */
4592b93b37SDavid Schultz char *
__ldtoa(long double * ld,int mode,int ndigits,int * decpt,int * sign,char ** rve)4692b93b37SDavid Schultz __ldtoa(long double *ld, int mode, int ndigits, int *decpt, int *sign,
4792b93b37SDavid Schultz     char **rve)
4892b93b37SDavid Schultz {
499c90f85aSDavid Schultz 	FPI fpi = {
5092b93b37SDavid Schultz 		LDBL_MANT_DIG,			/* nbits */
5192b93b37SDavid Schultz 		LDBL_MIN_EXP - LDBL_MANT_DIG,	/* emin */
5292b93b37SDavid Schultz 		LDBL_MAX_EXP - LDBL_MANT_DIG,	/* emax */
539c90f85aSDavid Schultz 		FLT_ROUNDS,	       		/* rounding */
5492b93b37SDavid Schultz #ifdef Sudden_Underflow	/* unused, but correct anyway */
5592b93b37SDavid Schultz 		1
5692b93b37SDavid Schultz #else
5792b93b37SDavid Schultz 		0
5892b93b37SDavid Schultz #endif
5992b93b37SDavid Schultz 	};
6092b93b37SDavid Schultz 	int be, kind;
6192b93b37SDavid Schultz 	char *ret;
6292b93b37SDavid Schultz 	union IEEEl2bits u;
6392b93b37SDavid Schultz 	uint32_t bits[(LDBL_MANT_DIG + 31) / 32];
643e636fa0SJohn Birrell 	void *vbits = bits;
6592b93b37SDavid Schultz 
6692b93b37SDavid Schultz 	u.e = *ld;
679c90f85aSDavid Schultz 
689c90f85aSDavid Schultz 	/*
699c90f85aSDavid Schultz 	 * gdtoa doesn't know anything about the sign of the number, so
709c90f85aSDavid Schultz 	 * if the number is negative, we need to swap rounding modes of
719c90f85aSDavid Schultz 	 * 2 (upwards) and 3 (downwards).
729c90f85aSDavid Schultz 	 */
7392b93b37SDavid Schultz 	*sign = u.bits.sign;
749c90f85aSDavid Schultz 	fpi.rounding ^= (fpi.rounding >> 1) & u.bits.sign;
759c90f85aSDavid Schultz 
7692b93b37SDavid Schultz 	be = u.bits.exp - (LDBL_MAX_EXP - 1) - (LDBL_MANT_DIG - 1);
7792b93b37SDavid Schultz 	LDBL_TO_ARRAY32(u, bits);
7892b93b37SDavid Schultz 
7992b93b37SDavid Schultz 	switch (fpclassify(u.e)) {
8092b93b37SDavid Schultz 	case FP_NORMAL:
8192b93b37SDavid Schultz 		kind = STRTOG_Normal;
8292b93b37SDavid Schultz #ifdef	LDBL_IMPLICIT_NBIT
8392b93b37SDavid Schultz 		bits[LDBL_MANT_DIG / 32] |= 1 << ((LDBL_MANT_DIG - 1) % 32);
8492b93b37SDavid Schultz #endif /* LDBL_IMPLICIT_NBIT */
8592b93b37SDavid Schultz 		break;
8692b93b37SDavid Schultz 	case FP_ZERO:
8792b93b37SDavid Schultz 		kind = STRTOG_Zero;
8892b93b37SDavid Schultz 		break;
8992b93b37SDavid Schultz 	case FP_SUBNORMAL:
9092b93b37SDavid Schultz 		kind = STRTOG_Denormal;
91d784b0c3SDavid Schultz 		be++;
9292b93b37SDavid Schultz 		break;
9392b93b37SDavid Schultz 	case FP_INFINITE:
9492b93b37SDavid Schultz 		kind = STRTOG_Infinite;
9592b93b37SDavid Schultz 		break;
9692b93b37SDavid Schultz 	case FP_NAN:
9792b93b37SDavid Schultz 		kind = STRTOG_NaN;
9892b93b37SDavid Schultz 		break;
9992b93b37SDavid Schultz 	default:
10092b93b37SDavid Schultz 		abort();
10192b93b37SDavid Schultz 	}
10292b93b37SDavid Schultz 
1033e636fa0SJohn Birrell 	ret = gdtoa(&fpi, be, vbits, &kind, mode, ndigits, decpt, rve);
10492b93b37SDavid Schultz 	if (*decpt == -32768)
10592b93b37SDavid Schultz 		*decpt = INT_MAX;
10692b93b37SDavid Schultz 	return ret;
10792b93b37SDavid Schultz }
108