tasayco@phoenix.Princeton.EDU (Francisco Figueirido) (12/06/90)
Some time ago I was writing my own floating point routines for an Atari (MC68000 processor) and while checking that it gave correct answers, I found that the MIPS processor (machine: SGI 4D/240, OS version 4D1-3.3) gives a slightly different answer than a SparcStation. I am including the program I used to test the operations and also the diffs between the output of both processors. I believe the correctly rounded result is the one given by the Sparc (I regret to say this because I really like the MIPS). As I am not an expert on the architercture of either processor or, for that matter, floating point stuff, I would appreciate any comments regarding this matter. The following is the program I used (sorry, I guess I could have posted a smaller version). Compile it and run with testdf -n 100 (if testdf is the name of the executable). This will run a loop of 100 iterations adding two numbers (see the source code for more information). ========================================================================== #include <stdio.h> double atof(/* const char * */); #define NUMCMDLIN 4 #define ADD 1 #define SUBSTRACT 2 #define MULTIPLY 3 #define DIVIDE 4 static char cmdlin[] = { 'x', 'y', 'o', 'n', }; static double fx = 0.333333333333; static double fy = 0.123456789; static unsigned int oflag = ADD; static unsigned int N = 1000; void __get_fx(argcp, argvp) int *argcp; char ***argvp; { (*argvp)++; (*argcp)--; if (*(*argvp) != (char *)0) fx = atof(*(*argvp)); } void __get_fy(argcp, argvp) int *argcp; char ***argvp; { (*argvp)++; (*argcp)--; if (*(*argvp) != (char *)0) fy = atof(*(*argvp)); } void __get_operator(argcp, argvp) int *argcp; char ***argvp; { char op; (*argvp)++; (*argcp)--; if (*(*argvp) != (char *)0) { op = *(*(*argvp)); switch (op) { case '+' : oflag = ADD; break; case '-' : oflag = SUBSTRACT; break; case '*' : oflag = MULTIPLY; break; case '/' : oflag = DIVIDE; break; } } } void __get_iterations(argcp, argvp) int *argcp; char ***argvp; { (*argvp)++; (*argcp)--; if (*(*argvp) != (char *)0) N = atoi(*(*argvp)); } static void (* getlin[])() = { __get_fx, __get_fy, __get_operator, __get_iterations, }; extern int main(argc, argv) int argc; char **argv; { unsigned int i, j; union { double d; int i[2]; } d2i; union { float f; int i; } f2i; /* Check the command line arguments */ argv++; argc--; while (argc > 0) { if ((*argv)[0] != '-') { /* skip this argument */ argc--; argv++; } for (i = 0; i < NUMCMDLIN; i++) { if ( argc > 0 && (*argv)[1] == cmdlin[i]) (* getlin[i])(&argc, &argv); } /* go to next argument */ argc--; argv++; } printf("\n"); d2i.d = fx; f2i.f = (float)fx; printf("fx = %08x %08x = %08x (%lf) \n", d2i.i[0], d2i.i[1], f2i.i, fx); d2i.d = fy; f2i.f = (float)fy; printf("fy = %08x %08x = %08x (%lf) \n", d2i.i[0], d2i.i[1], f2i.i, fy); printf("\n"); /* Compare the numbers as doubles */ if (fx == fy) printf("The numbers are equal (as doubles).\n\n"); else if (fx > fy) printf("fx is larger than fy (as doubles).\n\n"); else if (fx < fy) printf("fy is larger than fx (as doubles).\n\n"); else printf("Cannot decide for doubles!\n\n"); /* Compare the numbers as floats */ if ((float)fx == (float)fy) printf("The numbers are equal (as floats).\n\n"); else if ((float)fx > (float)fy) printf("fx is larger than fy (as floats).\n\n"); else if ((float)fx < (float)fy) printf("fy is larger than fx (as floats).\n\n"); else printf("Cannot decide for floats!\n\n"); d2i.d = fx; f2i.f = (float)fx; for (j = 0; j < N; j++) { printf(" >> %08x %08x = %08x \n", d2i.i[0], d2i.i[1], f2i.i); switch (oflag) { case ADD : d2i.d += fy; f2i.f += (float)fy; break; case SUBSTRACT : d2i.d -= fy; f2i.f -= (float)fy; break; case MULTIPLY : d2i.d *= fy; f2i.f *= (float)fy; break; case DIVIDE : d2i.d /= fy; f2i.f /= (float)fy; break; } } printf("\n"); } ========================================================================== This is the diff between the output for a Sparc and a MIPS: 10c10 < >> 3fdd3c0c a32396b9 = 3ee9e066 (Sparc) --- > >> 3fdd3c0c a32396b9 = 3ee9e065 (MIPS) ========================================================================== Francisco Figueirido e-mail: tasayco@phoenix.princeton.edu figuei@max.physics.sunysb.edu