aminal/vendor/github.com/go-gl/mathgl/mgl32/mat_test.go

459 lines
9.7 KiB
Go

// Copyright 2014 The go-gl Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package mgl32
import (
"fmt"
"math/rand"
"testing"
"time"
)
func TestMulIdent(t *testing.T) {
t.Parallel()
i1 := [...]float32{1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1}
i2 := Ident4()
i3 := Ident4()
mul := i2.Mul4(i3)
for i := range mul {
if mul[i] != i1[i] {
t.Errorf("Multiplication of identities does not yield identity")
}
}
}
// M>N
func TestMatRowsTall(t *testing.T) {
t.Parallel()
row0 := Vec3{1, 2, 3}
row1 := Vec3{4, 5, 6}
rows := [2]Vec3{row0, row1}
m1 := Mat2x3FromRows(rows[0], rows[1])
t.Logf("2x3 matrix as built from rows: %v", m1)
for r := 0; r < 2; r++ {
for c := 0; c < 3; c++ {
if !FloatEqualThreshold(m1.At(r, c), rows[r][c], 1e-5) {
t.Errorf("Matrix element at (%d,%d) wrong when built from rows. Got: %f, Expected: %f", r, c, m1.At(r, c), rows[r][c])
}
}
}
row0, row1 = m1.Rows()
rows2 := [2]Vec3{row0, row1}
t.Logf("2x3 matrix returned rows: %v", rows2)
for r := 0; r < 2; r++ {
for c := 0; c < 3; c++ {
if !FloatEqualThreshold(rows2[r][c], rows[r][c], 1e-5) {
t.Errorf("Matrix element at (%d,%d) wrong when rows are gotten. Got: %f, Expected: %f", r, c, rows2[r][c], rows[r][c])
}
}
}
}
// M<N
func TestMatRowsWide(t *testing.T) {
t.Parallel()
v0 := Vec3{1, 2, 3}
v1 := Vec3{4, 5, 6}
v2 := Vec3{7, 8, 9}
v3 := Vec3{10, 11, 12}
rows := [4]Vec3{v0, v1, v2, v3}
m1 := Mat4x3FromRows(v0, v1, v2, v3)
t.Logf("4x3 matrix as built from rows: %v", m1)
for r := 0; r < 4; r++ {
for c := 0; c < 3; c++ {
if !FloatEqualThreshold(m1.At(r, c), rows[r][c], 1e-5) {
t.Errorf("Matrix element at (%d,%d) wrong when built from rows. Got: %f, Expected: %f", r, c, m1.At(r, c), rows[r][c])
}
}
}
v0, v1, v2, v3 = m1.Rows()
r2 := [4]Vec3{v0, v1, v2, v3}
t.Logf("4x3 matrix returned rows: %v", r2)
for r := 0; r < 4; r++ {
for c := 0; c < 3; c++ {
if !FloatEqualThreshold(r2[r][c], rows[r][c], 1e-5) {
t.Errorf("Matrix element at (%d,%d) wrong when rows are gotten. Got: %f, Expected: %f", r, c, r2[r][c], rows[r][c])
}
}
}
}
// Square matrix
func TestMatRowsSquare(t *testing.T) {
t.Parallel()
v0 := Vec4{1, 2, 3, 4}
v1 := Vec4{5, 6, 7, 8}
v2 := Vec4{9, 10, 11, 12}
v3 := Vec4{13, 14, 15, 16}
rows := [4]Vec4{v0, v1, v2, v3}
m1 := Mat4FromRows(v0, v1, v2, v3)
t.Logf("4x4 matrix as built from rows: %v", m1)
for r := 0; r < 4; r++ {
for c := 0; c < 4; c++ {
if !FloatEqualThreshold(m1.At(r, c), rows[r][c], 1e-5) {
t.Errorf("Matrix element at (%d,%d) wrong when built from rows. Got: %f, Expected: %f", r, c, m1.At(r, c), rows[r][c])
}
}
}
v0, v1, v2, v3 = m1.Rows()
r2 := [4]Vec4{v0, v1, v2, v3}
t.Logf("4x4 matrix returned rows: %v", r2)
for r := 0; r < 4; r++ {
for c := 0; c < 4; c++ {
if !FloatEqualThreshold(r2[r][c], rows[r][c], 1e-5) {
t.Errorf("Matrix element at (%d,%d) wrong when rows are gotten. Got: %f, Expected: %f", r, c, r2[r][c], rows[r][c])
}
}
}
}
// M<N
func TestMatColsTall(t *testing.T) {
v0 := Vec3{1, 2, 3}
v1 := Vec3{4, 5, 6}
cols := [2]Vec3{v0, v1}
m1 := Mat3x2FromCols(v0, v1)
t.Logf("3x2 matrix as built from cols: %v", m1)
for r := 0; r < 3; r++ {
for c := 0; c < 2; c++ {
if !FloatEqualThreshold(m1.At(r, c), cols[c][r], 1e-5) {
t.Errorf("Matrix element at (%d,%d) wrong when built from rows. Got: %f, Expected: %f", r, c, m1.At(r, c), cols[c][r])
}
}
}
v0, v1 = m1.Cols()
r2 := [2]Vec3{v0, v1}
t.Logf("3x2 matrix returned cols: %v", r2)
for r := 0; r < 3; r++ {
for c := 0; c < 2; c++ {
if !FloatEqualThreshold(r2[c][r], cols[c][r], 1e-5) {
t.Errorf("Matrix element at (%d,%d) wrong when rows are gotten. Got: %f, Expected: %f", r, c, r2[c][r], cols[c][r])
}
}
}
}
// M>N
func TestMatColsWide(t *testing.T) {
t.Parallel()
v0 := Vec3{1, 2, 3}
v1 := Vec3{4, 5, 6}
v2 := Vec3{7, 8, 9}
v3 := Vec3{10, 11, 12}
cols := [4]Vec3{v0, v1, v2, v3}
m1 := Mat3x4FromCols(v0, v1, v2, v3)
t.Logf("3x4 matrix as built from cols: %v", m1)
for r := 0; r < 3; r++ {
for c := 0; c < 4; c++ {
if !FloatEqualThreshold(m1.At(r, c), cols[c][r], 1e-5) {
t.Errorf("Matrix element at (%d,%d) wrong when built from cols. Got: %f, Expected: %f", r, c, m1.At(r, c), cols[c][r])
}
}
}
v0, v1, v2, v3 = m1.Cols()
r2 := [4]Vec3{v0, v1, v2, v3}
t.Logf("3x4 matrix returned cols: %v", r2)
for r := 0; r < 3; r++ {
for c := 0; c < 4; c++ {
if !FloatEqualThreshold(r2[c][r], cols[c][r], 1e-5) {
t.Errorf("Matrix element at (%d,%d) wrong when rows are gotten. Got: %f, Expected: %f", r, c, r2[c][r], cols[c][r])
}
}
}
}
// Square matrix
func TestMatColsSquare(t *testing.T) {
t.Parallel()
v0 := Vec4{1, 2, 3, 4}
v1 := Vec4{5, 6, 7, 8}
v2 := Vec4{9, 10, 11, 12}
v3 := Vec4{13, 14, 15, 16}
cols := [4]Vec4{v0, v1, v2, v3}
m1 := Mat4FromCols(v0, v1, v2, v3)
t.Logf("4x4 matrix as built from cols: %v", m1)
for r := 0; r < 4; r++ {
for c := 0; c < 4; c++ {
if !FloatEqualThreshold(m1.At(r, c), cols[c][r], 1e-5) {
t.Errorf("Matrix element at (%d,%d) wrong when built from rows. Got: %f, Expected: %f", r, c, m1.At(r, c), cols[c][r])
}
}
}
v0, v1, v2, v3 = m1.Cols()
r2 := [4]Vec4{v0, v1, v2, v3}
t.Logf("4x4 matrix returned cols: %v", r2)
for r := 0; r < 4; r++ {
for c := 0; c < 4; c++ {
if !FloatEqualThreshold(r2[c][r], cols[c][r], 1e-5) {
t.Errorf("Matrix element at (%d,%d) wrong when rows are gotten. Got: %f, Expected: %f", r, c, r2[c][r], cols[c][r])
}
}
}
}
func TestTransposeTall(t *testing.T) {
t.Parallel()
m := Mat3x2FromCols(
Vec3{1, 2, 3},
Vec3{4, 5, 6},
)
transpose := m.Transpose()
correct := Mat2x3FromRows(
Vec3{1, 2, 3},
Vec3{4, 5, 6},
)
if !correct.ApproxEqualThreshold(transpose, 1e-4) {
t.Errorf("Transpose not correct. Got: %v, expected: %v", transpose, correct)
}
}
func TestTransposeWide(t *testing.T) {
t.Parallel()
m := Mat2x3FromCols(
Vec2{1, 2},
Vec2{3, 4},
Vec2{5, 6},
)
transpose := m.Transpose()
correct := Mat3x2FromRows(
Vec2{1, 2},
Vec2{3, 4},
Vec2{5, 6},
)
if !correct.ApproxEqualThreshold(transpose, 1e-4) {
t.Errorf("Transpose not correct. Got: %v, expected: %v", transpose, correct)
}
}
func TestTransposeSquare(t *testing.T) {
t.Parallel()
m := Mat3FromCols(
Vec3{1, 2, 3},
Vec3{4, 5, 6},
Vec3{7, 8, 9},
)
transpose := m.Transpose()
correct := Mat3FromRows(
Vec3{1, 2, 3},
Vec3{4, 5, 6},
Vec3{7, 8, 9},
)
if !correct.ApproxEqualThreshold(transpose, 1e-4) {
t.Errorf("Transpose not correct. Got: %v, expected: %v", transpose, correct)
}
}
func TestAtSet(t *testing.T) {
t.Parallel()
m := Mat3{1, 2, 3, 4, 5, 6, 7, 8, 9}
v := m.At(0, 2)
if !FloatEqualThreshold(v, 7, 1e-4) {
t.Errorf("Incorrect value gotten by At: %v, expected %v", v, 3)
}
m.Set(0, 2, 9001)
v = m.At(0, 2)
if !FloatEqualThreshold(v, 9001, 1e-4) {
t.Errorf("Value set by Set not gotten by At: %v, expected %v", v, 9001)
}
correctMat := Mat3{1, 2, 3, 4, 5, 6, 9001, 8, 9}
if !correctMat.ApproxEqualThreshold(m, 1e-4) {
t.Errorf("After set, not equal to matrix that should be identical. Got: %v, expected: %v", m, correctMat)
}
}
func TestDiagTrace(t *testing.T) {
t.Parallel()
m := Diag4(Vec4{1, 2, 3, 4})
tr := m.Trace()
if !FloatEqualThreshold(tr, 10, 1e-4) {
t.Errorf("Trace of matrix seeded with diagonal vector {1,2,3,4} not equal to 10. Got %v", tr)
}
}
func TestMatAbs(t *testing.T) {
t.Parallel()
m := Mat3{1, -3, 4, 5, -6, 8, -9, 10, 0}
result := Mat3{1, 3, 4, 5, 6, 8, 9, 10, 0}
m = m.Abs()
if !result.ApproxEqualThreshold(m, 1e-6) {
t.Errorf("Matrix absolute value does not work properly. Got: %v, Expected: %v", m, result)
}
}
func TestString(t *testing.T) {
m := Ident4()
str := fmt.Sprintf(` %[2]f %[1]f %[1]f %[1]f
%[1]f %[2]f %[1]f %[1]f
%[1]f %[1]f %[2]f %[1]f
%[1]f %[1]f %[1]f %[2]f
`, 0.0, 1.0)
if str != m.String() {
t.Errorf("Mat string conversion not working got %q expected %q", m.String(), str)
}
}
func BenchmarkMatAdd(b *testing.B) {
b.StopTimer()
rand := rand.New(rand.NewSource(int64(time.Now().Nanosecond())))
for i := 0; i < b.N; i++ {
b.StopTimer()
m1 := Mat4{}
m2 := Mat4{}
for j := 0; j < len(m1); j++ {
m1[j], m2[j] = rand.Float32(), rand.Float32()
}
b.StartTimer()
m1 = m1.Add(m2)
}
}
func BenchmarkMatScale(b *testing.B) {
b.StopTimer()
rand := rand.New(rand.NewSource(int64(time.Now().Nanosecond())))
for i := 0; i < b.N; i++ {
b.StopTimer()
m1 := Mat4{}
for j := 0; j < len(m1); j++ {
m1[j] = rand.Float32()
}
c := rand.Float32()
b.StartTimer()
m1 = m1.Mul(c)
}
}
func BenchmarkMatMul(b *testing.B) {
b.StopTimer()
rand := rand.New(rand.NewSource(int64(time.Now().Nanosecond())))
for i := 0; i < b.N; i++ {
b.StopTimer()
m1 := Mat4{}
m2 := Mat4{}
for j := 0; j < len(m1); j++ {
m1[j], m2[j] = rand.Float32(), rand.Float32()
}
b.StartTimer()
m1 = m1.Mul4(m2)
}
}
func BenchmarkMatTranspose(b *testing.B) {
b.StopTimer()
rand := rand.New(rand.NewSource(int64(time.Now().Nanosecond())))
for i := 0; i < b.N; i++ {
b.StopTimer()
m1 := Mat4{}
for j := 0; j < len(m1); j++ {
m1[j] = rand.Float32()
}
b.StartTimer()
_ = m1.Transpose()
}
}
func BenchmarkMatDet(b *testing.B) {
b.StopTimer()
rand := rand.New(rand.NewSource(int64(time.Now().Nanosecond())))
for i := 0; i < b.N; i++ {
b.StopTimer()
m1 := Mat4{}
for j := 0; j < len(m1); j++ {
m1[j] = rand.Float32()
}
b.StartTimer()
_ = m1.Det()
}
}
func BenchmarkMatInv(b *testing.B) {
b.StopTimer()
rand := rand.New(rand.NewSource(int64(time.Now().Nanosecond())))
for i := 0; i < b.N; i++ {
b.StopTimer()
m1 := Mat4{}
for j := 0; j < len(m1); j++ {
m1[j] = rand.Float32()
}
b.StartTimer()
m1 = m1.Inv()
}
}