mirror of
https://github.com/autc04/Retro68.git
synced 2024-12-01 11:52:47 +00:00
233 lines
3.4 KiB
C
233 lines
3.4 KiB
C
|
|
#include "test.h"
|
|
#include <errno.h>
|
|
|
|
|
|
int
|
|
randi (void)
|
|
{
|
|
static int next;
|
|
next = (next * 1103515245) + 12345;
|
|
return ((next >> 16) & 0xffff);
|
|
}
|
|
|
|
double randx (void)
|
|
{
|
|
double res;
|
|
|
|
do
|
|
{
|
|
union {
|
|
short parts[4];
|
|
double res;
|
|
} u;
|
|
|
|
u.parts[0] = randi();
|
|
u.parts[1] = randi();
|
|
u.parts[2] = randi();
|
|
u.parts[3] = randi();
|
|
res = u.res;
|
|
|
|
} while (!finite(res));
|
|
|
|
return res ;
|
|
}
|
|
|
|
/* Return a random double, but bias for numbers closer to 0 */
|
|
double randy (void)
|
|
{
|
|
int pow;
|
|
double r= randx();
|
|
r = frexp(r, &pow);
|
|
return ldexp(r, randi() & 0x1f);
|
|
}
|
|
|
|
void
|
|
test_frexp (void)
|
|
{
|
|
int i;
|
|
double r;
|
|
int t;
|
|
|
|
float xf;
|
|
double gives;
|
|
|
|
int pow;
|
|
|
|
|
|
/* Frexp of x return a and n, where a * 2**n == x, so test this with a
|
|
set of random numbers */
|
|
for (t = 0; t < 2; t++)
|
|
{
|
|
for (i = 0; i < 1000; i++)
|
|
{
|
|
|
|
double x = randx();
|
|
line(i);
|
|
switch (t)
|
|
{
|
|
case 0:
|
|
newfunc("frexp/ldexp");
|
|
r = frexp(x, &pow);
|
|
if (r > 1.0 || r < -1.0)
|
|
{
|
|
/* Answer can never be > 1 or < 1 */
|
|
test_iok(0,1);
|
|
}
|
|
|
|
gives = ldexp(r ,pow);
|
|
test_mok(gives,x,62);
|
|
break;
|
|
case 1:
|
|
newfunc("frexpf/ldexpf");
|
|
if (x > FLT_MIN && x < FLT_MAX)
|
|
{
|
|
/* test floats too, but they have a smaller range so make sure x
|
|
isn't too big. Also x can get smaller than a float can
|
|
represent to make sure that doesn't happen too */
|
|
xf = x;
|
|
r = frexpf(xf, &pow);
|
|
if (r > 1.0 || r < -1.0)
|
|
{
|
|
/* Answer can never be > 1 or < -1 */
|
|
test_iok(0,1);
|
|
}
|
|
|
|
gives = ldexpf(r ,pow);
|
|
test_mok(gives,x, 32);
|
|
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/* test a few numbers manually to make sure frexp/ldexp are not
|
|
testing as ok because both are broken */
|
|
|
|
r = frexp(64.0, &i);
|
|
|
|
test_mok(r, 0.5,64);
|
|
test_iok(i, 7);
|
|
|
|
r = frexp(96.0, &i);
|
|
|
|
test_mok(r, 0.75, 64);
|
|
test_iok(i, 7);
|
|
|
|
}
|
|
|
|
/* Test mod - this is given a real hammering by the strtod type
|
|
routines, here are some more tests.
|
|
|
|
By definition
|
|
|
|
modf = func(value, &iptr)
|
|
|
|
(*iptr + modf) == value
|
|
|
|
we test this
|
|
|
|
*/
|
|
void
|
|
test_mod (void)
|
|
{
|
|
int i;
|
|
|
|
newfunc("modf");
|
|
|
|
|
|
for (i = 0; i < 1000; i++)
|
|
{
|
|
double intpart;
|
|
double n;
|
|
line(i);
|
|
n = randx();
|
|
if (finite(n) && n != 0.0 )
|
|
{
|
|
double r = modf(n, &intpart);
|
|
line(i);
|
|
test_mok(intpart + r, n, 63);
|
|
}
|
|
|
|
}
|
|
newfunc("modff");
|
|
|
|
for (i = 0; i < 1000; i++)
|
|
{
|
|
float intpart;
|
|
double nd;
|
|
line(i);
|
|
nd = randx() ;
|
|
if (nd < FLT_MAX && finitef(nd) && nd != 0.0)
|
|
{
|
|
float n = nd;
|
|
double r = modff(n, &intpart);
|
|
line(i);
|
|
test_mok(intpart + r, n, 32);
|
|
}
|
|
}
|
|
|
|
|
|
}
|
|
|
|
/*
|
|
Test pow by multiplying logs
|
|
*/
|
|
void
|
|
test_pow (void)
|
|
{
|
|
unsigned int i;
|
|
newfunc("pow");
|
|
|
|
for (i = 0; i < 1000; i++)
|
|
{
|
|
double n1;
|
|
double n2;
|
|
double res;
|
|
double shouldbe;
|
|
|
|
line(i);
|
|
n1 = fabs(randy());
|
|
n2 = fabs(randy()/100.0);
|
|
res = pow(n1, n2);
|
|
shouldbe = exp(log(n1) * n2);
|
|
test_mok(shouldbe, res,64);
|
|
}
|
|
|
|
newfunc("powf");
|
|
|
|
for (i = 0; i < 1000; i++)
|
|
{
|
|
double n1;
|
|
double n2;
|
|
double res;
|
|
double shouldbe;
|
|
|
|
errno = 0;
|
|
|
|
line(i);
|
|
n1 = fabs(randy());
|
|
n2 = fabs(randy()/100.0);
|
|
res = powf(n1, n2);
|
|
shouldbe = expf(logf(n1) * n2);
|
|
if (!errno)
|
|
test_mok(shouldbe, res,28);
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
test_math2 (void)
|
|
{
|
|
test_mod();
|
|
test_frexp();
|
|
test_pow();
|
|
}
|