namespace GA2D { struct mvec { float r; float x, y; float xy; }; inline mvec mkmvec(float r, float x, float y, float xy) { mvec v = { r, x, y, xy }; return v; } inline mvec real(float r) { return mkmvec(r, 0.0f, 0.0f, 0.0f); } inline mvec vec(float x, float y) { return mkmvec(0.0f, x, y, 0.0f); } inline mvec bivec(float xy) { return mkmvec(0.0f, 0.0f, 0.0f, xy); } inline mvec operator+(const mvec &l, const mvec &r) { return mkmvec(l.r+r.r, l.x+r.x, l.y+r.y, l.xy+r.xy); } inline mvec operator-(const mvec &l, const mvec &r) { return mkmvec(l.r-r.r, l.x-r.x, l.y-r.y, l.xy-r.xy); } inline mvec operator*(const mvec &v, float r) { return mkmvec(v.r*r, v.x*r, v.y*r, v.xy*r); } inline mvec operator*(float r, const mvec &v) { return mkmvec(v.r*r, v.x*r, v.y*r, v.xy*r); } inline mvec operator/(const mvec &v, float r) { return v * (1.0f/r); } inline mvec operator/(float r, const mvec &v) { return v * (1.0f/r); } inline float normsq(const mvec &v){ return v.r*v.r + v.x*v.x + v.y*v.y + v.xy*v.xy; } inline float norm(const mvec &v){ return sqrtf(normsq(v)); } inline mvec normalized(const mvec &v){ return v / norm(v); } inline mvec operator*(const mvec &l, const mvec &r) { return mkmvec( l.r*r.r + l.x*r.x + l.y*r.y - l.xy*r.xy, l.r*r.x + l.x*r.r + l.xy*r.y - l.y*r.xy, l.r*r.y + l.y*r.r + l.x*r.xy - l.xy*r.x, l.r*r.xy + l.xy*r.r + l.x*r.y - l.y*r.x ); } inline mvec operator~(const mvec &v) { return mkmvec(v.r, v.x, v.y, -v.xy); } inline mvec grade(int k, const mvec &v) { mvec u; switch(k) { default: case 0: u.r = v.r; u.x = 0.0f; u.y = 0.0f; u.xy = 0.0f; break; case 1: u.r = 0.0f; u.x = v.x; u.y = v.y; u.xy = 0.0f; break; case 2: u.r = 0.0f; u.x = 0.0f; u.y = 0.0f; u.xy = v.xy; break; } return u; } }