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