| #include <signal.h> |
| #include "test.h" |
| #include <math.h> |
| #include <ieeefp.h> |
| #include <string.h> |
| int verbose; |
| static int count; |
| int inacc; |
| |
| |
| int |
| _DEFUN(main,(ac, av), |
| int ac _AND |
| char **av) |
| { |
| int i; |
| int math2 = 1; |
| int string= 1; |
| int is = 1; |
| int math= 1; |
| int cvt = 1; |
| int ieee= 1; |
| bt(); |
| for (i = 1; i < ac; i++) |
| { |
| if (strcmp(av[i],"-v")==0) |
| verbose ++; |
| if (strcmp(av[i],"-nomath2") == 0) |
| math2 = 0; |
| if (strcmp(av[i],"-nostrin") == 0) |
| string= 0; |
| if (strcmp(av[i],"-nois") == 0) |
| is = 0; |
| if (strcmp(av[i],"-nomath") == 0) |
| math= 0; |
| if (strcmp(av[i],"-nocvt") == 0) |
| cvt = 0; |
| if (strcmp(av[i],"-noiee") == 0) |
| ieee= 0; |
| } |
| if (cvt) |
| test_cvt(); |
| |
| if (math2) |
| test_math2(); |
| if (string) |
| test_string(); |
| if (math) |
| test_math(); |
| if (is) |
| test_is(); |
| if (ieee) test_ieee(); |
| printf("Tested %d functions, %d errors detected\n", count, inacc); |
| return 0; |
| } |
| |
| |
| static _CONST char *iname = "foo"; |
| void |
| _DEFUN(newfunc,(string), |
| _CONST char *string) |
| { |
| if (strcmp(iname, string)) |
| { |
| printf("testing %s\n", string); |
| fflush(stdout); |
| iname = string; |
| } |
| |
| } |
| |
| |
| static int theline; |
| |
| void line(li) |
| int li; |
| { |
| if (verbose) |
| { |
| printf(" %d\n", li); |
| } |
| theline = li; |
| |
| count++; |
| } |
| |
| |
| |
| int redo = 0; |
| int reduce = 0; |
| |
| int strtod_vector = 0; |
| |
| int |
| _DEFUN(bigger,(a,b), |
| __ieee_double_shape_type *a _AND |
| __ieee_double_shape_type *b) |
| { |
| |
| if (a->parts.msw > b->parts.msw) |
| { |
| |
| return 1; |
| } |
| else if (a->parts.msw == b->parts.msw) |
| { |
| if (a->parts.lsw > b->parts.lsw) |
| { |
| return 1; |
| } |
| } |
| return 0; |
| } |
| |
| |
| |
| /* Return the first bit different between two double numbers */ |
| int |
| _DEFUN(mag_of_error,(is, shouldbe), |
| double is _AND |
| double shouldbe) |
| { |
| __ieee_double_shape_type a,b; |
| int i; |
| int a_big; |
| unsigned int mask; |
| unsigned long int __x; |
| unsigned long int msw, lsw; |
| a.value = is; |
| |
| b.value = shouldbe; |
| |
| if (a.parts.msw == b.parts.msw |
| && a.parts.lsw== b.parts.lsw) return 64; |
| |
| |
| /* Subtract the larger from the smaller number */ |
| |
| a_big = bigger(&a, &b); |
| |
| if (!a_big) { |
| int t; |
| t = a.parts.msw; |
| a.parts.msw = b.parts.msw; |
| b.parts.msw = t; |
| |
| t = a.parts.lsw; |
| a.parts.lsw = b.parts.lsw; |
| b.parts.lsw = t; |
| } |
| |
| |
| |
| __x = (a.parts.lsw) - (b.parts.lsw); |
| msw = (a.parts.msw) - (b.parts.msw) - (__x > (a.parts.lsw)); |
| lsw = __x; |
| |
| |
| |
| |
| /* Find out which bit the difference is in */ |
| mask = 0x80000000; |
| for (i = 0; i < 32; i++) |
| { |
| if (((msw) & mask)!=0) return i; |
| mask >>=1; |
| } |
| |
| mask = 0x80000000; |
| for (i = 0; i < 32; i++) |
| { |
| |
| if (((lsw) & mask)!=0) return i+32; |
| mask >>=1; |
| } |
| |
| return 64; |
| |
| } |
| |
| int ok_mag; |
| |
| |
| |
| void |
| _DEFUN(test_sok,(is, shouldbe), |
| char *is _AND |
| char *shouldbe) |
| { |
| if (strcmp(is,shouldbe)) |
| { |
| printf("%s:%d, inacurate answer: (%s should be %s)\n", |
| iname, |
| theline, |
| is, shouldbe); |
| inacc++; |
| } |
| } |
| void |
| _DEFUN(test_iok,(is, shouldbe), |
| int is _AND |
| int shouldbe) |
| { |
| if (is != shouldbe){ |
| printf("%s:%d, inacurate answer: (%08x should be %08x)\n", |
| iname, |
| theline, |
| is, shouldbe); |
| inacc++; |
| } |
| } |
| |
| |
| /* Compare counted strings upto a certain length - useful to test single |
| prec float conversions against double results |
| */ |
| void |
| _DEFUN(test_scok,(is, shouldbe, count), |
| char *is _AND |
| char *shouldbe _AND |
| int count) |
| { |
| if (strncmp(is,shouldbe, count)) |
| { |
| printf("%s:%d, inacurate answer: (%s should be %s)\n", |
| iname, |
| theline, |
| is, shouldbe); |
| inacc++; |
| } |
| } |
| |
| void |
| _DEFUN(test_eok,(is, shouldbe), |
| int is _AND |
| int shouldbe) |
| { |
| if (is != shouldbe){ |
| printf("%s:%d, bad errno answer: (%d should be %d)\n", |
| iname, |
| theline, |
| is, shouldbe); |
| inacc++; |
| } |
| } |
| |
| void |
| _DEFUN(test_mok,(value, shouldbe, okmag), |
| double value _AND |
| double shouldbe _AND |
| int okmag) |
| { |
| __ieee_double_shape_type a,b; |
| int mag = mag_of_error(value, shouldbe); |
| if (mag == 0) |
| { |
| /* error in the first bit is ok if the numbers are both 0 */ |
| if (value == 0.0 && shouldbe == 0.0) |
| return; |
| |
| } |
| a.value = shouldbe; |
| b.value = value; |
| |
| if (mag < okmag) |
| { |
| printf("%s:%d, wrong answer: bit %d ", |
| iname, |
| theline, |
| mag); |
| printf("%08x%08x %08x%08x) ", |
| a.parts.msw, a.parts.lsw, |
| b.parts.msw, b.parts.lsw); |
| printf("(%g %g)\n", a.value, b.value); |
| inacc++; |
| } |
| } |
| |
| #ifdef __PCCNECV70__ |
| kill() {} |
| getpid() {} |
| #endif |
| |
| bt(){ |
| |
| double f1,f2; |
| f1 = 0.0; |
| f2 = 0.0/f1; |
| printf("(%g)\n", f2); |
| |
| } |