292 lines
4.6 KiB
C
292 lines
4.6 KiB
C
#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);
|
|
|
|
}
|