1/**************************************************************** 2 3The author of this software is David M. Gay. 4 5Copyright (C) 1998 by Lucent Technologies 6All Rights Reserved 7 8Permission to use, copy, modify, and distribute this software and 9its documentation for any purpose and without fee is hereby 10granted, provided that the above copyright notice appear in all 11copies and that both that the copyright notice and this 12permission notice and warranty disclaimer appear in supporting 13documentation, and that the name of Lucent or any of its entities 14not be used in advertising or publicity pertaining to 15distribution of the software without specific, written prior 16permission. 17 18LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 19INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. 20IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY 21SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 22WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER 23IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 24ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF 25THIS 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" 47int 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 58extern "C" double atof(const char*); 59#else 60extern double atof ANSI((char*)); 61#endif 62#endif 63 64typedef 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 78extern "C" char *dtoa(double, int, int, int*, int*, char **); 79#else 80extern char *dtoa ANSI((double, int, int, int*, int*, char **)); 81#endif 82 83 static void 84#ifdef KR_headers 85g_fmt(b, x) char *b; double x; 86#else 87g_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 150baderrno(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 161check(d) U *d; 162#else 163check(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 187main(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