xref: /freebsd/lib/libc/gdtoa/_ldtoa.c (revision d915a14e)
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