g_ddfmt.c revision 165743
1112158Sdas/****************************************************************
2112158Sdas
3112158SdasThe author of this software is David M. Gay.
4112158Sdas
5112158SdasCopyright (C) 1998 by Lucent Technologies
6112158SdasAll Rights Reserved
7112158Sdas
8112158SdasPermission to use, copy, modify, and distribute this software and
9112158Sdasits documentation for any purpose and without fee is hereby
10112158Sdasgranted, provided that the above copyright notice appear in all
11112158Sdascopies and that both that the copyright notice and this
12112158Sdaspermission notice and warranty disclaimer appear in supporting
13112158Sdasdocumentation, and that the name of Lucent or any of its entities
14112158Sdasnot be used in advertising or publicity pertaining to
15112158Sdasdistribution of the software without specific, written prior
16112158Sdaspermission.
17112158Sdas
18112158SdasLUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
19112158SdasINCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
20112158SdasIN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
21112158SdasSPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
22112158SdasWHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
23112158SdasIN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
24112158SdasARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
25112158SdasTHIS SOFTWARE.
26112158Sdas
27112158Sdas****************************************************************/
28112158Sdas
29165743Sdas/* Please send bug reports to David M. Gay (dmg@acm.org). */
30112158Sdas
31112158Sdas#include "gdtoaimp.h"
32112158Sdas#include <string.h>
33112158Sdas
34112158Sdas char *
35112158Sdas#ifdef KR_headers
36112158Sdasg_ddfmt(buf, dd, ndig, bufsize) char *buf; double *dd; int ndig; unsigned bufsize;
37112158Sdas#else
38112158Sdasg_ddfmt(char *buf, double *dd, int ndig, unsigned bufsize)
39112158Sdas#endif
40112158Sdas{
41112158Sdas	FPI fpi;
42112158Sdas	char *b, *s, *se;
43112158Sdas	ULong *L, bits0[4], *bits, *zx;
44112158Sdas	int bx, by, decpt, ex, ey, i, j, mode;
45112158Sdas	Bigint *x, *y, *z;
46112158Sdas	double ddx[2];
47112158Sdas
48112158Sdas	if (bufsize < 10 || bufsize < ndig + 8)
49112158Sdas		return 0;
50112158Sdas
51112158Sdas	L = (ULong*)dd;
52112158Sdas	if ((L[_0] & 0x7ff00000L) == 0x7ff00000L) {
53112158Sdas		/* Infinity or NaN */
54112158Sdas		if (L[_0] & 0xfffff || L[_1]) {
55112158Sdas nanret:
56112158Sdas			return strcp(buf, "NaN");
57112158Sdas			}
58112158Sdas		if ((L[2+_0] & 0x7ff00000) == 0x7ff00000) {
59112158Sdas			if (L[2+_0] & 0xfffff || L[2+_1])
60112158Sdas				goto nanret;
61112158Sdas			if ((L[_0] ^ L[2+_0]) & 0x80000000L)
62112158Sdas				goto nanret;	/* Infinity - Infinity */
63112158Sdas			}
64112158Sdas infret:
65112158Sdas		b = buf;
66112158Sdas		if (L[_0] & 0x80000000L)
67112158Sdas			*b++ = '-';
68112158Sdas		return strcp(b, "Infinity");
69112158Sdas		}
70112158Sdas	if ((L[2+_0] & 0x7ff00000) == 0x7ff00000) {
71112158Sdas		L += 2;
72112158Sdas		if (L[_0] & 0xfffff || L[_1])
73112158Sdas			goto nanret;
74112158Sdas		goto infret;
75112158Sdas		}
76112158Sdas	if (dd[0] + dd[1] == 0.) {
77112158Sdas		b = buf;
78112158Sdas#ifndef IGNORE_ZERO_SIGN
79112158Sdas		if (L[_0] & L[2+_0] & 0x80000000L)
80112158Sdas			*b++ = '-';
81112158Sdas#endif
82112158Sdas		*b++ = '0';
83112158Sdas		*b = 0;
84112158Sdas		return b;
85112158Sdas		}
86112158Sdas	if ((L[_0] & 0x7ff00000L) < (L[2+_0] & 0x7ff00000L)) {
87112158Sdas		ddx[1] = dd[0];
88112158Sdas		ddx[0] = dd[1];
89112158Sdas		dd = ddx;
90112158Sdas		L = (ULong*)dd;
91112158Sdas		}
92112158Sdas	z = d2b(dd[0], &ex, &bx);
93112158Sdas	if (dd[1] == 0.)
94112158Sdas		goto no_y;
95112158Sdas	x = z;
96112158Sdas	y = d2b(dd[1], &ey, &by);
97112158Sdas	if ( (i = ex - ey) !=0) {
98112158Sdas		if (i > 0) {
99112158Sdas			x = lshift(x, i);
100112158Sdas			ex = ey;
101112158Sdas			}
102112158Sdas		else
103112158Sdas			y = lshift(y, -i);
104112158Sdas		}
105112158Sdas	if ((L[_0] ^ L[2+_0]) & 0x80000000L) {
106112158Sdas		z = diff(x, y);
107112158Sdas		if (L[_0] & 0x80000000L)
108112158Sdas			z->sign = 1 - z->sign;
109112158Sdas		}
110112158Sdas	else {
111112158Sdas		z = sum(x, y);
112112158Sdas		if (L[_0] & 0x80000000L)
113112158Sdas			z->sign = 1;
114112158Sdas		}
115112158Sdas	Bfree(x);
116112158Sdas	Bfree(y);
117112158Sdas no_y:
118112158Sdas	bits = zx = z->x;
119112158Sdas	for(i = 0; !*zx; zx++)
120112158Sdas		i += 32;
121112158Sdas	i += lo0bits(zx);
122112158Sdas	if (i) {
123112158Sdas		rshift(z, i);
124112158Sdas		ex += i;
125112158Sdas		}
126112158Sdas	fpi.nbits = z->wds * 32 - hi0bits(z->x[j = z->wds-1]);
127112158Sdas	if (fpi.nbits < 106) {
128112158Sdas		fpi.nbits = 106;
129112158Sdas		if (j < 3) {
130112158Sdas			for(i = 0; i <= j; i++)
131112158Sdas				bits0[i] = bits[i];
132112158Sdas			while(i < 4)
133112158Sdas				bits0[i++] = 0;
134112158Sdas			bits = bits0;
135112158Sdas			}
136112158Sdas		}
137112158Sdas	mode = 2;
138112158Sdas	if (ndig <= 0) {
139112158Sdas		if (bufsize < (int)(fpi.nbits * .301029995664) + 10) {
140112158Sdas			Bfree(z);
141112158Sdas			return 0;
142112158Sdas			}
143112158Sdas		mode = 0;
144112158Sdas		}
145112158Sdas	fpi.emin = 1-1023-53+1;
146112158Sdas	fpi.emax = 2046-1023-106+1;
147112158Sdas	fpi.rounding = FPI_Round_near;
148112158Sdas	fpi.sudden_underflow = 0;
149112158Sdas	i = STRTOG_Normal;
150112158Sdas	s = gdtoa(&fpi, ex, bits, &i, mode, ndig, &decpt, &se);
151112158Sdas	b = g__fmt(buf, s, se, decpt, z->sign);
152112158Sdas	Bfree(z);
153112158Sdas	return b;
154112158Sdas	}
155