xref: /netbsd-src/lib/libc/gdtoa/g_ddfmt.c (revision 8b0f9554ff8762542c4defc4f70e1eb76fb508fa)
1 /* $NetBSD: g_ddfmt.c,v 1.1.1.1 2006/01/25 15:18:44 kleink Exp $ */
2 
3 /****************************************************************
4 
5 The author of this software is David M. Gay.
6 
7 Copyright (C) 1998 by Lucent Technologies
8 All Rights Reserved
9 
10 Permission to use, copy, modify, and distribute this software and
11 its documentation for any purpose and without fee is hereby
12 granted, provided that the above copyright notice appear in all
13 copies and that both that the copyright notice and this
14 permission notice and warranty disclaimer appear in supporting
15 documentation, and that the name of Lucent or any of its entities
16 not be used in advertising or publicity pertaining to
17 distribution of the software without specific, written prior
18 permission.
19 
20 LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
21 INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
22 IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
23 SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
24 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
25 IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
26 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
27 THIS SOFTWARE.
28 
29 ****************************************************************/
30 
31 /* Please send bug reports to David M. Gay (dmg@acm.org). */
32 
33 #include "gdtoaimp.h"
34 #include <string.h>
35 
36  char *
37 #ifdef KR_headers
38 g_ddfmt(buf, dd, ndig, bufsize) char *buf; double *dd; int ndig; unsigned bufsize;
39 #else
40 g_ddfmt(char *buf, double *dd, int ndig, unsigned bufsize)
41 #endif
42 {
43 	FPI fpi;
44 	char *b, *s, *se;
45 	ULong *L, bits0[4], *bits, *zx;
46 	int bx, by, decpt, ex, ey, i, j, mode;
47 	Bigint *x, *y, *z;
48 	double ddx[2];
49 
50 	if (bufsize < 10 || bufsize < ndig + 8)
51 		return 0;
52 
53 	L = (ULong*)dd;
54 	if ((L[_0] & 0x7ff00000L) == 0x7ff00000L) {
55 		/* Infinity or NaN */
56 		if (L[_0] & 0xfffff || L[_1]) {
57  nanret:
58 			return strcp(buf, "NaN");
59 			}
60 		if ((L[2+_0] & 0x7ff00000) == 0x7ff00000) {
61 			if (L[2+_0] & 0xfffff || L[2+_1])
62 				goto nanret;
63 			if ((L[_0] ^ L[2+_0]) & 0x80000000L)
64 				goto nanret;	/* Infinity - Infinity */
65 			}
66  infret:
67 		b = buf;
68 		if (L[_0] & 0x80000000L)
69 			*b++ = '-';
70 		return strcp(b, "Infinity");
71 		}
72 	if ((L[2+_0] & 0x7ff00000) == 0x7ff00000) {
73 		L += 2;
74 		if (L[_0] & 0xfffff || L[_1])
75 			goto nanret;
76 		goto infret;
77 		}
78 	if (dd[0] + dd[1] == 0.) {
79 		b = buf;
80 #ifndef IGNORE_ZERO_SIGN
81 		if (L[_0] & L[2+_0] & 0x80000000L)
82 			*b++ = '-';
83 #endif
84 		*b++ = '0';
85 		*b = 0;
86 		return b;
87 		}
88 	if ((L[_0] & 0x7ff00000L) < (L[2+_0] & 0x7ff00000L)) {
89 		ddx[1] = dd[0];
90 		ddx[0] = dd[1];
91 		dd = ddx;
92 		L = (ULong*)dd;
93 		}
94 	z = d2b(dd[0], &ex, &bx);
95 	if (dd[1] == 0.)
96 		goto no_y;
97 	x = z;
98 	y = d2b(dd[1], &ey, &by);
99 	if ( (i = ex - ey) !=0) {
100 		if (i > 0) {
101 			x = lshift(x, i);
102 			ex = ey;
103 			}
104 		else
105 			y = lshift(y, -i);
106 		}
107 	if ((L[_0] ^ L[2+_0]) & 0x80000000L) {
108 		z = diff(x, y);
109 		if (L[_0] & 0x80000000L)
110 			z->sign = 1 - z->sign;
111 		}
112 	else {
113 		z = sum(x, y);
114 		if (L[_0] & 0x80000000L)
115 			z->sign = 1;
116 		}
117 	Bfree(x);
118 	Bfree(y);
119  no_y:
120 	bits = zx = z->x;
121 	for(i = 0; !*zx; zx++)
122 		i += 32;
123 	i += lo0bits(zx);
124 	if (i) {
125 		rshift(z, i);
126 		ex += i;
127 		}
128 	fpi.nbits = z->wds * 32 - hi0bits(z->x[j = z->wds-1]);
129 	if (fpi.nbits < 106) {
130 		fpi.nbits = 106;
131 		if (j < 3) {
132 			for(i = 0; i <= j; i++)
133 				bits0[i] = bits[i];
134 			while(i < 4)
135 				bits0[i++] = 0;
136 			bits = bits0;
137 			}
138 		}
139 	mode = 2;
140 	if (ndig <= 0) {
141 		if (bufsize < (int)(fpi.nbits * .301029995664) + 10) {
142 			Bfree(z);
143 			return 0;
144 			}
145 		mode = 0;
146 		}
147 	fpi.emin = 1-1023-53+1;
148 	fpi.emax = 2046-1023-106+1;
149 	fpi.rounding = FPI_Round_near;
150 	fpi.sudden_underflow = 0;
151 	i = STRTOG_Normal;
152 	s = gdtoa(&fpi, ex, bits, &i, mode, ndig, &decpt, &se);
153 	b = g__fmt(buf, s, se, decpt, z->sign);
154 	Bfree(z);
155 	return b;
156 	}
157