quakeforge/tools/qfcc/test/pga2d.r
Bill Currie 40f04ff33e [qfcc] Implement undual and use for regressive product
I'm not sure the regressive product is right (overall sign), but that's
actually partly a problem in the math itself (duals and the regressive
product still get poked at, so it may be just a matter of
interpretation).
2024-02-20 16:46:02 +09:00

376 lines
8.8 KiB
R
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "test-harness.h"
#pragma warn no-vararg-integer
typedef @algebra(double(2,0,1)) PGA;
typedef PGA.group_mask(0x08) scalar_t;
typedef PGA.group_mask(0x01) vector_t;
typedef PGA.group_mask(0x04) bivector_t;
typedef PGA.group_mask(0x02) trivector_t;
typedef union {
PGA.group_mask(0x0c) mvec;
struct {
bivector_t bvec;
scalar_t scalar;
};
} evengrades_t;
typedef union {
PGA.group_mask(0x03) mvec;
struct {
vector_t vec;
trivector_t tvec;
};
} oddgrades_t;
static int
test_dual (void)
{
@algebra (PGA) {
auto a = 1f;
auto a0 = e0;
auto a1 = e1;
auto a2 = e2;
auto a12 = e12;
auto a01 = e01;
auto a20 = e20;
auto a012 = e012;
#define TEST_DUAL(x, y) \
if (x != y) { \
printf ("⋆" #x " != " #y "\n"); \
return 1; \
}
TEST_DUAL (a, e012);
TEST_DUAL (a0, e12);
TEST_DUAL (a1, e20);
TEST_DUAL (a2, e01);
TEST_DUAL (a20, e1);
TEST_DUAL (a01, e2);
TEST_DUAL (a12, e0);
TEST_DUAL (a012, 1);
#undef TEST_DUAL
#define TEST_DUAL(x) \
if (x *x != e012) { \
printf (#x " * ⋆" #x " != e012\n"); \
return 1; \
}
TEST_DUAL (a);
TEST_DUAL (a0);
TEST_DUAL (a1);
TEST_DUAL (a2);
TEST_DUAL (a20);
TEST_DUAL (a01);
TEST_DUAL (a12);
TEST_DUAL (a012);
#undef TEST_DUAL
}
return 0;
}
static int
test_undual (void)
{
@algebra (PGA) {
auto a = 1f;
auto a0 = e0;
auto a1 = e1;
auto a2 = e2;
auto a12 = e12;
auto a01 = e01;
auto a20 = e20;
auto a012 = e012;
#define TEST_UNDUAL(x, y) \
if (@undual x != y) { \
printf ("@undual " #x " != " #y "\n"); \
return 1; \
}
TEST_UNDUAL (a, e012);
TEST_UNDUAL (a0, e12);
TEST_UNDUAL (a1, e20);
TEST_UNDUAL (a2, e01);
TEST_UNDUAL (a20, e1);
TEST_UNDUAL (a01, e2);
TEST_UNDUAL (a12, e0);
TEST_UNDUAL (a012, 1);
#undef TEST_UNDUAL
#define TEST_UNDUAL(x) \
if (@undual x * x != e012) { \
printf ("@undual " #x " * " #x " != e012\n"); \
return 1; \
}
TEST_UNDUAL (a);
TEST_UNDUAL (a0);
TEST_UNDUAL (a1);
TEST_UNDUAL (a2);
TEST_UNDUAL (a20);
TEST_UNDUAL (a01);
TEST_UNDUAL (a12);
TEST_UNDUAL (a012);
#undef TEST_DUAL
}
return 0;
}
int
main (void)
{
if (sizeof (scalar_t) != sizeof (double)) {
printf ("scalar has wrong size: %d\n", sizeof (scalar_t));
return 1;
}
// vector_t is a vec3 but has alignment of 4 thus sizeof of 4 * scalar
if (sizeof (vector_t) != 4 * sizeof (scalar_t)) {
printf ("vector has wrong size: %d\n", sizeof (vector_t));
return 1;
}
// bivector_t is a vec3 but has alignment of 4 thus sizeof of 4 * scalar
if (sizeof (bivector_t) != 4 * sizeof (scalar_t)) {
printf ("bivector has wrong size: %d\n", sizeof (bivector_t));
return 1;
}
if (sizeof (trivector_t) != sizeof (scalar_t)) {
printf ("trivector has wrong size: %d\n", sizeof (trivector_t));
return 1;
}
scalar_t scalar;
vector_t vec, vecb;
bivector_t bvec, bvecb;
trivector_t tvec, tvecb;
@algebra (PGA) {
scalar = 42;
vec = 3*e1 - 2*e2 + e0;
bvec = 4*e20 - 3*e01 + 2*e12;
tvec = 7*e012;
vecb = 5*e1 + 12*e2 - 13*e0;
bvecb = 6*e20 + 4*e01 + 1*e12;
tvecb = 3*e012;
}
if (scalar != 42) {
printf ("scalar != 42: %g\n", scalar);
return 1;
}
if ((dvec3)vec != '3 -2 1'd) {
printf ("vec != '3 -2 1': %lv\n", vec);
return 1;
}
if ((dvec3)bvec != '4 -3 2'd) {
printf ("vec != '4 -3 2': %lv\n", bvec);
return 1;
}
if ((double)tvec != 7) {
printf ("tvec != 7: %g\n", tvec);
return 1;
}
auto a = vecbvec;
if ((double)a != 20) {
printf ("vec ∧ bvec != 20: %lv\n", a);
return 1;
}
auto b = bvecvec;
if ((double)b != 20) {
printf ("bvec ∧ vec != 20: %lv\n", b);
return 1;
}
auto c = vecbvec;
if ((dvec3)c != '4 6 1'd) {
printf ("vec • bvec != '4 6 1': %lv\n", c);
return 1;
}
auto d = bvecvec;
if ((dvec3)d != '-4 -6 -1'd) {
printf ("bvec • vec != '-4 -6 -1': %lv\n", d);
return 1;
}
oddgrades_t e;
e.mvec = vec * bvec;
if ((dvec3)e.vec != '4 6 1'd || (scalar_t)e.tvec != 20) {
printf ("vec • bvec != '4 6 1' + 20: %lv %g\n", e.vec, e.tvec);
return 1;
}
oddgrades_t f;
f.mvec = bvec * vec;
if ((dvec3)f.vec != '-4 -6 -1'd || (scalar_t)f.tvec != 20) {
printf ("bvec • vec != '-4 -6 -1' + 20: %lv %g\n", f.vec, f.tvec);
return 1;
}
if (vectvec || tvecvec) {
printf ("didn't get 0: %g %g", vectvec, tvecvec);
return 0;
}
auto g = vectvec;
if ((dvec3)g != '21 -14 0'd) {
printf ("vec • tvec != '21 -14 0': %lv\n", g);
return 1;
}
auto h = tvecvec;
if ((dvec3)h != '21 -14 0'd) {
printf ("vec • tvec != '21 -14 0': %lv\n", h);
return 1;
}
auto i = vec * tvec;
if ((dvec3)i != '21 -14 0'd) {
printf ("vec * tvec != '21 -14 0': %lv\n", i);
return 1;
}
auto j = tvec * vec;
if ((dvec3)j != '21 -14 0'd) {
printf ("vec * tvec != '21 -14 0': %lv\n", j);
return 1;
}
if (bvectvec || tvecbvec) {
printf ("didn't get 0: %g %g", bvectvec, tvecbvec);
return 0;
}
auto k = bvectvec;
if ((dvec3)k != '0 0 -14'd) {
printf ("bvec • tvec != '0 0 -14': %lv\n", k);
return 1;
}
auto l = tvecbvec;
if ((dvec3)l != '0 0 -14'd) {
printf ("tvec • bvec != '0 0 -14': %lv\n", l);
return 1;
}
auto m = bvec * tvec;
if ((dvec3)m != '0 0 -14'd) {
printf ("bvec * tvec != '0 0 -14': %lv\n", m);
return 1;
}
auto n = tvec * bvec;
if ((dvec3)n != '0 0 -14'd) {
printf ("tvec * bvec != '0 0 -14': %lv\n", n);
return 1;
}
// if (vecvec || bvecbvec || tvectvec) {
// printf ("didn't get 0: %g %g %g", vecvec, bvecbvec, tvectvec);
// return 0;
// }
auto o = vecvecb;
if ((dvec3)o != '14 44 46'd) {
printf ("vec ∧ vecb != '14 44 46': %lv\n", o);
return 1;
}
auto p = vecbvec;
if ((dvec3)p != '-14 -44 -46'd) {
printf ("vecb ∧ vec != '-14 -44 -46': %lv\n", p);
return 1;
}
auto q = vecvecb;
if (q != -9) {
printf ("vec • vecb != -9: %g\n", q);
return 1;
}
auto r = vecbvec;
if (r != -9) {
printf ("vecb • vec != -9: %g\n", r);
return 1;
}
evengrades_t s;
s.mvec= vec * vecb;
if (s.scalar != -9 || (dvec3)s.bvec != '14 44 46'd) {
printf ("vec * vecb != -9, '14 44 46': %g %lv\n",
s.scalar, s.bvec);
return 1;
}
evengrades_t t;
t.mvec = vecb * vec;
if (t.scalar != -9 || (dvec3)t.bvec != '-14 -44 -46'd) {
printf ("vecb * vec != -9, '-14 -44 -46': %g %lv\n",
t.scalar, t.bvec);
return 1;
}
if (bvecbvecb || tvectvecb) {
printf ("didn't get 0: %g %g", bvecbvecb, tvectvecb);
return 0;
}
auto u = bvecbvecb;
if (u != -2) {
printf ("bvec • bvecb != -2: %g\n", u);
return 1;
}
auto v = bvecbbvec;
if (v != -2) {
printf ("bvecb • bvec != -2: %g\n", v);
return 1;
}
evengrades_t w;
w.mvec = bvec * bvecb;
if (w.scalar != -2 || (dvec3)w.bvec != '11 -8 0'd) {
printf ("bvec * bvecb != -2, '11 -8 0': %g %lv\n",
w.scalar, w.bvec);
return 1;
}
evengrades_t x;
x.mvec = bvecb * bvec;
if (x.scalar != -2 || (dvec3)x.bvec != '-11 8 0'd) {
printf ("vecb * vec != -2, '-11 8 0': %g %lv\n",
x.scalar, x.bvec);
return 1;
}
if (tvectvecb || tvec * tvecb) {
printf ("didn't get 0: %g %g", tvectvecb, tvec * tvecb);
return 0;
}
e.mvec = e.mvec; // odd
if ((dvec3)e.vec != '4 6 1'd || (scalar_t)e.tvec != -20) {
printf ("odd† != '4 6 1' + -20: %lv %g\n", e.vec, e.tvec);
return 1;
}
s.mvec = s.mvec; // even
if (s.scalar != -9 || (dvec3)s.bvec != '-14 -44 -46'd) {
printf ("even† != -9, '-14 -44 -46': %g %lv\n",
s.scalar, s.bvec);
return 1;
}
e.mvec = e.mvec / 2; // odd
if ((dvec3)e.vec != '2 3 0.5'd || (scalar_t)e.tvec != -10) {
printf ("odd† != '2 3 0.5' + -10: %lv %g\n", e.vec, e.tvec);
return 1;
}
s.mvec = s.mvec / 2; // even
if (s.scalar != -4.5 || (dvec3)s.bvec != '-7 -22 -23'd) {
printf ("even† != -4.5, '-7 -22 -23': %g %lv\n",
s.scalar, s.bvec);
return 1;
}
e.mvec = -e.mvec; // odd
if ((dvec3)e.vec != '-2 -3 -0.5'd || (scalar_t)e.tvec != 10) {
printf ("odd† != '-2 -3 -0.5' + 10: %lv %g\n", e.vec, e.tvec);
return 1;
}
s.mvec = -s.mvec; // even
if (s.scalar != 4.5 || (dvec3)s.bvec != '7 22 23'd) {
printf ("even† != 4.5, '7 22 23': %g %lv\n",
s.scalar, s.bvec);
return 1;
}
evengrades_t dual_e;
dual_e.mvec =e.mvec; // test both dual operators
if ((dvec3)dual_e.bvec != '-2 -3 -0.5'd || dual_e.scalar != 10) {
printf ("⋆odd != '-2 -3 -0.5' + 10: %lv %g\n", e.vec, e.tvec);
return 1;
}
oddgrades_t dual_s;
dual_s.mvec = !s.mvec; // test both dual operators
if ((scalar_t)dual_s.tvec != 4.5 || (dvec3)dual_s.vec != '7 22 23'd) {
printf ("!even != 4.5, '7 22 23': %g %lv\n",
s.scalar, s.bvec);
return 1;
}
auto line = bvec bvecb;
if ((dvec3)line != '-11 8 34'd) {
printf ("bvec(%lv) bvecb(%lv) != '-11 8 34': %lv\n", bvec, bvecb, line);
return 1;
}
if (test_dual ()) {
printf ("dual failed\n");
return 1;
}
if (test_undual ()) {
printf ("dual failed\n");
return 1;
}
return 0; // to survive and prevail :)
}