you make it right; I'll make it fast
David Hough
sun!Eng!dgh
Tue Jun 12 14:46:39 PDT 1990
The first order of business for me working at home
is to get my base conversion correctness program into distributable form.
Anyway I extracted some test cases that I found by running it on our M/2000
which has 2.0 compilers, and put them into this test program:
test(s)
char *s ;
{
double x,atof(),strtod();
int e ;
extern errno;
long unsigned * pl;
pl=(long unsigned *) &x;
errno=0;
x=atof(s);
e=errno;
printf(" atof x %g %8X %8X errno %d s %s\n",x,pl[0],pl[1],e,s);
errno=0;
x=strtod(s,0);
e=errno;
printf(" strtod x %g %8X %8X errno %d s %s\n",x,pl[0],pl[1],e,s);
errno=0;
(void) sscanf(s,"%lf",&x);
e=errno;
printf(" sscanf x %g %8X %8X errno %d s %s\n",x,pl[0],pl[1],e,s);
}
main()
{
test("1.e+126");
test("1.0e+126");
test("-100000000000000000000000000000000000000000000000000000000000000");
test("-100000000000000000000000000000000000000000000000000000000000000.0");
test("-0999999999999999999999999999999999999999999999999999999");
test("-999999999999999999999999999999999999999999999999999999.0");
test("-836856653383323110000000000000000000000000000000000000000000000000000000000000000000000000.0000");
}
MIPS' conversion routines are pretty accurate for two man-weeks of effort
but not above criticism, in my view.
Some of you may not consider all of these tests to be legitimate or interesting;
anyway compiling cc testmips.c and running yields
atof x 1e+126 5A17A2EC C414A040 errno 0 s 1.e+126
strtod x 1e+126 5A17A2EC C414A041 errno 0 s 1.e+126
sscanf x 1e+126 5A17A2EC C414A040 errno 9 s 1.e+126
atof x 1e+126 5A17A2EC C414A03F errno 0 s 1.0e+126
strtod x 1e+126 5A17A2EC C414A041 errno 0 s 1.0e+126
sscanf x 1e+126 5A17A2EC C414A03F errno 9 s 1.0e+126
atof x -1e+62 CCCF1D75 A5709C1B errno 0 s -100000000000000000000000000000000000000000000000000000000000000
strtod x -1e+62 CCCF1D75 A5709C1B errno 0 s -100000000000000000000000000000000000000000000000000000000000000
sscanf x -1e+62 CCCF1D75 A5709C1B errno 34 s -100000000000000000000000000000000000000000000000000000000000000
atof x -1e+62 CCCF1D75 A5709C1B errno 0 s -100000000000000000000000000000000000000000000000000000000000000.0
strtod x -1e+62 CCCF1D75 A5709C1B errno 0 s -100000000000000000000000000000000000000000000000000000000000000.0
sscanf x -1e+62 CCCF1D75 A5709C1B errno 34 s -100000000000000000000000000000000000000000000000000000000000000.0
atof x -1e+54 CB24E187 8814C9CD errno 0 s -0999999999999999999999999999999999999999999999999999999
strtod x -1e+54 CB24E187 8814C9CE errno 0 s -0999999999999999999999999999999999999999999999999999999
sscanf x -1e+54 CB24E187 8814C9CD errno 9 s -0999999999999999999999999999999999999999999999999999999
atof x -1e+54 CB24E187 8814C9CD errno 0 s -999999999999999999999999999999999999999999999999999999.0
strtod x -1e+54 CB24E187 8814C9CE errno 0 s -999999999999999999999999999999999999999999999999999999.0
sscanf x -1e+54 CB24E187 8814C9CD errno 9 s -999999999999999999999999999999999999999999999999999999.0
atof x -8.36857e+89 D29A4AE3 2080FA81 errno 0 s -836856653383323110000000000000000000000000000000000000000000000000000000000000000000000000.0000
strtod x -8.36857e+89 D29A4AE3 2080FA82 errno 0 s -836856653383323110000000000000000000000000000000000000000000000000000000000000000000000000.0000
sscanf x -8.36857e+89 D29A4AE3 2080FA82 errno 34 s -836856653383323110000000000000000000000000000000000000000000000000000000000000000000000000.0000
which might be good enough for many purposes; compiling on a Sun-4
with our C 1.0 product this way:
/usr/lang/SC0.0/cc testmips.c -u _fix_libc_
(we don't distribute libc with C 1.0; the -u _fix_libc_ causes necessary patches
to be picked up from libm which we do distribute with C 1.0)
produces
atof x 1e+126 5A17A2EC C414A03F errno 0 s 1.e+126
strtod x 1e+126 5A17A2EC C414A03F errno 0 s 1.e+126
sscanf x 1e+126 5A17A2EC C414A03F errno 0 s 1.e+126
atof x 1e+126 5A17A2EC C414A03F errno 0 s 1.0e+126
strtod x 1e+126 5A17A2EC C414A03F errno 0 s 1.0e+126
sscanf x 1e+126 5A17A2EC C414A03F errno 0 s 1.0e+126
atof x -1e+62 CCCF1D75 A5709C1B errno 0 s -100000000000000000000000000000000000000000000000000000000000000
strtod x -1e+62 CCCF1D75 A5709C1B errno 0 s -100000000000000000000000000000000000000000000000000000000000000
sscanf x -1e+62 CCCF1D75 A5709C1B errno 0 s -100000000000000000000000000000000000000000000000000000000000000
atof x -1e+62 CCCF1D75 A5709C1B errno 0 s -100000000000000000000000000000000000000000000000000000000000000.0
strtod x -1e+62 CCCF1D75 A5709C1B errno 0 s -100000000000000000000000000000000000000000000000000000000000000.0
sscanf x -1e+62 CCCF1D75 A5709C1B errno 0 s -100000000000000000000000000000000000000000000000000000000000000.0
atof x -1e+54 CB24E187 8814C9CE errno 0 s -0999999999999999999999999999999999999999999999999999999
strtod x -1e+54 CB24E187 8814C9CE errno 0 s -0999999999999999999999999999999999999999999999999999999
sscanf x -1e+54 CB24E187 8814C9CE errno 0 s -0999999999999999999999999999999999999999999999999999999
atof x -1e+54 CB24E187 8814C9CE errno 0 s -999999999999999999999999999999999999999999999999999999.0
strtod x -1e+54 CB24E187 8814C9CE errno 0 s -999999999999999999999999999999999999999999999999999999.0
sscanf x -1e+54 CB24E187 8814C9CE errno 0 s -999999999999999999999999999999999999999999999999999999.0
atof x -8.36857e+89 D29A4AE3 2080FA81 errno 0 s -836856653383323110000000000000000000000000000000000000000000000000000000000000000000000000.0000
strtod x -8.36857e+89 D29A4AE3 2080FA81 errno 0 s -836856653383323110000000000000000000000000000000000000000000000000000000000000000000000000.0000
sscanf x -8.36857e+89 D29A4AE3 2080FA81 errno 0 s -836856653383323110000000000000000000000000000000000000000000000000000000000000000000000000.0000
which some people might prefer on consistency grounds if no others.
Which is more accurate? bc isn't good for much as a systems benchmark,
but it comes in handy here:
kcng% bc
obase=16
10^54
A70C3C40A64E6C51999090B65F67D9240000000000000
(10^54)*2
14E1878814C9CD8A33321216CBECFB2480000000000000
The latter form is convenient for comparison with IEEE double precision format.
Clearly
14E1878814C9CE000...
is a better approximation (ie correctly rounded) to
14E1878814C9CD8A33321216CBECFB2480000000000000
than
14E1878814C9CD000...
Similarly
(10^126)*4
17A2ECC414A03F7FF6CA1CB527787B130A97D51E51202365498FF69BE1291D6C857CBE\
4A2900000000000000000000000000000000
tells a similar story.
It took me quite a bit longer than two weeks - more like two months elapsed
time - to get the test program that found these examples working well; the
code that produces the correctly-rounded results quite a bit longer than that.
Regardless of one's opinion of bc,
I believe that the Sun results indicated are indeed correctly rounded.
Richard Tuck relates that it took him about six weeks elapsed time to write
up the 68010 assembly code for the base conversion in SunOS 3.x.
More information about the Numeric-interest
mailing list