quakeforge/libs/util/test/test-baryvf.c
Bill Currie ef9b04ba83 [util] Get tests working with sse2
It seems that i686 code generation is all over the place reguarding sse2
vs fp, with the resulting differences in carried precision. I'm not sure
I'm happy with the situation, but at least it's being tested to a
certain extent. Not sure if this broke basic (no sse) i686 tests.
2021-06-01 18:53:53 +09:00

118 lines
2.9 KiB
C

#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include "QF/mathlib.h"
#include "QF/mersenne.h"
#include "QF/sys.h"
#include "QF/simd/vec4f.h"
vec4f_t points[] = {
{-1, -1, 1},
{ 1, 1, 1},
{-1, 1, -1},
{ 1, -1, -1},
{-1, -1, -1},
{ 1, 1, -1},
{-1, 1, 1},
{ 1, -1, 1},
{ 0, 0, 0},
};
const vec4f_t *line[] = {&points[0], &points[1]};
const vec4f_t *tri[] = {&points[0], &points[1], &points[2]};
const vec4f_t *tetra[] = {&points[0], &points[1], &points[2], &points[3]};
struct {
const vec4f_t **points;
int num_points;
vec4f_t *x;
vec_t expect[4];
} tests[] = {
{line, 2, &points[0], {1, 0}},
{line, 2, &points[1], {0, 1}},
{line, 2, &points[2], {0.5, 0.5}},
{line, 2, &points[3], {0.5, 0.5}},
{line, 2, &points[8], {0.5, 0.5}},
{tri, 3, &points[0], {1, 0, 0}},
{tri, 3, &points[1], {0, 1, 0}},
{tri, 3, &points[2], {0, 0, 1}},
{tri, 3, &points[3], {0.333333333, 0.333333333, 0.333333333}},
{tri, 3, &points[8], {0.333333333, 0.333333333, 0.333333333}},
{tetra, 4, &points[0], {1, 0, 0, 0}},
{tetra, 4, &points[1], {0, 1, 0, 0}},
{tetra, 4, &points[2], {0, 0, 1, 0}},
{tetra, 4, &points[3], {0, 0, 0, 1}},
{tetra, 4, &points[4], { 0.5, -0.5, 0.5, 0.5}},
{tetra, 4, &points[5], {-0.5, 0.5, 0.5, 0.5}},
{tetra, 4, &points[6], { 0.5, 0.5, 0.5, -0.5}},
{tetra, 4, &points[7], { 0.5, 0.5, -0.5, 0.5}},
{tetra, 4, &points[8], {0.25, 0.25, 0.25, 0.25}},
};
#define num_tests (sizeof (tests) / sizeof (tests[0]))
static inline float
rnd (mtstate_t *mt)
{
union {
uint32_t u;
float f;
} uf;
do {
uf.u = mtwist_rand (mt) & 0x007fffff;
} while (!uf.u);
uf.u |= 0x40000000;
return uf.f - 3.0;
}
int
main (int argc, const char **argv)
{
int res = 0;
size_t i;
int j;
vec4f_t lambda;
mtstate_t mt;
double start, end;
for (i = 0; i < num_tests; i ++) {
lambda = BarycentricCoords_vf (tests[i].points, tests[i].num_points, *tests[i].x);
for (j = 0; j < tests[i].num_points; j++) {
if (tests[i].expect[j] != lambda[j])
break;
}
if (j != tests[i].num_points) {
res = 1;
printf ("test %d failed\n", (int) i);
printf ("expect:");
for (j = 0; j < tests[i].num_points; j++)
printf (" %.9g", tests[i].expect[j]);
printf ("\ngot :");
for (j = 0; j < tests[i].num_points; j++)
printf (" %.9g", lambda[j]);
printf ("\n");
}
}
mtwist_seed (&mt, 0);
start = Sys_DoubleTime ();
for (i = 0; i < 1000000; i++) {
vec4f_t p = { rnd (&mt), rnd (&mt), rnd (&mt) };
vec4f_t x = {};
lambda = BarycentricCoords_vf (tetra, 4, p);
for (j = 0; j < 4; j++) {
x = x + lambda[j] * *tetra[j];
}
if (VectorDistance_fast (x, p) > 1e-4) {
res = 1;
printf ("[%.9g %.9g %.9g] != [%.9g %.9g %.9g]: [%g %g %g %g]\n",
VectorExpand (x), VectorExpand (p), QuatExpand (lambda));
break;
}
}
end = Sys_DoubleTime ();
printf ("%d itterations in %gs: %g itters/second\n", (int) i, end - start,
i / (end - start));
return res;
}