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