// 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 ( "testing" "golang.org/x/exp/rand" "gonum.org/v1/gonum/blas" "gonum.org/v1/gonum/blas/blas64" "gonum.org/v1/gonum/floats" ) type Dlarfer interface { Dlarf(side blas.Side, m, n int, v []float64, incv int, tau float64, c []float64, ldc int, work []float64) } func DlarfTest(t *testing.T, impl Dlarfer) { rnd := rand.New(rand.NewSource(1)) for i, test := range []struct { m, n, ldc int incv, lastv int lastr, lastc int tau float64 }{ { m: 3, n: 2, ldc: 2, incv: 4, lastv: 1, lastr: 2, lastc: 1, tau: 2, }, { m: 2, n: 3, ldc: 3, incv: 4, lastv: 1, lastr: 1, lastc: 2, tau: 2, }, { m: 2, n: 3, ldc: 3, incv: 4, lastv: 1, lastr: 0, lastc: 1, tau: 2, }, { m: 2, n: 3, ldc: 3, incv: 4, lastv: 0, lastr: 0, lastc: 1, tau: 2, }, { m: 10, n: 10, ldc: 10, incv: 4, lastv: 6, lastr: 9, lastc: 8, tau: 2, }, } { // Construct a random matrix. c := make([]float64, test.ldc*test.m) for i := 0; i <= test.lastr; i++ { for j := 0; j <= test.lastc; j++ { c[i*test.ldc+j] = rnd.Float64() } } cCopy := make([]float64, len(c)) copy(cCopy, c) cCopy2 := make([]float64, len(c)) copy(cCopy2, c) // Test with side right. sz := max(test.m, test.n) // so v works for both right and left side. v := make([]float64, test.incv*sz+1) // Fill with nonzero entries up until lastv. for i := 0; i <= test.lastv; i++ { v[i*test.incv] = rnd.Float64() } // Construct h explicitly to compare. h := make([]float64, test.n*test.n) for i := 0; i < test.n; i++ { h[i*test.n+i] = 1 } hMat := blas64.General{ Rows: test.n, Cols: test.n, Stride: test.n, Data: h, } vVec := blas64.Vector{ Inc: test.incv, Data: v, } blas64.Ger(-test.tau, vVec, vVec, hMat) // Apply multiplication (2nd copy is to avoid aliasing). cMat := blas64.General{ Rows: test.m, Cols: test.n, Stride: test.ldc, Data: cCopy, } cMat2 := blas64.General{ Rows: test.m, Cols: test.n, Stride: test.ldc, Data: cCopy2, } blas64.Gemm(blas.NoTrans, blas.NoTrans, 1, cMat2, hMat, 0, cMat) // cMat now stores the true answer. Compare with the function call. work := make([]float64, sz) impl.Dlarf(blas.Right, test.m, test.n, v, test.incv, test.tau, c, test.ldc, work) if !floats.EqualApprox(c, cMat.Data, 1e-14) { t.Errorf("Dlarf mismatch right, case %v. Want %v, got %v", i, cMat.Data, c) } // Test on the left side. copy(c, cCopy2) copy(cCopy, c) // Construct h. h = make([]float64, test.m*test.m) for i := 0; i < test.m; i++ { h[i*test.m+i] = 1 } hMat = blas64.General{ Rows: test.m, Cols: test.m, Stride: test.m, Data: h, } blas64.Ger(-test.tau, vVec, vVec, hMat) blas64.Gemm(blas.NoTrans, blas.NoTrans, 1, hMat, cMat2, 0, cMat) impl.Dlarf(blas.Left, test.m, test.n, v, test.incv, test.tau, c, test.ldc, work) if !floats.EqualApprox(c, cMat.Data, 1e-14) { t.Errorf("Dlarf mismatch left, case %v. Want %v, got %v", i, cMat.Data, c) } } }