namespace PGA3D { struct mvec { float e[16]; }; static const mvec e0 = { { 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f } }; static const mvec e1 = { { 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f } }; static const mvec e2 = { { 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f } }; static const mvec e3 = { { 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f } }; static const mvec e01 = { { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f } }; static const mvec e02 = { { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f } }; static const mvec e03 = { { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f } }; static const mvec e12 = { { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f } }; static const mvec e31 = { { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f } }; static const mvec e23 = { { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f } }; static const mvec e021 = { { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f } }; static const mvec e013 = { { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f } }; static const mvec e032 = { { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f } }; static const mvec e123 = { { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f } }; static const mvec e0123 ={ { 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f } }; inline mvec real(float r) { mvec v; v.e[0] = r; v.e[1] = 0.0f; v.e[2] = 0.0f; v.e[3] = 0.0f; v.e[4] = 0.0f; v.e[5] = 0.0f; v.e[6] = 0.0f; v.e[7] = 0.0f; v.e[8] = 0.0f; v.e[9] = 0.0f; v.e[10] = 0.0f; v.e[11] = 0.0f; v.e[12] = 0.0f; v.e[13] = 0.0f; v.e[14] = 0.0f; v.e[15] = 0.0f; return v; } inline mvec vec(float x, float y, float z) { mvec v; v.e[0] = 0.0f; v.e[1] = 0.0f; v.e[2] = 0.0f; v.e[3] = 0.0f; v.e[4] = 0.0f; v.e[5] = 0.0f; v.e[6] = 0.0f; v.e[7] = 0.0f; v.e[8] = 0.0f; v.e[9] = 0.0f; v.e[10] = 0.0f; v.e[11] = z; v.e[12] = y; v.e[13] = x; v.e[14] = 0.0f; v.e[15] = 0.0f; return v; } inline mvec pt(float x, float y, float z) { mvec v; v.e[0] = 0.0f; v.e[1] = 0.0f; v.e[2] = 0.0f; v.e[3] = 0.0f; v.e[4] = 0.0f; v.e[5] = 0.0f; v.e[6] = 0.0f; v.e[7] = 0.0f; v.e[8] = 0.0f; v.e[9] = 0.0f; v.e[10] = 0.0f; v.e[11] = z; v.e[12] = y; v.e[13] = x; v.e[14] = 1.0f; v.e[15] = 0.0f; return v; } inline mvec plane(float x, float y, float z, float c) { mvec v; v.e[0] = 0.0f; v.e[1] = c; v.e[2] = x; v.e[3] = y; v.e[4] = z; v.e[5] = 0.0f; v.e[6] = 0.0f; v.e[7] = 0.0f; v.e[8] = 0.0f; v.e[9] = 0.0f; v.e[10] = 0.0f; v.e[11] = 0.0f; v.e[12] = 0.0f; v.e[13] = 0.0f; v.e[14] = 0.0f; v.e[15] = 0.0f; return v; } inline mvec operator+(const mvec &l, const mvec &r) { mvec u; u.e[0] = l.e[0] + r.e[0]; u.e[1] = l.e[1] + r.e[1]; u.e[2] = l.e[2] + r.e[2]; u.e[3] = l.e[3] + r.e[3]; u.e[4] = l.e[4] + r.e[4]; u.e[5] = l.e[5] + r.e[5]; u.e[6] = l.e[6] + r.e[6]; u.e[7] = l.e[7] + r.e[7]; u.e[8] = l.e[8] + r.e[8]; u.e[9] = l.e[9] + r.e[9]; u.e[10] = l.e[10] + r.e[10]; u.e[11] = l.e[11] + r.e[11]; u.e[12] = l.e[12] + r.e[12]; u.e[13] = l.e[13] + r.e[13]; u.e[14] = l.e[14] + r.e[14]; u.e[15] = l.e[15] + r.e[15]; return u; } inline mvec operator-(const mvec &l, const mvec &r) { mvec u; u.e[0] = l.e[0] - r.e[0]; u.e[1] = l.e[1] - r.e[1]; u.e[2] = l.e[2] - r.e[2]; u.e[3] = l.e[3] - r.e[3]; u.e[4] = l.e[4] - r.e[4]; u.e[5] = l.e[5] - r.e[5]; u.e[6] = l.e[6] - r.e[6]; u.e[7] = l.e[7] - r.e[7]; u.e[8] = l.e[8] - r.e[8]; u.e[9] = l.e[9] - r.e[9]; u.e[10] = l.e[10] - r.e[10]; u.e[11] = l.e[11] - r.e[11]; u.e[12] = l.e[12] - r.e[12]; u.e[13] = l.e[13] - r.e[13]; u.e[14] = l.e[14] - r.e[14]; u.e[15] = l.e[15] - r.e[15]; return u; } inline mvec operator*(const mvec &v, float r) { mvec u; u.e[0] = v.e[0] * r; u.e[1] = v.e[1] * r; u.e[2] = v.e[2] * r; u.e[3] = v.e[3] * r; u.e[4] = v.e[4] * r; u.e[5] = v.e[5] * r; u.e[6] = v.e[6] * r; u.e[7] = v.e[7] * r; u.e[8] = v.e[8] * r; u.e[9] = v.e[9] * r; u.e[10] = v.e[10] * r; u.e[11] = v.e[11] * r; u.e[12] = v.e[12] * r; u.e[13] = v.e[13] * r; u.e[14] = v.e[14] * r; u.e[15] = v.e[15] * r; return u; } inline mvec operator*(float r, const mvec &v) { return v * 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.e[0]*v.e[0] + v.e[2]*v.e[2] + v.e[3]*v.e[3] + v.e[4]*v.e[4] + v.e[8]*v.e[8] + v.e[9]*v.e[9] + v.e[10]*v.e[10] + v.e[14]*v.e[14]; } 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) { mvec v; v.e[0] = + l.e[0]*r.e[0] + l.e[2]*r.e[2] + l.e[3]*r.e[3] + l.e[4]*r.e[4] - l.e[8]*r.e[8] - l.e[9]*r.e[9] - l.e[10]*r.e[10] - l.e[14]*r.e[14]; v.e[1] = + l.e[0]*r.e[1] + l.e[1]*r.e[0] - l.e[2]*r.e[5] - l.e[3]*r.e[6] - l.e[4]*r.e[7] + l.e[5]*r.e[2] + l.e[6]*r.e[3] + l.e[7]*r.e[4] + l.e[8]*r.e[11] + l.e[9]*r.e[12] + l.e[10]*r.e[13] + l.e[11]*r.e[8] + l.e[12]*r.e[9] + l.e[13]*r.e[10] + l.e[14]*r.e[15] - l.e[15]*r.e[14]; v.e[2] = + l.e[0]*r.e[2] + l.e[2]*r.e[0] - l.e[3]*r.e[8] + l.e[4]*r.e[9] + l.e[8]*r.e[3] - l.e[9]*r.e[4] - l.e[10]*r.e[14] - l.e[14]*r.e[10]; v.e[3] = + l.e[0]*r.e[3] + l.e[2]*r.e[8] + l.e[3]*r.e[0] - l.e[4]*r.e[10] - l.e[8]*r.e[2] - l.e[9]*r.e[14] + l.e[10]*r.e[4] - l.e[14]*r.e[9]; v.e[4] = + l.e[0]*r.e[4] - l.e[2]*r.e[9] + l.e[3]*r.e[10] + l.e[4]*r.e[0] - l.e[8]*r.e[14] + l.e[9]*r.e[2] - l.e[10]*r.e[3] - l.e[14]*r.e[8]; v.e[5] = + l.e[0]*r.e[5] + l.e[1]*r.e[2] - l.e[2]*r.e[1] - l.e[3]*r.e[11] + l.e[4]*r.e[12] + l.e[5]*r.e[0] - l.e[6]*r.e[8] + l.e[7]*r.e[9] + l.e[8]*r.e[6] - l.e[9]*r.e[7] - l.e[10]*r.e[15] - l.e[11]*r.e[3] + l.e[12]*r.e[4] + l.e[13]*r.e[14] - l.e[14]*r.e[13] - l.e[15]*r.e[10]; v.e[6] = + l.e[0]*r.e[6] + l.e[1]*r.e[3] + l.e[2]*r.e[11] - l.e[3]*r.e[1] - l.e[4]*r.e[13] + l.e[5]*r.e[8] + l.e[6]*r.e[0] - l.e[7]*r.e[10] - l.e[8]*r.e[5] - l.e[9]*r.e[15] + l.e[10]*r.e[7] + l.e[11]*r.e[2] + l.e[12]*r.e[14] - l.e[13]*r.e[4] - l.e[14]*r.e[12] - l.e[15]*r.e[9]; v.e[7] = + l.e[0]*r.e[7] + l.e[1]*r.e[4] - l.e[2]*r.e[12] + l.e[3]*r.e[13] - l.e[4]*r.e[1] - l.e[5]*r.e[9] + l.e[6]*r.e[10] + l.e[7]*r.e[0] - l.e[8]*r.e[15] + l.e[9]*r.e[5] - l.e[10]*r.e[6] + l.e[11]*r.e[14] - l.e[12]*r.e[2] + l.e[13]*r.e[3] - l.e[14]*r.e[11] - l.e[15]*r.e[8]; v.e[8] = + l.e[0]*r.e[8] + l.e[2]*r.e[3] - l.e[3]*r.e[2] + l.e[4]*r.e[14] + l.e[8]*r.e[0] + l.e[9]*r.e[10] - l.e[10]*r.e[9] + l.e[14]*r.e[4]; v.e[9] = + l.e[0]*r.e[9] - l.e[2]*r.e[4] + l.e[3]*r.e[14] + l.e[4]*r.e[2] - l.e[8]*r.e[10] + l.e[9]*r.e[0] + l.e[10]*r.e[8] + l.e[14]*r.e[3]; v.e[10] = + l.e[0]*r.e[10] + l.e[2]*r.e[14] + l.e[3]*r.e[4] - l.e[4]*r.e[3] + l.e[8]*r.e[9] - l.e[9]*r.e[8] + l.e[10]*r.e[0] + l.e[14]*r.e[2]; v.e[11] = + l.e[0]*r.e[11] - l.e[1]*r.e[8] + l.e[2]*r.e[6] - l.e[3]*r.e[5] + l.e[4]*r.e[15] - l.e[5]*r.e[3] + l.e[6]*r.e[2] - l.e[7]*r.e[14] - l.e[8]*r.e[1] + l.e[9]*r.e[13] - l.e[10]*r.e[12] + l.e[11]*r.e[0] + l.e[12]*r.e[10] - l.e[13]*r.e[9] + l.e[14]*r.e[7] - l.e[15]*r.e[4]; v.e[12] = + l.e[0]*r.e[12] - l.e[1]*r.e[9] - l.e[2]*r.e[7] + l.e[3]*r.e[15] + l.e[4]*r.e[5] + l.e[5]*r.e[4] - l.e[6]*r.e[14] - l.e[7]*r.e[2] - l.e[8]*r.e[13] - l.e[9]*r.e[1] + l.e[10]*r.e[11] - l.e[11]*r.e[10] + l.e[12]*r.e[0] + l.e[13]*r.e[8] + l.e[14]*r.e[6] - l.e[15]*r.e[3]; v.e[13] = + l.e[0]*r.e[13] - l.e[1]*r.e[10] + l.e[2]*r.e[15] + l.e[3]*r.e[7] - l.e[4]*r.e[6] - l.e[5]*r.e[14] - l.e[6]*r.e[4] + l.e[7]*r.e[3] + l.e[8]*r.e[12] - l.e[9]*r.e[11] - l.e[10]*r.e[1] + l.e[11]*r.e[9] - l.e[12]*r.e[8] + l.e[13]*r.e[0] + l.e[14]*r.e[5] - l.e[15]*r.e[2]; v.e[14] = + l.e[0]*r.e[14] + l.e[2]*r.e[10] + l.e[3]*r.e[9] + l.e[4]*r.e[8] + l.e[8]*r.e[4] + l.e[9]*r.e[3] + l.e[10]*r.e[2] + l.e[14]*r.e[0]; v.e[15] = + l.e[0]*r.e[15] + l.e[1]*r.e[14] + l.e[2]*r.e[13] + l.e[3]*r.e[12] + l.e[4]*r.e[11] + l.e[5]*r.e[10] + l.e[6]*r.e[9] + l.e[7]*r.e[8] + l.e[8]*r.e[7] + l.e[9]*r.e[6] + l.e[10]*r.e[5] - l.e[11]*r.e[4] - l.e[12]*r.e[3] - l.e[13]*r.e[2] - l.e[14]*r.e[1] + l.e[15]*r.e[0]; return v; } inline mvec operator^(const mvec &l, const mvec &r) { mvec v; v.e[0] = + l.e[0]*r.e[0]; v.e[1] = + l.e[0]*r.e[1] + l.e[1]*r.e[0]; v.e[2] = + l.e[0]*r.e[2] + l.e[2]*r.e[0]; v.e[3] = + l.e[0]*r.e[3] + l.e[3]*r.e[0]; v.e[4] = + l.e[0]*r.e[4] + l.e[4]*r.e[0]; v.e[5] = + l.e[0]*r.e[5] + l.e[1]*r.e[2] - l.e[2]*r.e[1] + l.e[5]*r.e[0]; v.e[6] = + l.e[0]*r.e[6] + l.e[1]*r.e[3] - l.e[3]*r.e[1] + l.e[6]*r.e[0]; v.e[7] = + l.e[0]*r.e[7] + l.e[1]*r.e[4] - l.e[4]*r.e[1] + l.e[7]*r.e[0]; v.e[8] = + l.e[0]*r.e[8] + l.e[2]*r.e[3] - l.e[3]*r.e[2] + l.e[8]*r.e[0]; v.e[9] = + l.e[0]*r.e[9] - l.e[2]*r.e[4] + l.e[4]*r.e[2] + l.e[9]*r.e[0]; v.e[10] = + l.e[0]*r.e[10] + l.e[3]*r.e[4] - l.e[4]*r.e[3] + l.e[10]*r.e[0]; v.e[11] = + l.e[0]*r.e[11] - l.e[1]*r.e[8] + l.e[2]*r.e[6] - l.e[3]*r.e[5] - l.e[5]*r.e[3] + l.e[6]*r.e[2] - l.e[8]*r.e[1] + l.e[11]*r.e[0]; v.e[12] = + l.e[0]*r.e[12] - l.e[1]*r.e[9] - l.e[2]*r.e[7] + l.e[4]*r.e[5] + l.e[5]*r.e[4] - l.e[7]*r.e[2] - l.e[9]*r.e[1] + l.e[12]*r.e[0]; v.e[13] = + l.e[0]*r.e[13] - l.e[1]*r.e[10] + l.e[3]*r.e[7] - l.e[4]*r.e[6] - l.e[6]*r.e[4] + l.e[7]*r.e[3] - l.e[10]*r.e[1] + l.e[13]*r.e[0]; v.e[14] = + l.e[0]*r.e[14] + l.e[2]*r.e[10] + l.e[3]*r.e[9] + l.e[4]*r.e[8] + l.e[8]*r.e[4] + l.e[9]*r.e[3] + l.e[10]*r.e[2] + l.e[14]*r.e[0]; v.e[15] = + l.e[0]*r.e[15] + l.e[1]*r.e[14] + l.e[2]*r.e[13] + l.e[3]*r.e[12] + l.e[4]*r.e[11] + l.e[5]*r.e[10] + l.e[6]*r.e[9] + l.e[7]*r.e[8] + l.e[8]*r.e[7] + l.e[9]*r.e[6] + l.e[10]*r.e[5] - l.e[11]*r.e[4] - l.e[12]*r.e[3] - l.e[13]*r.e[2] - l.e[14]*r.e[1] + l.e[15]*r.e[0]; return v; } inline mvec operator|(const mvec &l, const mvec &r) { mvec v; v.e[0] = + l.e[0]*r.e[0] + l.e[2]*r.e[2] + l.e[3]*r.e[3] + l.e[4]*r.e[4] - l.e[8]*r.e[8] - l.e[9]*r.e[9] - l.e[10]*r.e[10] - l.e[14]*r.e[14]; v.e[1] = + l.e[0]*r.e[1] + l.e[1]*r.e[0] - l.e[2]*r.e[5] - l.e[3]*r.e[6] - l.e[4]*r.e[7] + l.e[5]*r.e[2] + l.e[6]*r.e[3] + l.e[7]*r.e[4] + l.e[8]*r.e[11] + l.e[9]*r.e[12] + l.e[10]*r.e[13] + l.e[11]*r.e[8] + l.e[12]*r.e[9] + l.e[13]*r.e[10] + l.e[14]*r.e[15] - l.e[15]*r.e[14]; v.e[2] = + l.e[0]*r.e[2] + l.e[2]*r.e[0] - l.e[3]*r.e[8] + l.e[4]*r.e[9] + l.e[8]*r.e[3] - l.e[9]*r.e[4] - l.e[10]*r.e[14] - l.e[14]*r.e[10]; v.e[3] = + l.e[0]*r.e[3] + l.e[2]*r.e[8] + l.e[3]*r.e[0] - l.e[4]*r.e[10] - l.e[8]*r.e[2] - l.e[9]*r.e[14] + l.e[10]*r.e[4] - l.e[14]*r.e[9]; v.e[4] = + l.e[0]*r.e[4] - l.e[2]*r.e[9] + l.e[3]*r.e[10] + l.e[4]*r.e[0] - l.e[8]*r.e[14] + l.e[9]*r.e[2] - l.e[10]*r.e[3] - l.e[14]*r.e[8]; v.e[5] = + l.e[0]*r.e[5] - l.e[3]*r.e[11] + l.e[4]*r.e[12] + l.e[5]*r.e[0] - l.e[10]*r.e[15] - l.e[11]*r.e[3] + l.e[12]*r.e[4] - l.e[15]*r.e[10]; v.e[6] = + l.e[0]*r.e[6] + l.e[2]*r.e[11] - l.e[4]*r.e[13] + l.e[6]*r.e[0] - l.e[9]*r.e[15] + l.e[11]*r.e[2] - l.e[13]*r.e[4] - l.e[15]*r.e[9]; v.e[7] = + l.e[0]*r.e[7] - l.e[2]*r.e[12] + l.e[3]*r.e[13] + l.e[7]*r.e[0] - l.e[8]*r.e[15] - l.e[12]*r.e[2] + l.e[13]*r.e[3] - l.e[15]*r.e[8]; v.e[8] = + l.e[0]*r.e[8] + l.e[4]*r.e[14] + l.e[8]*r.e[0] + l.e[14]*r.e[4]; v.e[9] = + l.e[0]*r.e[9] + l.e[3]*r.e[14] + l.e[9]*r.e[0] + l.e[14]*r.e[3]; v.e[10] = + l.e[0]*r.e[10] + l.e[2]*r.e[14] + l.e[10]*r.e[0] + l.e[14]*r.e[2]; v.e[11] = + l.e[0]*r.e[11] + l.e[4]*r.e[15] + l.e[11]*r.e[0] - l.e[15]*r.e[4]; v.e[12] = + l.e[0]*r.e[12] + l.e[3]*r.e[15] + l.e[12]*r.e[0] - l.e[15]*r.e[3]; v.e[13] = + l.e[0]*r.e[13] + l.e[2]*r.e[15] + l.e[13]*r.e[0] - l.e[15]*r.e[2]; v.e[14] = + l.e[0]*r.e[14] + l.e[14]*r.e[0]; v.e[15] = + l.e[0]*r.e[15] + l.e[15]*r.e[0]; return v; } inline mvec operator&(const mvec &l, const mvec &r) { mvec v; v.e[15] = + l.e[15]*r.e[15]; v.e[14] = + l.e[15]*r.e[14] + l.e[14]*r.e[15]; v.e[13] = + l.e[15]*r.e[13] + l.e[13]*r.e[15]; v.e[12] = + l.e[15]*r.e[12] + l.e[12]*r.e[15]; v.e[11] = + l.e[15]*r.e[11] + l.e[11]*r.e[15]; v.e[10] = + l.e[15]*r.e[10] + l.e[14]*r.e[13] - l.e[13]*r.e[14] + l.e[10]*r.e[15]; v.e[9] = + l.e[15]*r.e[9] + l.e[14]*r.e[12] - l.e[12]*r.e[14] + l.e[9]*r.e[15]; v.e[8] = + l.e[15]*r.e[8] + l.e[14]*r.e[11] - l.e[11]*r.e[14] + l.e[8]*r.e[15]; v.e[7] = + l.e[15]*r.e[7] + l.e[13]*r.e[12] - l.e[12]*r.e[13] + l.e[7]*r.e[15]; v.e[6] = + l.e[15]*r.e[6] - l.e[13]*r.e[11] + l.e[11]*r.e[13] + l.e[6]*r.e[15]; v.e[5] = + l.e[15]*r.e[5] + l.e[12]*r.e[11] - l.e[11]*r.e[12] + l.e[5]*r.e[15]; v.e[4] = + l.e[15]*r.e[4] - l.e[14]*r.e[7] + l.e[13]*r.e[9] - l.e[12]*r.e[10] - l.e[10]*r.e[12] + l.e[9]*r.e[13] - l.e[7]*r.e[14] + l.e[4]*r.e[15]; v.e[3] = + l.e[15]*r.e[3] - l.e[14]*r.e[6] - l.e[13]*r.e[8] + l.e[11]*r.e[10] + l.e[10]*r.e[11] - l.e[8]*r.e[13] - l.e[6]*r.e[14] + l.e[3]*r.e[15]; v.e[2] = + l.e[15]*r.e[2] - l.e[14]*r.e[5] + l.e[12]*r.e[8] - l.e[11]*r.e[9] - l.e[9]*r.e[11] + l.e[8]*r.e[12] - l.e[5]*r.e[14] + l.e[2]*r.e[15]; v.e[1] = + l.e[15]*r.e[1] + l.e[13]*r.e[5] + l.e[12]*r.e[6] + l.e[11]*r.e[7] + l.e[7]*r.e[11] + l.e[6]*r.e[12] + l.e[5]*r.e[13] + l.e[1]*r.e[15]; v.e[0] = + l.e[15]*r.e[0] + l.e[14]*r.e[1] + l.e[13]*r.e[2] + l.e[12]*r.e[3] + l.e[11]*r.e[4] + l.e[10]*r.e[5] + l.e[9]*r.e[6] + l.e[8]*r.e[7] + l.e[7]*r.e[8] + l.e[6]*r.e[9] + l.e[5]*r.e[10] - l.e[4]*r.e[11] - l.e[3]*r.e[12] - l.e[2]*r.e[13] - l.e[1]*r.e[14] + l.e[0]*r.e[15]; return v; } inline mvec operator~(const mvec &v) { mvec u; u.e[0] = v.e[0]; u.e[1] = v.e[1]; u.e[2] = v.e[2]; u.e[3] = v.e[3]; u.e[4] = v.e[4]; u.e[5] = - v.e[5]; u.e[6] = - v.e[6]; u.e[7] = - v.e[7]; u.e[8] = - v.e[8]; u.e[9] = - v.e[9]; u.e[10] = - v.e[10]; u.e[11] = - v.e[11]; u.e[12] = - v.e[12]; u.e[13] = - v.e[13]; u.e[14] = - v.e[14]; u.e[15] = v.e[15]; return u; } inline mvec operator!(const mvec &v) { mvec u; u.e[0] = v.e[15]; u.e[1] = v.e[14]; u.e[2] = v.e[13]; u.e[3] = v.e[12]; u.e[4] = v.e[11]; u.e[5] = v.e[10]; u.e[6] = v.e[9]; u.e[7] = v.e[8]; u.e[8] = v.e[7]; u.e[9] = v.e[6]; u.e[10] = v.e[5]; u.e[11] = v.e[4]; u.e[12] = v.e[3]; u.e[13] = v.e[2]; u.e[14] = v.e[1]; u.e[15] = v.e[0]; return u; } //inline mvec operator&(const mvec &l, const mvec &r) { return !(!l ^ !r); } }