inline Mat2 Mat2::operator*(const Mat2& rhs) const { return Mat2(m[0]*rhs[0] + m[2]*rhs[1], m[1]*rhs[0] + m[3]*rhs[1], m[0]*rhs[2] + m[2]*rhs[3], m[1]*rhs[2] + m[3]*rhs[3]); }
inline Mat2 operator-(const Mat2& rhs) { return Mat2(-rhs[0], -rhs[1], -rhs[2], -rhs[3]); }
inline Mat2 Mat2::operator+(const Mat2& rhs) const { return Mat2(m[0]+rhs[0], m[1]+rhs[1], m[2]+rhs[2], m[3]+rhs[3]); }
inline Mat2 Mat2::operator-(const Mat2& rhs) const { return Mat2(m[0]-rhs[0], m[1]-rhs[1], m[2]-rhs[2], m[3]-rhs[3]); }
Mat2 Mat2::operator*(const Mat2 &m) const { return Mat2(d00*m.d00 + d01*m.d10, d00*m.d01 + d01*m.d11, d10*m.d00 + d11*m.d10, d10*m.d01 + d11*m.d11); }
// Returns a jacobian matrix for this force wrt velocity Mat2 ViscousDragForce::GetJacobian(int flags) const { return Mat2(-drag, 0.f, 0.f, -drag); }
Mat2 Mat2::transpose() { return Mat2(d00, d10, d01, d11); }
Mat2 operator*(Mat2 const& m1, Mat2 const& m2) { return Mat2((m1.a*m2.a+m1.b*m2.c),(m1.a*m2.b+m1.b*m2.d), (m1.c*m2.a+m1.d*m2.c),(m1.c*m2.b+m1.d*m2.d)); }
Mat2 Mat2::identity() { return Mat2(1.0f, 0.0f, 0.0f, 1.0f); }
Mat2 Mat2::zero() { return Mat2(0.0f, 0.0f, 0.0f, 0.0f); }
Mat2 make_rotation_mat2(float phi) { return Mat2(std::cos(phi), -(std::sin(phi)), std::sin(phi), std::cos(phi)); }
Mat2 transpose (Mat2 const & m ) { return(Mat2(m.a,m.c,m.b,m.d)); }
Mat2 inverse (Mat2 const & m ) { return (1/(m.a*m.d - m.b*m.c) * Mat2(m.d,-m.b,-m.c,m.a)); }
inline Mat2 operator*(float s, const Mat2& rhs) { return Mat2(s*rhs[0], s*rhs[1], s*rhs[2], s*rhs[3]); }
Mat2 Mat2::inverse() { return Mat2( d11,-d10, -d01, d00) /determinant(); }
Mat2 Mat2::I() { return Mat2(1,0, 0,1); }
Mat2 operator*(float v,Mat2 const& u) { return(Mat2((u.a*v),(u.b*v),(u.c*v),(u.d*v))); }