newlib-cygwin/newlib/libm/test/test.c

283 lines
4.3 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
main (int ac,
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
newfunc (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
bigger (__ieee_double_shape_type *a,
__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
mag_of_error (double is,
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
test_sok (char *is,
char *shouldbe)
{
if (strcmp(is,shouldbe))
{
printf("%s:%d, inacurate answer: (%s should be %s)\n",
iname,
theline,
is, shouldbe);
inacc++;
}
}
void
test_iok (int is,
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
test_scok (char *is,
char *shouldbe,
int count)
{
if (strncmp(is,shouldbe, count))
{
printf("%s:%d, inacurate answer: (%s should be %s)\n",
iname,
theline,
is, shouldbe);
inacc++;
}
}
void
test_eok (int is,
int shouldbe)
{
if (is != shouldbe){
printf("%s:%d, bad errno answer: (%d should be %d)\n",
iname,
theline,
is, shouldbe);
inacc++;
}
}
void
test_mok (double value,
double shouldbe,
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);
}