mirror of
https://github.com/gonum/gonum.git
synced 2025-10-10 09:30:13 +08:00
spatial/r3: provide safe option for Mat operations
This commit is contained in:
@@ -5,7 +5,6 @@
|
||||
package r3
|
||||
|
||||
import (
|
||||
"math"
|
||||
"testing"
|
||||
|
||||
"golang.org/x/exp/rand"
|
||||
@@ -13,55 +12,108 @@ import (
|
||||
"gonum.org/v1/gonum/mat"
|
||||
)
|
||||
|
||||
func TestMatAdd(t *testing.T) {
|
||||
const tol = 1e-16
|
||||
rnd := rand.New(rand.NewSource(1))
|
||||
for tc := 0; tc < 20; tc++ {
|
||||
a := randomMat(rnd)
|
||||
b := randomMat(rnd)
|
||||
var (
|
||||
want mat.Dense
|
||||
got Mat
|
||||
)
|
||||
want.Add(a, b)
|
||||
got.Add(a, b)
|
||||
if !mat.EqualApprox(&got, &want, tol) {
|
||||
t.Errorf("unexpected result for matrix add:\ngot:\n%v\nwant:\n%v", mat.Formatted(&got), mat.Formatted(&want))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestMatSub(t *testing.T) {
|
||||
const tol = 1e-16
|
||||
rnd := rand.New(rand.NewSource(1))
|
||||
for tc := 0; tc < 20; tc++ {
|
||||
a := randomMat(rnd)
|
||||
b := randomMat(rnd)
|
||||
var (
|
||||
want mat.Dense
|
||||
got Mat
|
||||
)
|
||||
want.Sub(a, b)
|
||||
got.Sub(a, b)
|
||||
if !mat.EqualApprox(&got, &want, tol) {
|
||||
t.Errorf("unexpected result for matrix subtract:\ngot:\n%v\nwant:\n%v", mat.Formatted(&got), mat.Formatted(&want))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestMatMul(t *testing.T) {
|
||||
const tol = 1e-14
|
||||
rnd := rand.New(rand.NewSource(1))
|
||||
for tc := 0; tc < 20; tc++ {
|
||||
a := randomMat(rnd)
|
||||
b := randomMat(rnd)
|
||||
var (
|
||||
want mat.Dense
|
||||
got Mat
|
||||
)
|
||||
want.Mul(a, b)
|
||||
got.Mul(a, b)
|
||||
if !mat.EqualApprox(&got, &want, tol) {
|
||||
t.Errorf("unexpected result for matrix multiply:\ngot:\n%v\nwant:\n%v", mat.Formatted(&got), mat.Formatted(&want))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestMatScale(t *testing.T) {
|
||||
const tol = 1e-12
|
||||
const tol = 1e-16
|
||||
rnd := rand.New(rand.NewSource(1))
|
||||
for tc := 0; tc < 20; tc++ {
|
||||
v := rnd.Float64()
|
||||
a := randomMat(rnd)
|
||||
gotmat := NewMat(nil)
|
||||
gotmat.Scale(v, a)
|
||||
for iv := range a.data {
|
||||
i := iv / 3
|
||||
j := iv % 3
|
||||
expect := v * a.At(i, j)
|
||||
got := gotmat.At(i, j)
|
||||
if math.Abs(got-expect) > tol {
|
||||
t.Errorf(
|
||||
"case %d: got=%v, want=%v",
|
||||
tc, got, expect)
|
||||
}
|
||||
var (
|
||||
want mat.Dense
|
||||
got Mat
|
||||
)
|
||||
want.Scale(v, a)
|
||||
got.Scale(v, a)
|
||||
if !mat.EqualApprox(&got, &want, tol) {
|
||||
t.Errorf("unexpected result for matrix scale:\ngot:\n%v\nwant:\n%v", mat.Formatted(&got), mat.Formatted(&want))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestMatCloneFrom(t *testing.T) {
|
||||
const tol = 1e-16
|
||||
rnd := rand.New(rand.NewSource(1))
|
||||
for tc := 0; tc < 20; tc++ {
|
||||
a := randomMat(rnd)
|
||||
gotmat := NewMat(nil)
|
||||
gotmat.CloneFrom(a)
|
||||
if !mat.Equal(a, gotmat) {
|
||||
t.Error("Clonefrom fail")
|
||||
want := randomMat(rnd)
|
||||
got := NewMat(nil)
|
||||
got.CloneFrom(want)
|
||||
if !mat.EqualApprox(got, want, tol) {
|
||||
t.Errorf("unexpected result from CloneFrom:\ngot:\n%v\nwant:\n%v", mat.Formatted(got), mat.Formatted(want))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestSkew(t *testing.T) {
|
||||
const tol = 1e-16
|
||||
rnd := rand.New(rand.NewSource(1))
|
||||
for tc := 0; tc < 20; tc++ {
|
||||
v1 := randomVec(rnd)
|
||||
v2 := randomVec(rnd)
|
||||
sk := Skew(v1)
|
||||
want := Cross(v1, v2)
|
||||
got := sk.MulVec(v2)
|
||||
expect := Cross(v1, v2)
|
||||
if got != expect {
|
||||
t.Error("r3.Cross(v1,v2) not match with r3.Skew(v1)*v2")
|
||||
if d := want.Sub(got); d.Dot(d) > tol {
|
||||
t.Errorf("r3.Cross(v1,v2) does not agree with r3.Skew(v1)*v2: got:%v want:%v", got, want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestTranspose(t *testing.T) {
|
||||
const tol = 1e-16
|
||||
rnd := rand.New(rand.NewSource(1))
|
||||
for tc := 0; tc < 20; tc++ {
|
||||
d := mat.NewDense(3, 3, nil)
|
||||
@@ -70,23 +122,24 @@ func TestTranspose(t *testing.T) {
|
||||
mt := m.T()
|
||||
dt := d.T()
|
||||
if !mat.Equal(mt, dt) {
|
||||
t.Error("Dense.T() not equal to r3.Mat.T()")
|
||||
t.Errorf("Dense.T() not equal to r3.Mat.T():\ngot:\n%v\nwant:\n%v", mat.Formatted(mt), mat.Formatted(dt))
|
||||
}
|
||||
vd := mat.NewVecDense(3, nil)
|
||||
v := randomVec(rnd)
|
||||
vd.SetVec(0, v.X)
|
||||
vd.SetVec(1, v.Y)
|
||||
vd.SetVec(2, v.Z)
|
||||
got := m.MulVecTrans(v)
|
||||
vd.MulVec(dt, vd)
|
||||
if vd.AtVec(0) != got.X || vd.AtVec(1) != got.Y || vd.AtVec(2) != got.Z {
|
||||
t.Error("VecDense.MulVec(dense.T()) not equal to r3.Mat.MulVec(r3.Vec)")
|
||||
want := Vec{X: vd.AtVec(0), Y: vd.AtVec(1), Z: vd.AtVec(2)}
|
||||
got := m.MulVecTrans(v)
|
||||
if d := want.Sub(got); d.Dot(d) > tol {
|
||||
t.Errorf("VecDense.MulVec(dense.T()) not agree with r3.Mat.MulVec(r3.Vec): got:%v want:%v", got, want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func randomMat(rnd *rand.Rand) *Mat {
|
||||
m := Mat{data: new([3][3]float64)}
|
||||
m := Mat{new(array)}
|
||||
for iv := 0; iv < 9; iv++ {
|
||||
i := iv / 3
|
||||
j := iv % 3
|
||||
|
Reference in New Issue
Block a user