mirror of
https://github.com/gonum/gonum.git
synced 2025-10-13 19:03:44 +08:00
244 lines
4.4 KiB
Go
244 lines
4.4 KiB
Go
// Copyright ©2013 The gonum 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 mat64
|
|
|
|
import (
|
|
"github.com/gonum/blas/cblas"
|
|
|
|
"fmt"
|
|
"testing"
|
|
check "launchpad.net/gocheck"
|
|
)
|
|
|
|
// Tests
|
|
func Test(t *testing.T) { check.TestingT(t) }
|
|
|
|
type S struct{}
|
|
|
|
var _ = check.Suite(&S{})
|
|
|
|
func leaksPanic(fn Panicker) (panicked bool) {
|
|
defer func() {
|
|
r := recover()
|
|
panicked = r != nil
|
|
}()
|
|
Maybe(fn)
|
|
return
|
|
}
|
|
|
|
func panics(fn func()) (panicked bool, message string) {
|
|
defer func() {
|
|
r := recover()
|
|
panicked = r != nil
|
|
message = fmt.Sprint(r)
|
|
}()
|
|
fn()
|
|
return
|
|
}
|
|
|
|
func (s *S) SetUpSuite(c *check.C) { blasEngine = cblas.Blas{} }
|
|
|
|
func flatten(f [][]float64) (r, c int, d []float64) {
|
|
for _, r := range f {
|
|
d = append(d, r...)
|
|
}
|
|
return len(f), len(f[0]), d
|
|
}
|
|
|
|
func unflatten(r, c int, d []float64) [][]float64 {
|
|
m := make([][]float64, r)
|
|
for i := 0; i < r; i++ {
|
|
m[i] = d[i*c : (i+1)*c]
|
|
}
|
|
return m
|
|
}
|
|
|
|
func eye() *Dense {
|
|
return NewDense(3, 3, []float64{
|
|
1, 0, 0,
|
|
0, 1, 0,
|
|
0, 0, 1,
|
|
})
|
|
}
|
|
|
|
func (s *S) TestMaybe(c *check.C) {
|
|
for i, test := range []struct {
|
|
fn Panicker
|
|
panics bool
|
|
}{
|
|
{
|
|
func() {},
|
|
false,
|
|
},
|
|
{
|
|
func() { panic("panic") },
|
|
true,
|
|
},
|
|
{
|
|
func() { panic(Error("panic")) },
|
|
false,
|
|
},
|
|
} {
|
|
c.Check(leaksPanic(test.fn), check.Equals, test.panics, check.Commentf("Test %d", i))
|
|
}
|
|
}
|
|
|
|
func (s *S) TestSolve(c *check.C) {
|
|
for _, test := range []struct {
|
|
name string
|
|
panics bool
|
|
a [][]float64
|
|
b [][]float64
|
|
x [][]float64
|
|
}{
|
|
{
|
|
name: "OneElement",
|
|
panics: false,
|
|
a: [][]float64{{6}},
|
|
b: [][]float64{{3}},
|
|
x: [][]float64{{0.5}},
|
|
},
|
|
{
|
|
name: "SquareIdentity",
|
|
panics: false,
|
|
a: [][]float64{
|
|
{1, 0, 0},
|
|
{0, 1, 0},
|
|
{0, 0, 1},
|
|
},
|
|
b: [][]float64{
|
|
{3},
|
|
{2},
|
|
{1},
|
|
},
|
|
x: [][]float64{
|
|
{3},
|
|
{2},
|
|
{1},
|
|
},
|
|
},
|
|
{
|
|
name: "Square",
|
|
panics: false,
|
|
a: [][]float64{
|
|
{0.8147, 0.9134, 0.5528},
|
|
{0.9058, 0.6324, 0.8723},
|
|
{0.1270, 0.0975, 0.7612},
|
|
},
|
|
b: [][]float64{
|
|
{0.278},
|
|
{0.547},
|
|
{0.958},
|
|
},
|
|
x: [][]float64{
|
|
{-0.932687281002860},
|
|
{0.303963920182067},
|
|
{1.375216503507109},
|
|
},
|
|
},
|
|
{
|
|
name: "ColumnMismatch",
|
|
panics: true,
|
|
a: [][]float64{
|
|
{0.6046602879796196, 0.9405090880450124, 0.6645600532184904},
|
|
{0.4377141871869802, 0.4246374970712657, 0.6868230728671094},
|
|
},
|
|
b: [][]float64{
|
|
{0.30091186058528707},
|
|
{0.5152126285020654},
|
|
{0.8136399609900968},
|
|
{0.12345},
|
|
},
|
|
x: [][]float64{
|
|
{-26.618512183136257},
|
|
{8.730387239011677},
|
|
{12.316510032082446},
|
|
{0.1234},
|
|
},
|
|
},
|
|
{
|
|
name: "WideMatrix",
|
|
panics: false,
|
|
a: [][]float64{
|
|
{0.8147, 0.9134, 0.5528},
|
|
{0.9058, 0.6324, 0.8723},
|
|
},
|
|
b: [][]float64{
|
|
{0.278},
|
|
{0.547},
|
|
},
|
|
x: [][]float64{
|
|
{0.25919787248965376},
|
|
{-0.25560256266441034},
|
|
{0.5432324059702451},
|
|
},
|
|
},
|
|
|
|
{
|
|
name: "Skinny1",
|
|
panics: false,
|
|
a: [][]float64{
|
|
{0.8147, 0.9134, 0.9},
|
|
{0.9058, 0.6324, 0.9},
|
|
{0.1270, 0.0975, 0.1},
|
|
{1.6, 2.8, -3.5},
|
|
},
|
|
b: [][]float64{
|
|
{0.278},
|
|
{0.547},
|
|
{-0.958},
|
|
{1.452},
|
|
},
|
|
x: [][]float64{
|
|
{0.820970340787782},
|
|
{-0.218604626527306},
|
|
{-0.212938815234215},
|
|
},
|
|
},
|
|
{
|
|
name: "Skinny2",
|
|
panics: false,
|
|
a: [][]float64{
|
|
{0.8147, 0.9134, 0.231, -1.65},
|
|
{0.9058, 0.6324, 0.9, 0.72},
|
|
{0.1270, 0.0975, 0.1, 1.723},
|
|
{1.6, 2.8, -3.5, 0.987},
|
|
{7.231, 9.154, 1.823, 0.9},
|
|
},
|
|
b: [][]float64{
|
|
{0.278, 8.635},
|
|
{0.547, 9.125},
|
|
{-0.958, -0.762},
|
|
{1.452, 1.444},
|
|
{1.999, -7.234},
|
|
},
|
|
x: [][]float64{
|
|
{1.863006789511373, 44.467887791812750},
|
|
{-1.127270935407224, -34.073794226035126},
|
|
{-0.527926457947330, -8.032133759788573},
|
|
{-0.248621916204897, -2.366366415805275},
|
|
},
|
|
},
|
|
} {
|
|
a := NewDense(flatten(test.a))
|
|
b := NewDense(flatten(test.b))
|
|
|
|
var x *Dense
|
|
|
|
fn := func() {
|
|
x = Solve(a, b)
|
|
}
|
|
|
|
panicked, message := panics(fn)
|
|
if panicked {
|
|
c.Check(panicked, check.Equals, test.panics, check.Commentf("Test %v panicked: %s", test.name, message))
|
|
continue
|
|
}
|
|
|
|
trueX := NewDense(flatten(test.x))
|
|
c.Check(x.EqualsApprox(trueX, 1e-13), check.Equals, true, check.Commentf("Test %v solution mismatch: Found %v, expected %v ", test.name, x, trueX))
|
|
}
|
|
}
|