quakeforge/libs/util/test/test-csvf.c
Bill Currie c11a930436 [simd] Set the homogeneous coord in the csvf test
The homogeneous coord was not being initialized and thus was picking up
rubbish from the stack. This is why the test would succeed in some
circumstances but fail in others.
2021-12-26 12:25:06 +09:00

130 lines
3.2 KiB
C

#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include "QF/mathlib.h"
#include "QF/mersenne.h"
#include "QF/simd/vec4f.h"
#include "QF/sys.h"
const 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},
};
// This particular triangle from ad_tears caused SEB to hit its iteration
// limit because the center in affine hull test failed due to excessivly tight
// epsilon.
// However, the problem isn't here (but good to have a set of tests for it
// anyway).
const vec4f_t tears_triangleA[] = {
{2201.82007, -1262, -713.450012, 1},
{2201.8501, -1262, -713.593994, 1},
};
const vec4f_t tears_triangleB[] = {
{2201.82007, -1262, -713.450012, 1},
{2201.84009, -1262, -713.445007, 1},
};
const vec4f_t tears_triangleC[] = {
{2201.8501, -1262, -713.593994, 1},
{2201.84009, -1262, -713.445007, 1},
};
struct {
const vec4f_t *points;
int num_points;
sphere_t expect;
} tests[] = {
{0, 0, {{ 0, 0, 0}, 0}},
{points, 1, {{-1, -1, 1}, 0}},
{points, 2, {{ 0, 0, 1}, 1.41421356}},
{points, 3, {{-0.333333343, 0.333333343, 0.333333343}, 1.63299322}},
{points, 4, {{0, 0, 0}, 1.73205081}},
{tears_triangleA, 2, {{2201.83496, -1262, -713.521973}, 0.0734853372}},
{tears_triangleB, 2, {{2201.83008, -1262, -713.44751}, 0.0103178304}},
{tears_triangleC, 2, {{2201.84521, -1262, -713.519531}, 0.0746228099}},
};
#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;
vspheref_t sphere;
mtstate_t mt;
double start, end;
for (i = 0; i < num_tests; i ++) {
sphere = CircumSphere_vf (tests[i].points, tests[i].num_points);
if (VectorDistance_fast (sphere.center, tests[i].expect.center) > 1e-4
|| fabs (sphere.radius - tests[i].expect.radius) > 1e-4) {
res = 1;
printf ("test %d failed\n", (int) i);
printf ("expect: {%.9g, %.9g, %.9g},%.9g\n",
VectorExpand (tests[i].expect.center),
tests[i].expect.radius);
printf ("got : {%.9g, %.9g, %.9g},%.9g\n",
VectorExpand (sphere.center),
sphere.radius);
}
}
mtwist_seed (&mt, 0);
start = Sys_DoubleTime ();
for (i = 0; !res && i < 1000000; i++) {
vec4f_t cloud[4];
vspheref_t cc;
vec_t r2;
vec_t fr;
for (j = 0; j < 4; j++) {
VectorSet (rnd (&mt), rnd (&mt), rnd (&mt), cloud[j]);
cloud[j][3] = 1;
}
cc = CircumSphere_vf (cloud, 4);
if (cc.radius < 0) {
// degenerate
continue;
}
r2 = cc.radius * cc.radius;
for (j = 0; j < 4; j++) {
vec4f_t d = cloud[j] - cc.center;
fr = dotf (d, d)[0];
if (fabs (fr - r2) < 1e-3 * r2)
continue;
printf ("%zd %d %.9g - %.9g = %.9g %.9g\n",
i, j, fr, r2, fr - r2, fabs(fr - r2));
printf ("[%.9g %.9g %.9g] - [%.9g %.9g %.9g] = %.9g != %.9g\n",
VectorExpand (cloud[j]), VectorExpand (cc.center), fr, r2);
res = 1;
}
}
end = Sys_DoubleTime ();
printf ("%d itterations in %gs: %g itters/second\n", (int) i, end - start,
i / (end - start));
return res;
}