#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 = vec ∧ bvec; if ((double)a != 20) { printf ("vec ∧ bvec != 20: %lv\n", a); return 1; } auto b = bvec ∧ vec; if ((double)b != 20) { printf ("bvec ∧ vec != 20: %lv\n", b); return 1; } auto c = vec • bvec; if ((dvec3)c != '4 6 1'd) { printf ("vec • bvec != '4 6 1': %lv\n", c); return 1; } auto d = bvec • vec; 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 (vec ∧ tvec || tvec ∧ vec) { printf ("didn't get 0: %g %g", vec ∧ tvec, tvec ∧ vec); return 0; } auto g = vec • tvec; if ((dvec3)g != '21 -14 0'd) { printf ("vec • tvec != '21 -14 0': %lv\n", g); return 1; } auto h = tvec • vec; 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 (bvec ∧ tvec || tvec ∧ bvec) { printf ("didn't get 0: %g %g", bvec ∧ tvec, tvec ∧ bvec); return 0; } auto k = bvec • tvec; if ((dvec3)k != '0 0 -14'd) { printf ("bvec • tvec != '0 0 -14': %lv\n", k); return 1; } auto l = tvec • bvec; 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 (vec ∧ vec || bvec ∧ bvec || tvec ∧ tvec) { // printf ("didn't get 0: %g %g %g", vec ∧ vec, bvec ∧ bvec, tvec ∧ tvec); // return 0; // } auto o = vec ∧ vecb; if ((dvec3)o != '14 44 46'd) { printf ("vec ∧ vecb != '14 44 46': %lv\n", o); return 1; } auto p = vecb ∧ vec; if ((dvec3)p != '-14 -44 -46'd) { printf ("vecb ∧ vec != '-14 -44 -46': %lv\n", p); return 1; } auto q = vec • vecb; if (q != -9) { printf ("vec • vecb != -9: %g\n", q); return 1; } auto r = vecb • vec; 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 (bvec ∧ bvecb || tvec ∧ tvecb) { printf ("didn't get 0: %g %g", bvec ∧ bvecb, tvec ∧ tvecb); return 0; } auto u = bvec • bvecb; if (u != -2) { printf ("bvec • bvecb != -2: %g\n", u); return 1; } auto v = bvecb • bvec; 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 (tvec • tvecb || tvec * tvecb) { printf ("didn't get 0: %g %g", tvec • tvecb, 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 :) }