// Copyright ©2015 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 testlapack import ( "log" "testing" "gonum.org/v1/gonum/floats" "gonum.org/v1/gonum/lapack" ) type Dgeconer interface { Dlanger Dgetrfer Dgecon(norm lapack.MatrixNorm, n int, a []float64, lda int, anorm float64, work []float64, iwork []int) float64 } func DgeconTest(t *testing.T, impl Dgeconer) { for _, test := range []struct { m int n int a []float64 condOne float64 condInf float64 }{ { a: []float64{ 8, 1, 6, 3, 5, 7, 4, 9, 2, }, m: 3, n: 3, condOne: 3.0 / 16, condInf: 3.0 / 16, }, { a: []float64{ 2, 9, 3, 2, 10, 9, 9, 3, 1, 1, 5, 2, 8, 4, 10, 2, }, m: 4, n: 4, condOne: 0.024740155174938, condInf: 0.012034465570035, }, // Dgecon does not match Dpocon for this case. https://github.com/xianyi/OpenBLAS/issues/664. { a: []float64{ 2.9995576045549965, -2.0898894566158663, 3.965560740124006, -2.0898894566158663, 1.9634729526261008, -2.8681002706874104, 3.965560740124006, -2.8681002706874104, 5.502416670471008, }, m: 3, n: 3, condOne: 0.024054837369015203, condInf: 0.024054837369015203, }, } { m := test.m n := test.n lda := n a := make([]float64, len(test.a)) copy(a, test.a) ipiv := make([]int, min(m, n)) // Find the norms of the original matrix. work := make([]float64, 4*n) oneNorm := impl.Dlange(lapack.MaxColumnSum, m, n, a, lda, work) infNorm := impl.Dlange(lapack.MaxRowSum, m, n, a, lda, work) // Compute LU factorization of a. impl.Dgetrf(m, n, a, lda, ipiv) // Compute the condition number iwork := make([]int, n) condOne := impl.Dgecon(lapack.MaxColumnSum, n, a, lda, oneNorm, work, iwork) condInf := impl.Dgecon(lapack.MaxRowSum, n, a, lda, infNorm, work, iwork) // Error if not the same order, otherwise log the difference. if !floats.EqualWithinAbsOrRel(condOne, test.condOne, 1e0, 1e0) { t.Errorf("One norm mismatch. Want %v, got %v.", test.condOne, condOne) } else if !floats.EqualWithinAbsOrRel(condOne, test.condOne, 1e-14, 1e-14) { log.Printf("Dgecon one norm mismatch. Want %v, got %v.", test.condOne, condOne) } if !floats.EqualWithinAbsOrRel(condInf, test.condInf, 1e0, 1e0) { t.Errorf("One norm mismatch. Want %v, got %v.", test.condInf, condInf) } else if !floats.EqualWithinAbsOrRel(condInf, test.condInf, 1e-14, 1e-14) { log.Printf("Dgecon one norm mismatch. Want %v, got %v.", test.condInf, condInf) } } }