| 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
|
|---|
| 30 | David M. Gay
|
|---|
| 31 | Bell Laboratories, Room 2C-463
|
|---|
| 32 | 600 Mountain Avenue
|
|---|
| 33 | Murray Hill, NJ 07974-0636
|
|---|
| 34 | U.S.A.
|
|---|
| 35 | dmg@bell-labs.com
|
|---|
| 36 | */
|
|---|
| 37 |
|
|---|
| 38 | /* Test program for strtod and dtoa.
|
|---|
| 39 | *
|
|---|
| 40 | * Inputs (on stdin):
|
|---|
| 41 | * number[: mode [ndigits]]
|
|---|
| 42 | * or
|
|---|
| 43 | * #hex0 hex1[: mode [ndigits]]
|
|---|
| 44 | * where number is a decimal floating-point number,
|
|---|
| 45 | * hex0 is a string of Hex digits for the most significant
|
|---|
| 46 | * word of the number, hex1 is a similar string for the other
|
|---|
| 47 | * (least significant) word, and mode and ndigits are
|
|---|
| 48 | * parameters to dtoa.
|
|---|
| 49 | */
|
|---|
| 50 |
|
|---|
| 51 | #include <stdio.h>
|
|---|
| 52 | #include "gdtoa.h"
|
|---|
| 53 | #ifdef KR_headers
|
|---|
| 54 | #define Void /*void*/
|
|---|
| 55 | #else
|
|---|
| 56 | #define Void void
|
|---|
| 57 | #endif
|
|---|
| 58 |
|
|---|
| 59 | #ifdef __STDC__
|
|---|
| 60 | #include <stdlib.h>
|
|---|
| 61 | #else
|
|---|
| 62 | #ifdef __cplusplus
|
|---|
| 63 | extern "C" double atof(const char*);
|
|---|
| 64 | #else
|
|---|
| 65 | extern double atof ANSI((char*));
|
|---|
| 66 | #endif
|
|---|
| 67 | #endif
|
|---|
| 68 | #ifdef IEEE_8087
|
|---|
| 69 | #define word0(x) ((ULong *)&x)[1]
|
|---|
| 70 | #define word1(x) ((ULong *)&x)[0]
|
|---|
| 71 | #else
|
|---|
| 72 | #define word0(x) ((ULong *)&x)[0]
|
|---|
| 73 | #define word1(x) ((ULong *)&x)[1]
|
|---|
| 74 | #endif
|
|---|
| 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
|
|---|
| 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
|
|---|
| 150 | baderrno(Void)
|
|---|
| 151 | {
|
|---|
| 152 | fflush(stdout);
|
|---|
| 153 | perror("\nerrno strtod");
|
|---|
| 154 | fflush(stderr);
|
|---|
| 155 | }
|
|---|
| 156 |
|
|---|
| 157 | #define U (unsigned long)
|
|---|
| 158 |
|
|---|
| 159 | static void
|
|---|
| 160 | #ifdef KR_headers
|
|---|
| 161 | check(d) double d;
|
|---|
| 162 | #else
|
|---|
| 163 | check(double d)
|
|---|
| 164 | #endif
|
|---|
| 165 | {
|
|---|
| 166 | char buf[64];
|
|---|
| 167 | int decpt, sign;
|
|---|
| 168 | char *s, *se;
|
|---|
| 169 | double d1;
|
|---|
| 170 |
|
|---|
| 171 | s = dtoa(d, 0, 0, &decpt, &sign, &se);
|
|---|
| 172 | sprintf(buf, "%s.%se%d", sign ? "-" : "", s, decpt);
|
|---|
| 173 | errno = 0;
|
|---|
| 174 | d1 = strtod(buf, (char **)0);
|
|---|
| 175 | if (errno)
|
|---|
| 176 | baderrno();
|
|---|
| 177 | if (d != d1) {
|
|---|
| 178 | printf("sent d = %.17g = 0x%lx %lx, buf = %s\n",
|
|---|
| 179 | d, U word0(d), U word1(d), buf);
|
|---|
| 180 | printf("got d1 = %.17g = 0x%lx %lx\n",
|
|---|
| 181 | d1, U word0(d1), U word1(d1));
|
|---|
| 182 | }
|
|---|
| 183 | }
|
|---|
| 184 |
|
|---|
| 185 | main(Void){
|
|---|
| 186 | char buf[2048], buf1[32];
|
|---|
| 187 | char *fmt, *s, *se;
|
|---|
| 188 | double d, d1;
|
|---|
| 189 | int decpt, sign;
|
|---|
| 190 | int mode = 0, ndigits = 17;
|
|---|
| 191 | ULong x, y;
|
|---|
| 192 | #ifdef VAX
|
|---|
| 193 | ULong z;
|
|---|
| 194 | #endif
|
|---|
| 195 |
|
|---|
| 196 | while(fgets(buf, sizeof(buf), stdin)) {
|
|---|
| 197 | if (*buf == '*') {
|
|---|
| 198 | printf("%s", buf);
|
|---|
| 199 | continue;
|
|---|
| 200 | }
|
|---|
| 201 | printf("Input: %s", buf);
|
|---|
| 202 | if (*buf == '#') {
|
|---|
| 203 | x = word0(d);
|
|---|
| 204 | y = word1(d);
|
|---|
| 205 | sscanf(buf+1, "%lx %lx:%d %d", &x, &y, &mode, &ndigits);
|
|---|
| 206 | word0(d) = x;
|
|---|
| 207 | word1(d) = y;
|
|---|
| 208 | fmt = "Output: d =\n%.17g = 0x%lx %lx\n";
|
|---|
| 209 | }
|
|---|
| 210 | else {
|
|---|
| 211 | errno = 0;
|
|---|
| 212 | d = strtod(buf,&se);
|
|---|
| 213 | if (*se == ':')
|
|---|
| 214 | sscanf(se+1,"%d %d", &mode, &ndigits);
|
|---|
| 215 | d1 = atof(buf);
|
|---|
| 216 | fmt = "Output: d =\n%.17g = 0x%lx %lx, se = %s";
|
|---|
| 217 | if (errno)
|
|---|
| 218 | baderrno();
|
|---|
| 219 | }
|
|---|
| 220 | printf(fmt, d, U word0(d), U word1(d), se);
|
|---|
| 221 | g_fmt(buf1, d);
|
|---|
| 222 | printf("\tg_fmt gives \"%s\"\n", buf1);
|
|---|
| 223 | if (*buf != '#' && d != d1)
|
|---|
| 224 | printf("atof gives\n\
|
|---|
| 225 | d1 = %.17g = 0x%lx %lx\nversus\n\
|
|---|
| 226 | d = %.17g = 0x%lx %lx\n", d1, U word0(d1), U word1(d1),
|
|---|
| 227 | d, U word0(d), U word1(d));
|
|---|
| 228 | check(d);
|
|---|
| 229 | s = dtoa(d, mode, ndigits, &decpt, &sign, &se);
|
|---|
| 230 | printf("\tdtoa(mode = %d, ndigits = %d):\n", mode, ndigits);
|
|---|
| 231 | printf("\tdtoa returns sign = %d, decpt = %d, %d digits:\n%s\n",
|
|---|
| 232 | sign, decpt, se-s, s);
|
|---|
| 233 | x = word1(d);
|
|---|
| 234 | if (x != 0xffffffff
|
|---|
| 235 | && (word0(d) & 0x7ff00000) != 0x7ff00000) {
|
|---|
| 236 | #ifdef VAX
|
|---|
| 237 | z = x << 16 | x >> 16;
|
|---|
| 238 | z++;
|
|---|
| 239 | z = z << 16 | z >> 16;
|
|---|
| 240 | word1(d) = z;
|
|---|
| 241 | #else
|
|---|
| 242 | word1(d) = x + 1;
|
|---|
| 243 | #endif
|
|---|
| 244 | printf("\tnextafter(d,+Inf) = %.17g = 0x%lx %lx:\n",
|
|---|
| 245 | d, U word0(d), U word1(d));
|
|---|
| 246 | g_fmt(buf1, d);
|
|---|
| 247 | printf("\tg_fmt gives \"%s\"\n", buf1);
|
|---|
| 248 | s = dtoa(d, mode, ndigits, &decpt, &sign, &se);
|
|---|
| 249 | printf(
|
|---|
| 250 | "\tdtoa returns sign = %d, decpt = %d, %d digits:\n%s\n",
|
|---|
| 251 | sign, decpt, se-s, s);
|
|---|
| 252 | check(d);
|
|---|
| 253 | }
|
|---|
| 254 | if (x) {
|
|---|
| 255 | #ifdef VAX
|
|---|
| 256 | z = x << 16 | x >> 16;
|
|---|
| 257 | z--;
|
|---|
| 258 | z = z << 16 | z >> 16;
|
|---|
| 259 | word1(d) = z;
|
|---|
| 260 | #else
|
|---|
| 261 | word1(d) = x - 1;
|
|---|
| 262 | #endif
|
|---|
| 263 | printf("\tnextafter(d,-Inf) = %.17g = 0x%lx %lx:\n",
|
|---|
| 264 | d, U word0(d), U word1(d));
|
|---|
| 265 | g_fmt(buf1, d);
|
|---|
| 266 | printf("\tg_fmt gives \"%s\"\n", buf1);
|
|---|
| 267 | s = dtoa(d, mode, ndigits, &decpt, &sign, &se);
|
|---|
| 268 | printf(
|
|---|
| 269 | "\tdtoa returns sign = %d, decpt = %d, %d digits:\n%s\n",
|
|---|
| 270 | sign, decpt, se-s, s);
|
|---|
| 271 | check(d);
|
|---|
| 272 | }
|
|---|
| 273 | }
|
|---|
| 274 | return 0;
|
|---|
| 275 | }
|
|---|