From 77927b49f4b9919c4eb7bd67be9db9914933625e Mon Sep 17 00:00:00 2001 From: btracey Date: Thu, 1 Oct 2015 22:37:31 -0600 Subject: [PATCH] Add Dlacpy and tests --- README.md | 2 +- cgo/clapack/clapack.go | 8 ++++ cgo/clapack/genLapack.pl | 24 +++++++++++- cgo/lapack.go | 9 +++++ cgo/lapack_test.go | 4 ++ lapack64/lapack64.go | 2 +- native/dlacpy.go | 40 +++++++++++++++++++ native/lapack_test.go | 4 ++ testlapack/dlacpy.go | 84 ++++++++++++++++++++++++++++++++++++++++ 9 files changed, 174 insertions(+), 3 deletions(-) create mode 100644 native/dlacpy.go create mode 100644 testlapack/dlacpy.go diff --git a/README.md b/README.md index b2fc7b2..6e3bf1c 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -Gonum LAPACK [![Build Status](https://travis-ci.org/gonum/lapack.svg?branch=master)](https://travis-ci.org/gonum/lapack) [![Coverage Status](https://img.shields.io/coveralls/gonum/lapack.svg)](https://coveralls.io/r/gonum/lapack) +Gonum LAPACK [![Build Status](https://travis-ci.org/gonum/lapack.svg?branch=master)](https://travis-ci.org/gonum/lapack) [![Coverage Status](https://coveralls.io/repos/gonum/lapack/badge.svg?branch=master&service=github)](https://coveralls.io/github/gonum/lapack?branch=master) ====== A collection of packages to provide LAPACK functionality for the Go programming diff --git a/cgo/clapack/clapack.go b/cgo/clapack/clapack.go index fb13700..bf5a81e 100644 --- a/cgo/clapack/clapack.go +++ b/cgo/clapack/clapack.go @@ -2917,6 +2917,8 @@ func Slacpy(ul blas.Uplo, m int, n int, a []float32, lda int, b []float32, ldb i ul = 'U' case blas.Lower: ul = 'L' + case blas.All: + ul = 'A' default: panic("lapack: illegal triangle") } @@ -2930,6 +2932,8 @@ func Dlacpy(ul blas.Uplo, m int, n int, a []float64, lda int, b []float64, ldb i ul = 'U' case blas.Lower: ul = 'L' + case blas.All: + ul = 'A' default: panic("lapack: illegal triangle") } @@ -2943,6 +2947,8 @@ func Clacpy(ul blas.Uplo, m int, n int, a []complex64, lda int, b []complex64, l ul = 'U' case blas.Lower: ul = 'L' + case blas.All: + ul = 'A' default: panic("lapack: illegal triangle") } @@ -2956,6 +2962,8 @@ func Zlacpy(ul blas.Uplo, m int, n int, a []complex128, lda int, b []complex128, ul = 'U' case blas.Lower: ul = 'L' + case blas.All: + ul = 'A' default: panic("lapack: illegal triangle") } diff --git a/cgo/clapack/genLapack.pl b/cgo/clapack/genLapack.pl index 720cb4f..2548d6c 100644 --- a/cgo/clapack/genLapack.pl +++ b/cgo/clapack/genLapack.pl @@ -124,6 +124,12 @@ package clapack "double_return" => "float64" ); +# allUplo is a list of routines that allow 'A' for their uplo argument. +# The list keys are truncated by one character to cover all four numeric types. +our %allUplo = ( + "lacpy" => undef +); + foreach my $line (@lines) { process($line); } @@ -225,7 +231,22 @@ sub processParamToGo { }; $var eq "uplo" && do { $var = "ul"; - my $bp = << "EOH"; + my $bp; + if (exists $allUplo{substr($func, 1)}) { + $bp = << "EOH"; +switch $var { +case blas.Upper: +$var = 'U' +case blas.Lower: +$var = 'L' +case blas.All: +$var = 'A' +default: +panic("lapack: illegal triangle") +} +EOH + } else { + $bp = << "EOH"; switch $var { case blas.Upper: $var = 'U' @@ -235,6 +256,7 @@ sub processParamToGo { panic("lapack: illegal triangle") } EOH + } push @boilerplate, $bp; push @processed, $var." blas.Uplo"; next; }; diff --git a/cgo/lapack.go b/cgo/lapack.go index 3b86808..fdb6b42 100644 --- a/cgo/lapack.go +++ b/cgo/lapack.go @@ -67,6 +67,15 @@ type Implementation struct{} var _ lapack.Float64 = Implementation{} +// Dlacpy copies the elements of A specified by uplo into B. Uplo can specify +// a triangular portion with blas.Upper or blas.Lower, or can specify all of the +// elemest with blas.All. +func (impl Implementation) Dlacpy(uplo blas.Uplo, m, n int, a []float64, lda int, b []float64, ldb int) { + checkMatrix(m, n, a, lda) + checkMatrix(m, n, b, ldb) + clapack.Dlacpy(uplo, m, n, a, lda, b, ldb) +} + // Dlange computes the matrix norm of the general m×n matrix a. The input norm // specifies the norm computed. // lapack.MaxAbs: the maximum absolute value of an element. diff --git a/cgo/lapack_test.go b/cgo/lapack_test.go index 786e6f3..6ab342b 100644 --- a/cgo/lapack_test.go +++ b/cgo/lapack_test.go @@ -13,6 +13,10 @@ import ( var impl = Implementation{} +func TestDlacpy(t *testing.T) { + testlapack.DlacpyTest(t, impl) +} + func TestDlange(t *testing.T) { testlapack.DlangeTest(t, impl) } diff --git a/lapack64/lapack64.go b/lapack64/lapack64.go index 47b539d..c05b214 100644 --- a/lapack64/lapack64.go +++ b/lapack64/lapack64.go @@ -6,7 +6,7 @@ // calls, as specified in the netlib standard (www.netlib.org). // // The native Go routines are used by default, and the Use function can be used -// to set an alternate implementation. +// to set an alternative implementation. // // If the type of matrix (General, Symmetric, etc.) is known and fixed, it is // used in the wrapper signature. In many cases, however, the type of the matrix diff --git a/native/dlacpy.go b/native/dlacpy.go new file mode 100644 index 0000000..0836ca5 --- /dev/null +++ b/native/dlacpy.go @@ -0,0 +1,40 @@ +// 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 native + +import "github.com/gonum/blas" + +// Dlacpy copies the elements of A specified by uplo into B. Uplo can specify +// a triangular portion with blas.Upper or blas.Lower, or can specify all of the +// elemest with blas.All. +func (impl Implementation) Dlacpy(uplo blas.Uplo, m, n int, a []float64, lda int, b []float64, ldb int) { + checkMatrix(m, n, a, lda) + checkMatrix(m, n, b, ldb) + switch uplo { + default: + panic(badUplo) + case blas.Upper: + for i := 0; i < m; i++ { + for j := i; j < n; j++ { + b[i*ldb+j] = a[i*lda+j] + } + } + return + case blas.Lower: + for i := 0; i < m; i++ { + for j := 0; j < min(i, n); j++ { + b[i*ldb+j] = a[i*lda+j] + } + } + return + case blas.All: + for i := 0; i < m; i++ { + for j := 0; j < n; j++ { + b[i*ldb+j] = a[i*lda+j] + } + } + return + } +} diff --git a/native/lapack_test.go b/native/lapack_test.go index 508f5a5..54c4e54 100644 --- a/native/lapack_test.go +++ b/native/lapack_test.go @@ -52,6 +52,10 @@ func TestDgetrs(t *testing.T) { testlapack.DgetrsTest(t, impl) } +func TestDlacpy(t *testing.T) { + testlapack.DlacpyTest(t, impl) +} + func TestDlaev2(t *testing.T) { testlapack.Dlaev2Test(t, impl) } diff --git a/testlapack/dlacpy.go b/testlapack/dlacpy.go new file mode 100644 index 0000000..148bb48 --- /dev/null +++ b/testlapack/dlacpy.go @@ -0,0 +1,84 @@ +package testlapack + +import ( + "fmt" + "math/rand" + "testing" + + "github.com/gonum/blas" +) + +type Dlacpyer interface { + Dlacpy(uplo blas.Uplo, m, n int, a []float64, lda int, b []float64, ldb int) +} + +func DlacpyTest(t *testing.T, impl Dlacpyer) { + for _, uplo := range []blas.Uplo{blas.Upper, blas.Lower, blas.All} { + for _, test := range []struct { + m, n, lda, ldb int + }{ + {3, 5, 0, 0}, + {5, 5, 0, 0}, + {7, 5, 0, 0}, + + {3, 5, 10, 12}, + {5, 5, 10, 12}, + {7, 5, 10, 12}, + } { + m := test.m + n := test.n + lda := test.lda + if lda == 0 { + lda = n + } + ldb := test.ldb + if ldb == 0 { + ldb = n + } + a := make([]float64, m*lda) + for i := range a { + a[i] = rand.Float64() + } + b := make([]float64, m*ldb) + for i := range b { + b[i] = rand.Float64() + } + impl.Dlacpy(uplo, m, n, a, lda, b, ldb) + equal := true + switch uplo { + case blas.Upper: + for i := 0; i < m; i++ { + for j := i; j < n; j++ { + if b[i*ldb+j] != a[i*lda+j] { + equal = false + goto DoneCheck + } + } + } + case blas.Lower: + for i := 0; i < m; i++ { + for j := 0; j < min(i, n); j++ { + if b[i*ldb+j] != a[i*lda+j] { + equal = false + goto DoneCheck + } + } + } + case blas.All: + for i := 0; i < m; i++ { + for j := 0; j < n; j++ { + if b[i*ldb+j] != a[i*lda+j] { + equal = false + goto DoneCheck + } + } + } + } + DoneCheck: + if !equal { + fmt.Println(blas.Lower) + t.Errorf("Matrices not equal after copy. Uplo = %d, m = %d, n = %d", uplo, m, n) + } + } + } +}