mirror of
https://github.com/bloeys/gglm.git
synced 2025-12-29 13:38:20 +00:00
Mat2 and Mat3 determinant and inverse matrices
This commit is contained in:
22
gglm/mat2.go
22
gglm/mat2.go
@ -84,7 +84,6 @@ func (m *Mat2) Eq(m2 *Mat2) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (m *Mat2) Transpose() *Mat2 {
|
func (m *Mat2) Transpose() *Mat2 {
|
||||||
|
|
||||||
m.Data = [2][2]float32{
|
m.Data = [2][2]float32{
|
||||||
{m.Data[0][0], m.Data[1][0]},
|
{m.Data[0][0], m.Data[1][0]},
|
||||||
{m.Data[0][1], m.Data[1][1]},
|
{m.Data[0][1], m.Data[1][1]},
|
||||||
@ -93,6 +92,27 @@ func (m *Mat2) Transpose() *Mat2 {
|
|||||||
return m
|
return m
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (m *Mat2) Determinant() float32 {
|
||||||
|
return (m.Data[0][0] * m.Data[1][1]) - (m.Data[0][1] * m.Data[1][0])
|
||||||
|
}
|
||||||
|
|
||||||
|
// Invert inverts this matrix.
|
||||||
|
//
|
||||||
|
// Note that the inverse is not defined if the determinant is zero or extremely small.
|
||||||
|
// In the case the determinant is zero the matrix will (usually) get filled with infinities
|
||||||
|
func (m *Mat2) Invert() *Mat2 {
|
||||||
|
|
||||||
|
// https://www.cuemath.com/algebra/inverse-of-2x2-matrix/
|
||||||
|
inverseDet := 1 / m.Determinant()
|
||||||
|
|
||||||
|
m.Data = [2][2]float32{
|
||||||
|
{m.Data[1][1] * inverseDet, -m.Data[0][1] * inverseDet}, // Col0
|
||||||
|
{-m.Data[1][0] * inverseDet, m.Data[0][0] * inverseDet}, // Col1
|
||||||
|
}
|
||||||
|
|
||||||
|
return m
|
||||||
|
}
|
||||||
|
|
||||||
// AddMat2 m3 = m1 + m2
|
// AddMat2 m3 = m1 + m2
|
||||||
func AddMat2(m1, m2 *Mat2) *Mat2 {
|
func AddMat2(m1, m2 *Mat2) *Mat2 {
|
||||||
return &Mat2{
|
return &Mat2{
|
||||||
|
|||||||
@ -179,6 +179,56 @@ func TestTransposeMat2(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestDeterminantMat2(t *testing.T) {
|
||||||
|
|
||||||
|
m := gglm.NewMat2Id()
|
||||||
|
ans := float32(1)
|
||||||
|
|
||||||
|
if m.Determinant() != ans {
|
||||||
|
t.Errorf("Got: %f; Expected: %f", m.Determinant(), ans)
|
||||||
|
}
|
||||||
|
|
||||||
|
m = &gglm.Mat2{
|
||||||
|
Data: [2][2]float32{
|
||||||
|
{1, 8},
|
||||||
|
{5, 31},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
ans = -9
|
||||||
|
|
||||||
|
if m.Determinant() != ans {
|
||||||
|
t.Errorf("Got: %f; Expected: %f", m.Determinant(), ans)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestInverseMat2(t *testing.T) {
|
||||||
|
|
||||||
|
m := gglm.NewMat2Id()
|
||||||
|
ans := gglm.NewMat2Id()
|
||||||
|
|
||||||
|
if !m.Invert().Eq(ans) {
|
||||||
|
t.Errorf("Got: %v; Expected: %v", m.String(), ans.String())
|
||||||
|
}
|
||||||
|
|
||||||
|
m = &gglm.Mat2{
|
||||||
|
Data: [2][2]float32{
|
||||||
|
{1, 8},
|
||||||
|
{5, 31},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
ans = &gglm.Mat2{
|
||||||
|
Data: [2][2]float32{
|
||||||
|
{-31 / 9.0, 8 / 9.0},
|
||||||
|
{5 / 9.0, -1 / 9.0},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
if !m.Invert().Eq(ans) {
|
||||||
|
t.Errorf("Got: %v; Expected: %v", m.String(), ans.String())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func BenchmarkMulMat2(b *testing.B) {
|
func BenchmarkMulMat2(b *testing.B) {
|
||||||
|
|
||||||
m1 := gglm.NewMat2Id()
|
m1 := gglm.NewMat2Id()
|
||||||
|
|||||||
58
gglm/mat3.go
58
gglm/mat3.go
@ -145,6 +145,64 @@ func (m *Mat3) Transpose() *Mat3 {
|
|||||||
return m
|
return m
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (m *Mat3) Determinant() float32 {
|
||||||
|
x := m.Data[0][0] * (m.Data[1][1]*m.Data[2][2] - m.Data[2][1]*m.Data[1][2])
|
||||||
|
y := m.Data[1][0] * (m.Data[2][1]*m.Data[0][2] - m.Data[0][1]*m.Data[2][2])
|
||||||
|
z := m.Data[2][0] * (m.Data[0][1]*m.Data[1][2] - m.Data[1][1]*m.Data[0][2])
|
||||||
|
return x + y + z
|
||||||
|
}
|
||||||
|
|
||||||
|
// Invert inverts this matrix.
|
||||||
|
//
|
||||||
|
// Note that the inverse is not defined if the determinant is zero or extremely small.
|
||||||
|
// In the case the determinant is zero the matrix will (usually) get filled with infinities
|
||||||
|
func (m *Mat3) Invert() *Mat3 {
|
||||||
|
|
||||||
|
// https://www.cuemath.com/algebra/inverse-of-3x3-matrix/
|
||||||
|
|
||||||
|
// Manually inline the determinant function because go doesn't
|
||||||
|
x := m.Data[0][0] * (m.Data[1][1]*m.Data[2][2] - m.Data[2][1]*m.Data[1][2])
|
||||||
|
y := m.Data[1][0] * (m.Data[2][1]*m.Data[0][2] - m.Data[0][1]*m.Data[2][2])
|
||||||
|
z := m.Data[2][0] * (m.Data[0][1]*m.Data[1][2] - m.Data[1][1]*m.Data[0][2])
|
||||||
|
|
||||||
|
inverseDet := 1 / (x + y + z)
|
||||||
|
|
||||||
|
// Inverse[0][0] = + (m[1][1] * m[2][2] - m[2][1] * m[1][2]) * OneOverDeterminant;
|
||||||
|
// Inverse[1][0] = - (m[1][0] * m[2][2] - m[2][0] * m[1][2]) * OneOverDeterminant;
|
||||||
|
// Inverse[2][0] = + (m[1][0] * m[2][1] - m[2][0] * m[1][1]) * OneOverDeterminant;
|
||||||
|
// Inverse[0][1] = - (m[0][1] * m[2][2] - m[2][1] * m[0][2]) * OneOverDeterminant;
|
||||||
|
// Inverse[1][1] = + (m[0][0] * m[2][2] - m[2][0] * m[0][2]) * OneOverDeterminant;
|
||||||
|
// Inverse[2][1] = - (m[0][0] * m[2][1] - m[2][0] * m[0][1]) * OneOverDeterminant;
|
||||||
|
// Inverse[0][2] = + (m[0][1] * m[1][2] - m[1][1] * m[0][2]) * OneOverDeterminant;
|
||||||
|
// Inverse[1][2] = - (m[0][0] * m[1][2] - m[1][0] * m[0][2]) * OneOverDeterminant;
|
||||||
|
// Inverse[2][2] = + (m[0][0] * m[1][1] - m[1][0] * m[0][1]) * OneOverDeterminant;
|
||||||
|
|
||||||
|
m.Data = [3][3]float32{
|
||||||
|
// Col0
|
||||||
|
{
|
||||||
|
(m.Data[1][1]*m.Data[2][2] - m.Data[2][1]*m.Data[1][2]) * inverseDet,
|
||||||
|
-(m.Data[0][1]*m.Data[2][2] - m.Data[2][1]*m.Data[0][2]) * inverseDet,
|
||||||
|
(m.Data[0][1]*m.Data[1][2] - m.Data[1][1]*m.Data[0][2]) * inverseDet,
|
||||||
|
},
|
||||||
|
|
||||||
|
// Col1
|
||||||
|
{
|
||||||
|
-(m.Data[1][0]*m.Data[2][2] - m.Data[2][0]*m.Data[1][2]) * inverseDet,
|
||||||
|
(m.Data[0][0]*m.Data[2][2] - m.Data[2][0]*m.Data[0][2]) * inverseDet,
|
||||||
|
-(m.Data[0][0]*m.Data[1][2] - m.Data[1][0]*m.Data[0][2]) * inverseDet,
|
||||||
|
},
|
||||||
|
|
||||||
|
// Col2
|
||||||
|
{
|
||||||
|
(m.Data[1][0]*m.Data[2][1] - m.Data[2][0]*m.Data[1][1]) * inverseDet,
|
||||||
|
-(m.Data[0][0]*m.Data[2][1] - m.Data[2][0]*m.Data[0][1]) * inverseDet,
|
||||||
|
(m.Data[0][0]*m.Data[1][1] - m.Data[1][0]*m.Data[0][1]) * inverseDet,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
return m
|
||||||
|
}
|
||||||
|
|
||||||
// AddMat3 m3 = m1 + m2
|
// AddMat3 m3 = m1 + m2
|
||||||
func AddMat3(m1, m2 *Mat3) *Mat3 {
|
func AddMat3(m1, m2 *Mat3) *Mat3 {
|
||||||
return &Mat3{
|
return &Mat3{
|
||||||
|
|||||||
@ -196,6 +196,59 @@ func TestTransposeMat3(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestDeterminantMat3(t *testing.T) {
|
||||||
|
|
||||||
|
m := gglm.NewMat3Id()
|
||||||
|
ans := float32(1)
|
||||||
|
|
||||||
|
if m.Determinant() != ans {
|
||||||
|
t.Errorf("Got: %f; Expected: %f", m.Determinant(), ans)
|
||||||
|
}
|
||||||
|
|
||||||
|
m = &gglm.Mat3{
|
||||||
|
Data: [3][3]float32{
|
||||||
|
{1, 8, 2},
|
||||||
|
{5, 3, 5},
|
||||||
|
{9, 6, 7},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
ans = 77
|
||||||
|
|
||||||
|
if m.Determinant() != ans {
|
||||||
|
t.Errorf("Got: %f; Expected: %f", m.Determinant(), ans)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestInverseMat3(t *testing.T) {
|
||||||
|
|
||||||
|
m := gglm.NewMat3Id()
|
||||||
|
ans := gglm.NewMat3Id()
|
||||||
|
|
||||||
|
if !m.Invert().Eq(ans) {
|
||||||
|
t.Errorf("Got: %v; Expected: %v", m.String(), ans.String())
|
||||||
|
}
|
||||||
|
|
||||||
|
m = &gglm.Mat3{
|
||||||
|
Data: [3][3]float32{
|
||||||
|
{1, 8, 2},
|
||||||
|
{5, 3, 5},
|
||||||
|
{9, 6, 7},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
ans = &gglm.Mat3{
|
||||||
|
Data: [3][3]float32{
|
||||||
|
{-9 / 77.0, -4 / 7.0, 34 / 77.0},
|
||||||
|
{10 / 77.0, -1 / 7.0, 5 / 77.0},
|
||||||
|
{3 / 77.0, 6 / 7.0, -37 / 77.0},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
if !m.Invert().Eq(ans) {
|
||||||
|
t.Errorf("Got: %v; Expected: %v", m.String(), ans.String())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func BenchmarkMulMat3(b *testing.B) {
|
func BenchmarkMulMat3(b *testing.B) {
|
||||||
|
|
||||||
m1 := gglm.NewMat3Id()
|
m1 := gglm.NewMat3Id()
|
||||||
|
|||||||
Reference in New Issue
Block a user