xref: /minix3/lib/libc/gdtoa/test/dt.c (revision f14fb602092e015ff630df58e17c2a9cd57d29b3)
1 /****************************************************************
2 
3 The author of this software is David M. Gay.
4 
5 Copyright (C) 1998 by Lucent Technologies
6 All Rights Reserved
7 
8 Permission to use, copy, modify, and distribute this software and
9 its documentation for any purpose and without fee is hereby
10 granted, provided that the above copyright notice appear in all
11 copies and that both that the copyright notice and this
12 permission notice and warranty disclaimer appear in supporting
13 documentation, and that the name of Lucent or any of its entities
14 not be used in advertising or publicity pertaining to
15 distribution of the software without specific, written prior
16 permission.
17 
18 LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
19 INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
20 IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
21 SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
22 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
23 IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
24 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
25 THIS SOFTWARE.
26 
27 ****************************************************************/
28 
29 /* Please send bug reports to David M. Gay (dmg at acm dot org,
30  * with " at " changed at "@" and " dot " changed to ".").	*/
31 
32 /* Test program for strtod and dtoa.
33  *
34  * Inputs (on stdin):
35  *		number[: mode [ndigits]]
36  * or
37  *		#hex0 hex1[: mode [ndigits]]
38  * where number is a decimal floating-point number,
39  * hex0 is a string of Hex digits for the most significant
40  * word of the number, hex1 is a similar string for the other
41  * (least significant) word, and mode and ndigits are
42  * parameters to dtoa.
43  */
44 
45 #include <stdio.h>
46 #include "gdtoa.h"
47 int STRTOD_DIGLIM = 24;
48 #ifdef KR_headers
49 #define Void /*void*/
50 #else
51 #define Void void
52 #endif
53 
54 #ifdef __STDC__
55 #include <stdlib.h>
56 #else
57 #ifdef __cplusplus
58 extern "C" double atof(const char*);
59 #else
60 extern double atof ANSI((char*));
61 #endif
62 #endif
63 
64 typedef union { double d; ULong L[2]; } U;
65 
66 #ifdef IEEE_8087
67 #define word0(x) (x)->L[1]
68 #define word1(x) (x)->L[0]
69 #else
70 #define word0(x) (x)->L[0]
71 #define word1(x) (x)->L[1]
72 #endif
73 #define dval(x) (x)->d
74 
75 #include "errno.h"
76 
77 #ifdef __cplusplus
78 extern "C" char *dtoa(double, int, int, int*, int*, char **);
79 #else
80 extern char *dtoa ANSI((double, int, int, int*, int*, char **));
81 #endif
82 
83  static void
84 #ifdef KR_headers
g_fmt(b,x)85 g_fmt(b, x) char *b; double x;
86 #else
87 g_fmt(char *b, double x)
88 #endif
89 {
90 	char *s, *se;
91 	int decpt, i, j, k, sign;
92 
93 	if (!x) {
94 		*b++ = '0';
95 		*b = 0;
96 		return;
97 		}
98 	s = dtoa(x, 0, 0, &decpt, &sign, &se);
99 	if (sign)
100 		*b++ = '-';
101 	if (decpt == 9999) /* Infinity or Nan */ {
102 		while((*b++ = *s++));
103 		return;
104 		}
105 	if (decpt <= -4 || decpt > se - s + 5) {
106 		*b++ = *s++;
107 		if (*s) {
108 			*b++ = '.';
109 			while((*b = *s++))
110 				b++;
111 			}
112 		*b++ = 'e';
113 		/* sprintf(b, "%+.2d", decpt - 1); */
114 		if (--decpt < 0) {
115 			*b++ = '-';
116 			decpt = -decpt;
117 			}
118 		else
119 			*b++ = '+';
120 		for(j = 2, k = 10; 10*k <= decpt; j++, k *= 10){};
121 		for(;;) {
122 			i = decpt / k;
123 			*b++ = i + '0';
124 			if (--j <= 0)
125 				break;
126 			decpt -= i*k;
127 			decpt *= 10;
128 			}
129 		*b = 0;
130 		}
131 	else if (decpt <= 0) {
132 		*b++ = '.';
133 		for(; decpt < 0; decpt++)
134 			*b++ = '0';
135 		while((*b++ = *s++));
136 		}
137 	else {
138 		while((*b = *s++)) {
139 			b++;
140 			if (--decpt == 0 && *s)
141 				*b++ = '.';
142 			}
143 		for(; decpt > 0; decpt--)
144 			*b++ = '0';
145 		*b = 0;
146 		}
147 	}
148 
149  static void
baderrno(Void)150 baderrno(Void)
151 {
152 	fflush(stdout);
153 	perror("\nerrno strtod");
154 	fflush(stderr);
155 	}
156 
157 #define UL (unsigned long)
158 
159  static void
160 #ifdef KR_headers
check(d)161 check(d) U *d;
162 #else
163 check(U *d)
164 #endif
165 {
166 	char buf[64];
167 	int decpt, sign;
168 	char *s, *se;
169 	U d1;
170 
171 	s = dtoa(dval(d), 0, 0, &decpt, &sign, &se);
172 	sprintf(buf, "%s%s%se%d", sign ? "-" : "",
173 		decpt == 9999 ? "" : ".", s, decpt);
174 	errno = 0;
175 	dval(&d1) = strtod(buf, (char **)0);
176 	if (errno)
177 		baderrno();
178 	if (dval(d) != dval(&d1)) {
179 		printf("sent d = %.17g = 0x%lx %lx, buf = %s\n",
180 			dval(d), UL word0(d), UL word1(d), buf);
181 		printf("got d1 = %.17g = 0x%lx %lx\n",
182 			dval(&d1), UL word0(&d1), UL word1(&d1));
183 		}
184 	}
185 
186  int
main(Void)187 main(Void)
188 {
189 	U d, d1;
190 	char buf[2048], buf1[32];
191 	char *fmt, *s, *s1, *se;
192 	int decpt, sign;
193 	int mode = 0, ndigits = 17;
194 	ULong x, y;
195 #ifdef VAX
196 	ULong z;
197 #endif
198 
199 	while(fgets(buf, sizeof(buf), stdin)) {
200 		if (*buf == '*') {
201 			printf("%s", buf);
202 			continue;
203 			}
204 		printf("Input: %s", buf);
205 		if (*buf == '#') {
206 			x = word0(&d);
207 			y = word1(&d);
208 			/* sscanf(buf+1, "%lx %lx:%d %d", &x, &y, &mode, &ndigits); */
209 			x = (ULong)strtoul(s1 = buf+1, &se, 16);
210 			if (se > s1) {
211 				y = (ULong)strtoul(s1 = se, &se, 16);
212 				if (se > s1)
213 					sscanf(se, ":%d %d", &mode, &ndigits);
214 				}
215 			word0(&d) = x;
216 			word1(&d) = y;
217 			fmt = "Output: d =\n%.17g = 0x%lx %lx\n";
218 			}
219 		else if (*buf == '*') {
220 			x = strtoul(buf,&s,10);
221 			if (!*s && x > 18)
222 				STRTOD_DIGLIM = (int)x;
223 			printf("STRTOD_DIGLIM = %lu\n", UL x);
224 			continue;
225 			}
226 		else {
227 			errno = 0;
228 			dval(&d) = strtod(buf,&se);
229 			if (*se == ':')
230 				sscanf(se+1,"%d %d", &mode, &ndigits);
231 			dval(&d1) = atof(buf);
232 			fmt = "Output: d =\n%.17g = 0x%lx %lx, se = %s";
233 			if (errno)
234 				baderrno();
235 			}
236 		printf(fmt, dval(&d), UL word0(&d), UL word1(&d), se);
237 		g_fmt(buf1, dval(&d));
238 		printf("\tg_fmt gives \"%s\"\n", buf1);
239 		if (*buf != '#' && dval(&d) != dval(&d1))
240 			printf("atof gives\n\
241 	d1 = %.17g = 0x%lx %lx\nversus\n\
242 	d  = %.17g = 0x%lx %lx\n", dval(&d1), UL word0(&d1), UL word1(&d1),
243 				dval(&d), UL word0(&d), UL word1(&d));
244 		check(&d);
245 		s = dtoa(dval(&d), mode, ndigits, &decpt, &sign, &se);
246 		printf("\tdtoa(mode = %d, ndigits = %d):\n", mode, ndigits);
247 		printf("\tdtoa returns sign = %d, decpt = %d, %d digits:\n%s\n",
248 			sign, decpt, (int)(se-s), s);
249 		x = word1(&d);
250 		if (x != 0xffffffff
251 		 && (word0(&d) & 0x7ff00000) != 0x7ff00000) {
252 #ifdef VAX
253 			z = x << 16 | x >> 16;
254 			z++;
255 			z = z << 16 | z >> 16;
256 			word1(&d) = z;
257 #else
258 			word1(&d) = x + 1;
259 #endif
260 			printf("\tnextafter(d,+Inf) = %.17g = 0x%lx %lx:\n",
261 				dval(&d), UL word0(&d), UL word1(&d));
262 			g_fmt(buf1, dval(&d));
263 			printf("\tg_fmt gives \"%s\"\n", buf1);
264 			s = dtoa(dval(&d), mode, ndigits, &decpt, &sign, &se);
265 			printf(
266 		"\tdtoa returns sign = %d, decpt = %d, %d digits:\n%s\n",
267 				sign, decpt, (int)(se-s), s);
268 			check(&d);
269 			}
270 		if (x) {
271 #ifdef VAX
272 			z = x << 16 | x >> 16;
273 			z--;
274 			z = z << 16 | z >> 16;
275 			word1(&d) = z;
276 #else
277 			word1(&d) = x - 1;
278 #endif
279 			printf("\tnextafter(d,-Inf) = %.17g = 0x%lx %lx:\n",
280 				dval(&d), UL word0(&d), UL word1(&d));
281 			g_fmt(buf1, dval(&d));
282 			printf("\tg_fmt gives \"%s\"\n", buf1);
283 			s = dtoa(dval(&d), mode, ndigits, &decpt, &sign, &se);
284 			printf(
285 		"\tdtoa returns sign = %d, decpt = %d, %d digits:\n%s\n",
286 				sign, decpt, (int)(se-s), s);
287 			check(&d);
288 			}
289 		}
290 	return 0;
291 	}
292