├── .github ├── ISSUE_TEMPLATE.md └── PULL_REQUEST_TEMPLATE.md ├── .gitignore ├── .travis.yml ├── .travis ├── check-generate.sh ├── linux │ ├── ATLAS │ │ └── install.sh │ ├── OpenBLAS │ │ └── install.sh │ └── gonum │ │ └── install.sh └── test-coverage.sh ├── README.md ├── cgo ├── bench_test.go ├── lapack.go ├── lapack_test.go └── lapacke │ ├── generate.go │ ├── generate_lapacke.go │ ├── lapacke.go │ ├── lapacke.h │ ├── lapacke_config.h │ ├── lapacke_mangling.h │ └── lapacke_utils.h ├── internal └── testdata │ ├── dlahr2test │ └── main.go │ ├── dlaqr5test │ └── main.go │ ├── dlasqtest │ ├── Makefile │ ├── Readme.md │ ├── dcopy.f │ ├── disnan.f │ ├── dlaisnan.f │ ├── dlamch.f │ ├── dlas2.f │ ├── dlascl.f │ ├── dlasq1.f │ ├── dlasq2.f │ ├── dlasq3.f │ ├── dlasq4.f │ ├── dlasq5.f │ ├── dlasq6.f │ ├── dlasrt.f │ ├── ieeeck.f │ ├── ilaenv.f │ ├── iparmq.f │ ├── lsame.f │ ├── testdlasq1.f90 │ ├── testdlasq2.f90 │ ├── testdlasq3.f90 │ ├── testdlasq4.f90 │ └── xerbla.f │ ├── dsterftest │ ├── Makefile │ ├── disnan.f │ ├── dlae2.f │ ├── dlaisnan.f │ ├── dlamch.f │ ├── dlanst.f │ ├── dlapy2.f │ ├── dlascl.f │ ├── dlasrt.f │ ├── dlassq.f │ ├── dsterf.f │ ├── lsame.f │ ├── testdsterf.f90 │ └── xerbla.f │ └── netlib │ ├── daxpy.f │ ├── dcopy.f │ ├── dgemm.f │ ├── dgemv.f │ ├── dlabad.f │ ├── dlacpy.f │ ├── dlahr2.f │ ├── dlamch.f │ ├── dlapy2.f │ ├── dlaqr1.f │ ├── dlaqr5.f │ ├── dlarfg.f │ ├── dlaset.f │ ├── dnrm2.f │ ├── dscal.f │ ├── dtrmm.f │ ├── dtrmv.f │ ├── lsame.f │ ├── netlib.go │ └── xerbla.f ├── lapack.go ├── lapack64 └── lapack64.go ├── native ├── bench_test.go ├── dbdsqr.go ├── dgebak.go ├── dgebal.go ├── dgebd2.go ├── dgebrd.go ├── dgecon.go ├── dgeev.go ├── dgehd2.go ├── dgehrd.go ├── dgelq2.go ├── dgelqf.go ├── dgels.go ├── dgeql2.go ├── dgeqp3.go ├── dgeqr2.go ├── dgeqrf.go ├── dgerq2.go ├── dgerqf.go ├── dgesvd.go ├── dgetf2.go ├── dgetrf.go ├── dgetri.go ├── dgetrs.go ├── dggsvd3.go ├── dggsvp3.go ├── dhseqr.go ├── dlabrd.go ├── dlacn2.go ├── dlacpy.go ├── dlae2.go ├── dlaev2.go ├── dlaexc.go ├── dlags2.go ├── dlahqr.go ├── dlahr2.go ├── dlaln2.go ├── dlange.go ├── dlanst.go ├── dlansy.go ├── dlantr.go ├── dlanv2.go ├── dlapll.go ├── dlapmt.go ├── dlapy2.go ├── dlaqp2.go ├── dlaqps.go ├── dlaqr04.go ├── dlaqr1.go ├── dlaqr23.go ├── dlaqr5.go ├── dlarf.go ├── dlarfb.go ├── dlarfg.go ├── dlarft.go ├── dlarfx.go ├── dlartg.go ├── dlas2.go ├── dlascl.go ├── dlaset.go ├── dlasq1.go ├── dlasq2.go ├── dlasq3.go ├── dlasq4.go ├── dlasq5.go ├── dlasq6.go ├── dlasr.go ├── dlasrt.go ├── dlassq.go ├── dlasv2.go ├── dlaswp.go ├── dlasy2.go ├── dlatrd.go ├── dlatrs.go ├── doc.go ├── dorg2l.go ├── dorg2r.go ├── dorgbr.go ├── dorghr.go ├── dorgl2.go ├── dorglq.go ├── dorgql.go ├── dorgqr.go ├── dorgtr.go ├── dorm2r.go ├── dormbr.go ├── dormhr.go ├── dorml2.go ├── dormlq.go ├── dormqr.go ├── dormr2.go ├── dpocon.go ├── dpotf2.go ├── dpotrf.go ├── drscl.go ├── dsteqr.go ├── dsterf.go ├── dsyev.go ├── dsytd2.go ├── dsytrd.go ├── dtgsja.go ├── dtrcon.go ├── dtrevc3.go ├── dtrexc.go ├── dtrti2.go ├── dtrtri.go ├── dtrtrs.go ├── general.go ├── iladlc.go ├── iladlr.go ├── ilaenv.go ├── iparmq.go └── lapack_test.go └── testlapack ├── dbdsqr.go ├── dgebak.go ├── dgebal.go ├── dgebd2.go ├── dgebrd.go ├── dgecon.go ├── dgeev.go ├── dgeev_bench.go ├── dgehd2.go ├── dgehrd.go ├── dgelq2.go ├── dgelqf.go ├── dgels.go ├── dgeql2.go ├── dgeqp3.go ├── dgeqr2.go ├── dgeqrf.go ├── dgerq2.go ├── dgerqf.go ├── dgesvd.go ├── dgetf2.go ├── dgetrf.go ├── dgetri.go ├── dgetrs.go ├── dggsvd3.go ├── dggsvp3.go ├── dhseqr.go ├── dlabrd.go ├── dlacn2.go ├── dlacpy.go ├── dlae2.go ├── dlaev2.go ├── dlaexc.go ├── dlags2.go ├── dlahqr.go ├── dlahr2.go ├── dlaln2.go ├── dlange.go ├── dlanst.go ├── dlansy.go ├── dlantr.go ├── dlanv2.go ├── dlapll.go ├── dlapmt.go ├── dlapy2.go ├── dlaqp2.go ├── dlaqps.go ├── dlaqr04.go ├── dlaqr1.go ├── dlaqr23.go ├── dlaqr5.go ├── dlarf.go ├── dlarfb.go ├── dlarfg.go ├── dlarft.go ├── dlarfx.go ├── dlartg.go ├── dlas2.go ├── dlascl.go ├── dlaset.go ├── dlasq1.go ├── dlasq2.go ├── dlasq3.go ├── dlasq4.go ├── dlasq5.go ├── dlasr.go ├── dlasrt.go ├── dlasv2.go ├── dlaswp.go ├── dlasy2.go ├── dlatrd.go ├── dlatrs.go ├── dorg2l.go ├── dorg2r.go ├── dorgbr.go ├── dorghr.go ├── dorgl2.go ├── dorglq.go ├── dorgql.go ├── dorgqr.go ├── dorgtr.go ├── dorm2r.go ├── dormbr.go ├── dormhr.go ├── dorml2.go ├── dormlq.go ├── dormqr.go ├── dormr2.go ├── dpocon.go ├── dpotf2.go ├── dpotrf.go ├── drscl.go ├── dsteqr.go ├── dsterf.go ├── dsyev.go ├── dsytd2.go ├── dsytrd.go ├── dtgsja.go ├── dtrcon.go ├── dtrevc3.go ├── dtrexc.go ├── dtrti2.go ├── dtrtri.go ├── fortran.go ├── general.go ├── iladlc.go ├── iladlr.go ├── matgen.go ├── matgen_test.go ├── test_matrices.go └── testdata ├── dlahr2data.json.gz └── dlaqr5data.json.gz /.github/ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | ### This repository is no longer actively maintained. 2 | 3 | Development of the packages in this repository has moved to https://github.com/gonum/gonum. 4 | Please file issues [there](https://github.com/gonum/gonum/issues) after having checked that your issue has not been fixed. 5 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | ### This repository is no longer actively maintained. 2 | 3 | Development of the packages in this repository has moved to https://github.com/gonum/gonum. 4 | Please send pull requests [there](https://github.com/gonum/gonum/pulls) after having checked that your addition has not already been made. 5 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gonum/lapack/e4cdc5a0bff924bb10be88482e635bd40429f65e/.gitignore -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: required 2 | 3 | language: go 4 | 5 | env: 6 | matrix: 7 | - BLAS_LIB=OpenBLAS 8 | - BLAS_LIB=gonum 9 | # Does not currently link correctly. Note that there is an issue with drotgm in ATLAS. 10 | # - BLAS_LIB=ATLAS 11 | # If we can get multiarch builds on travis. 12 | # There are some issues with the Accellerate implementation. 13 | #- BLAS_LIB=Accellerate 14 | 15 | # Versions of go that are explicitly supported by gonum. 16 | go: 17 | - 1.5.4 18 | - 1.6.3 19 | - 1.7.3 20 | 21 | # Cache used to persist the compiled BLAS library between CI calls. 22 | cache: 23 | directories: 24 | - .travis/OpenBLAS.cache 25 | 26 | # Required for coverage. 27 | before_install: 28 | - go get golang.org/x/tools/cmd/cover 29 | - go get github.com/mattn/goveralls 30 | - go get github.com/cznic/cc 31 | - go get github.com/gonum/internal/binding 32 | 33 | # Install the appropriate BLAS library. 34 | install: 35 | - bash .travis/$TRAVIS_OS_NAME/$BLAS_LIB/install.sh 36 | 37 | # Get deps, build, test, and ensure the code is gofmt'ed. 38 | # If we are building as gonum, then we have access to the coveralls api key, so we can run coverage as well. 39 | script: 40 | - if [[ "$BLAS_LIB" == "gonum" ]]; then pushd native; fi 41 | - go get -d -t -v ./... 42 | - go build -v ./... 43 | - go test -v ./... 44 | - test -z "$(gofmt -d *.go)" 45 | - if [[ $TRAVIS_SECURE_ENV_VARS = "true" ]]; then bash -c "${TRAVIS_BUILD_DIR}/.travis/test-coverage.sh"; fi 46 | # This is run last since it alters the tree. 47 | - ${TRAVIS_BUILD_DIR}/.travis/check-generate.sh 48 | -------------------------------------------------------------------------------- /.travis/check-generate.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -ex 3 | 4 | go generate github.com/gonum/lapack/cgo/lapacke 5 | if [ -n "$(git diff)" ]; then 6 | exit 1 7 | fi 8 | -------------------------------------------------------------------------------- /.travis/linux/ATLAS/install.sh: -------------------------------------------------------------------------------- 1 | set -ex 2 | 3 | # fetch and install ATLAS 4 | sudo apt-get update -qq 5 | sudo apt-get install -qq libatlas-base-dev 6 | 7 | 8 | # fetch and install gonum/blas and gonum/matrix 9 | export CGO_LDFLAGS="-L/usr/lib -latlas -llapack_atlas" 10 | go get github.com/gonum/blas 11 | go get github.com/gonum/matrix/mat64 12 | 13 | # install lapack against ATLAS 14 | pushd cgo/lapacke 15 | go install -v -x 16 | popd 17 | 18 | # travis compiles commands in script and then executes in bash. By adding 19 | # set -e we are changing the travis build script's behavior, and the set 20 | # -e lives on past the commands we are providing it. Some of the travis 21 | # commands are supposed to exit with non zero status, but then continue 22 | # executing. set -x makes the travis log files extremely verbose and 23 | # difficult to understand. 24 | # 25 | # see travis-ci/travis-ci#5120 26 | set +ex 27 | -------------------------------------------------------------------------------- /.travis/linux/OpenBLAS/install.sh: -------------------------------------------------------------------------------- 1 | set -ex 2 | 3 | CACHE_DIR=${TRAVIS_BUILD_DIR}/.travis/${BLAS_LIB}.cache 4 | 5 | # fetch fortran to build OpenBLAS 6 | sudo apt-get update -qq && sudo apt-get install -qq gfortran 7 | 8 | # check if cache exists 9 | if [ -e ${CACHE_DIR}/last_commit_id ]; then 10 | echo "Cache $CACHE_DIR hit" 11 | LAST_COMMIT="$(git ls-remote git://github.com/xianyi/OpenBLAS HEAD | grep -o '^\S*')" 12 | CACHED_COMMIT="$(cat ${CACHE_DIR}/last_commit_id)" 13 | # determine current OpenBLAS master commit id and compare 14 | # with commit id in cache directory 15 | if [ "$LAST_COMMIT" != "$CACHED_COMMIT" ]; then 16 | echo "Cache Directory $CACHE_DIR has stale commit" 17 | # if commit is different, delete the cache 18 | rm -rf ${CACHE_DIR} 19 | fi 20 | fi 21 | 22 | if [ ! -e ${CACHE_DIR}/last_commit_id ]; then 23 | # Clear cache. 24 | rm -rf ${CACHE_DIR} 25 | 26 | # cache generation 27 | echo "Building cache at $CACHE_DIR" 28 | mkdir ${CACHE_DIR} 29 | sudo git clone --depth=1 git://github.com/xianyi/OpenBLAS 30 | 31 | pushd OpenBLAS 32 | sudo make FC=gfortran &> /dev/null && sudo make PREFIX=${CACHE_DIR} install 33 | popd 34 | 35 | curl http://www.netlib.org/blas/blast-forum/cblas.tgz | tar -zx 36 | 37 | pushd CBLAS 38 | sudo mv Makefile.LINUX Makefile.in 39 | sudo BLLIB=${CACHE_DIR}/lib/libopenblas.a make alllib 40 | sudo mv lib/cblas_LINUX.a ${CACHE_DIR}/lib/libcblas.a 41 | popd 42 | 43 | # Record commit id used to generate cache. 44 | pushd OpenBLAS 45 | echo $(git rev-parse HEAD) > ${CACHE_DIR}/last_commit_id 46 | popd 47 | 48 | fi 49 | 50 | # copy the cache files into /usr 51 | sudo cp -r ${CACHE_DIR}/* /usr/ 52 | 53 | # install gonum/blas against OpenBLAS 54 | # fetch and install gonum/blas 55 | export CGO_LDFLAGS="-L/usr/lib -lopenblas" 56 | go get github.com/gonum/blas 57 | 58 | # install lapacke against OpenBLAS 59 | pushd cgo/lapacke 60 | go install -v -x 61 | popd 62 | 63 | # travis compiles commands in script and then executes in bash. By adding 64 | # set -e we are changing the travis build script's behavior, and the set 65 | # -e lives on past the commands we are providing it. Some of the travis 66 | # commands are supposed to exit with non zero status, but then continue 67 | # executing. set -x makes the travis log files extremely verbose and 68 | # difficult to understand. 69 | # 70 | # see travis-ci/travis-ci#5120 71 | set +ex 72 | -------------------------------------------------------------------------------- /.travis/linux/gonum/install.sh: -------------------------------------------------------------------------------- 1 | set -ex 2 | 3 | # fetch gonum/blas 4 | go get github.com/gonum/blas/native 5 | 6 | # travis compiles commands in script and then executes in bash. By adding 7 | # set -e we are changing the travis build script's behavior, and the set 8 | # -e lives on past the commands we are providing it. Some of the travis 9 | # commands are supposed to exit with non zero status, but then continue 10 | # executing. set -x makes the travis log files extremely verbose and 11 | # difficult to understand. 12 | # 13 | # see travis-ci/travis-ci#5120 14 | set +ex 15 | -------------------------------------------------------------------------------- /.travis/test-coverage.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | PROFILE_OUT=$PWD/profile.out 4 | ACC_OUT=$PWD/acc.out 5 | 6 | testCover() { 7 | # set the return value to 0 (succesful) 8 | retval=0 9 | # get the directory to check from the parameter. Default to '.' 10 | d=${1:-.} 11 | # skip if there are no Go files here 12 | ls $d/*.go &> /dev/null || return $retval 13 | # switch to the directory to check 14 | pushd $d > /dev/null 15 | # create the coverage profile 16 | coverageresult=`go test -v -coverprofile=$PROFILE_OUT` 17 | # output the result so we can check the shell output 18 | echo ${coverageresult} 19 | # append the results to acc.out if coverage didn't fail, else set the retval to 1 (failed) 20 | ( [[ ${coverageresult} == *FAIL* ]] && retval=1 ) || ( [ -f $PROFILE_OUT ] && grep -v "mode: set" $PROFILE_OUT >> $ACC_OUT ) 21 | # return to our working dir 22 | popd > /dev/null 23 | # return our return value 24 | return $retval 25 | } 26 | 27 | # Init acc.out 28 | echo "mode: set" > $ACC_OUT 29 | 30 | # Run test coverage on all directories containing go files except testlapack. 31 | find . -maxdepth 10 -type d -not -path './testlapack*' | while read d; do testCover $d || exit; done 32 | 33 | # Upload the coverage profile to coveralls.io 34 | [ -n "$COVERALLS_TOKEN" ] && goveralls -coverprofile=$ACC_OUT -service=travis-ci -repotoken $COVERALLS_TOKEN 35 | 36 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 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) [![GoDoc](https://godoc.org/github.com/gonum/lapack?status.svg)](https://godoc.org/github.com/gonum/lapack) 2 | ====== 3 | 4 | # This repository is no longer maintained. Development has moved to https://github.com/gonum/gonum. 5 | 6 | A collection of packages to provide LAPACK functionality for the Go programming 7 | language (http://golang.org). This provides a partial implementation in native go 8 | and a wrapper using cgo to a c-based implementation. 9 | 10 | ## Installation 11 | 12 | ``` 13 | go get github.com/gonum/lapack 14 | ``` 15 | 16 | 17 | Install OpenBLAS: 18 | ``` 19 | git clone https://github.com/xianyi/OpenBLAS 20 | cd OpenBLAS 21 | make 22 | ``` 23 | 24 | Then install the lapack/cgo package: 25 | ```sh 26 | CGO_LDFLAGS="-L/path/to/OpenBLAS -lopenblas" go install github.com/gonum/lapack/cgo 27 | ``` 28 | 29 | For Windows you can download binary packages for OpenBLAS at 30 | http://sourceforge.net/projects/openblas/files/ 31 | 32 | If you want to use a different BLAS package such as the Intel MKL you can 33 | adjust the `CGO_LDFLAGS` variable: 34 | ```sh 35 | CGO_LDFLAGS="-lmkl_rt" go install github.com/gonum/lapack/cgo 36 | ``` 37 | 38 | ## Packages 39 | 40 | ### lapack 41 | 42 | Defines the LAPACK API based on http://www.netlib.org/lapack/lapacke.html 43 | 44 | ### lapack/lapacke 45 | 46 | Binding to a C implementation of the lapacke interface (e.g. OpenBLAS or intel MKL) 47 | 48 | The linker flags (i.e. path to the BLAS library and library name) might have to be adapted. 49 | 50 | The recommended (free) option for good performance on both linux and darwin is OpenBLAS. 51 | 52 | ## Issues 53 | 54 | If you find any bugs, feel free to file an issue on the github [issue tracker for gonum/gonum](https://github.com/gonum/gonum/issues) or [gonum/netlib for the CGO implementation](https://github.com/gonum/netlib/issues) if the bug exists in that reposity; no code changes will be made to this repository. Other discussions should be taken to the gonum-dev Google Group. 55 | 56 | https://groups.google.com/forum/#!forum/gonum-dev 57 | 58 | ## License 59 | 60 | Please see github.com/gonum/license for general license information, contributors, authors, etc on the Gonum suite of packages. 61 | -------------------------------------------------------------------------------- /cgo/bench_test.go: -------------------------------------------------------------------------------- 1 | // Copyright ©2016 The gonum Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // +build go1.7 6 | 7 | package cgo 8 | 9 | import ( 10 | "testing" 11 | 12 | "github.com/gonum/lapack/testlapack" 13 | ) 14 | 15 | func BenchmarkDgeev(b *testing.B) { testlapack.DgeevBenchmark(b, impl) } 16 | -------------------------------------------------------------------------------- /cgo/lapacke/generate.go: -------------------------------------------------------------------------------- 1 | // Copyright ©2016 The gonum Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | //go:generate go run generate_lapacke.go 6 | 7 | package lapacke 8 | -------------------------------------------------------------------------------- /cgo/lapacke/lapacke_mangling.h: -------------------------------------------------------------------------------- 1 | #ifndef LAPACK_HEADER_INCLUDED 2 | #define LAPACK_HEADER_INCLUDED 3 | 4 | #ifndef LAPACK_GLOBAL 5 | #if defined(LAPACK_GLOBAL_PATTERN_LC) || defined(ADD_) 6 | #define LAPACK_GLOBAL(lcname,UCNAME) lcname##_ 7 | #elif defined(LAPACK_GLOBAL_PATTERN_UC) || defined(UPPER) 8 | #define LAPACK_GLOBAL(lcname,UCNAME) UCNAME 9 | #elif defined(LAPACK_GLOBAL_PATTERN_MC) || defined(NOCHANGE) 10 | #define LAPACK_GLOBAL(lcname,UCNAME) lcname 11 | #else 12 | #define LAPACK_GLOBAL(lcname,UCNAME) lcname##_ 13 | #endif 14 | #endif 15 | 16 | #endif 17 | 18 | -------------------------------------------------------------------------------- /internal/testdata/dlahr2test/main.go: -------------------------------------------------------------------------------- 1 | // Copyright ©2016 The gonum Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // dlahr2test generates test data for Dlahr2. Test cases are stored in 6 | // gzip-compressed JSON file testlapack/testdata/dlahr2data.json.gz which is 7 | // read during testing by testlapack/dlahr2.go. 8 | // 9 | // This program uses cgo to call Fortran version of DLAHR2. Therefore, matrices 10 | // passed to the Fortran routine are in column-major format but are written into 11 | // the output file in row-major format. 12 | package main 13 | 14 | import ( 15 | "compress/gzip" 16 | "encoding/json" 17 | "log" 18 | "math/rand" 19 | "os" 20 | "path/filepath" 21 | 22 | "github.com/gonum/lapack/internal/testdata/netlib" 23 | ) 24 | 25 | type Dlahr2Test struct { 26 | N, K, NB int 27 | A []float64 28 | 29 | AWant []float64 30 | TWant []float64 31 | YWant []float64 32 | TauWant []float64 33 | } 34 | 35 | func main() { 36 | file, err := os.Create(filepath.FromSlash("../../../testlapack/testdata/dlahr2data.json.gz")) 37 | if err != nil { 38 | log.Fatal(err) 39 | } 40 | defer file.Close() 41 | w := gzip.NewWriter(file) 42 | 43 | rnd := rand.New(rand.NewSource(1)) 44 | 45 | var tests []Dlahr2Test 46 | for _, n := range []int{4, 5, 6, 7, 11} { 47 | for k := 0; k <= n/2; k++ { 48 | for nb := 1; nb <= k; nb++ { 49 | ain := genrand(n, n-k+1, rnd) 50 | a := make([]float64, len(ain)) 51 | copy(a, ain) 52 | 53 | t := genrand(nb, nb, rnd) 54 | y := genrand(n, nb, rnd) 55 | tau := genrand(nb, 1, rnd) 56 | 57 | netlib.Dlahr2(n, k, nb, a, n, tau, t, nb, y, n) 58 | 59 | tests = append(tests, Dlahr2Test{ 60 | N: n, 61 | K: k, 62 | NB: nb, 63 | A: rowMajor(n, n-k+1, ain), 64 | AWant: rowMajor(n, n-k+1, a), 65 | TWant: rowMajor(nb, nb, t), 66 | YWant: rowMajor(n, nb, y), 67 | TauWant: tau, 68 | }) 69 | } 70 | } 71 | } 72 | json.NewEncoder(w).Encode(tests) 73 | 74 | err = w.Close() 75 | if err != nil { 76 | log.Fatal(err) 77 | } 78 | } 79 | 80 | // genrand returns a general r×c matrix with random entries. 81 | func genrand(r, c int, rnd *rand.Rand) []float64 { 82 | m := make([]float64, r*c) 83 | for i := range m { 84 | m[i] = rnd.NormFloat64() 85 | } 86 | return m 87 | } 88 | 89 | // rowMajor returns the given r×c column-major matrix a in row-major format. 90 | func rowMajor(r, c int, a []float64) []float64 { 91 | if len(a) != r*c { 92 | panic("testdata: slice length mismatch") 93 | } 94 | m := make([]float64, len(a)) 95 | for i := 0; i < r; i++ { 96 | for j := 0; j < c; j++ { 97 | m[i*c+j] = a[i+j*r] 98 | } 99 | } 100 | return m 101 | } 102 | -------------------------------------------------------------------------------- /internal/testdata/dlasqtest/Makefile: -------------------------------------------------------------------------------- 1 | FC = gfortran 2 | FFLAGS = -O2 3 | 4 | targets = testdlasq1 testdlasq2 testdlasq3 testdlasq4 5 | objects = dlamch.o lsame.o xerbla.o ieeeck.o iparmq.o ilaenv.o dlasrt.o \ 6 | dlaisnan.o disnan.o dlasq6.o dlasq5.o dlasq4.o dlasq3.o dlasq2.o 7 | 8 | default : $(targets) 9 | .PHONY : default 10 | 11 | testdlasq1 : testdlasq1.o $(objects) dcopy.o dlas2.o dlascl.o dlasq1.o 12 | 13 | testdlasq2 : testdlasq2.o $(objects) 14 | 15 | testdlasq3 : testdlasq3.o $(objects) 16 | 17 | testdlasq4 : testdlasq4.o $(objects) 18 | 19 | % : %.o 20 | $(FC) $(FFLAGS) $^ -o $@ 21 | 22 | %.o : %.f90 23 | $(FC) $(FFLAGS) -c -o $@ $< 24 | 25 | clean : 26 | rm -f *.o $(targets) *.txt 27 | .PHONY : clean -------------------------------------------------------------------------------- /internal/testdata/dlasqtest/Readme.md: -------------------------------------------------------------------------------- 1 | This set of codes generates tests for the dlasq* routines. 2 | 3 | The high level routines are testdlasq*.f90. The testdlasq*.f90 routines are intended in combination with the routines in gonum/lapack/testlapack. 4 | During execution, these high-level routines record the inputs and outputs 5 | to the executed subroutines. For example, testdlasq3, when executed, 6 | generates files gen4tests.txt and gen5tests.txt that record the inputs 7 | and outputs to the evaluation of dlasq4 and dlasq5 respectively. The output 8 | format in gen*tests.txt is the struct literal that matches the respective test 9 | in gonum/lapack/testlapack/dlasq*.go. Thus, these generated tests can be copied 10 | into the testing routine to test the native implementation. 11 | 12 | The testing routines in testlapack have code for generating inputs for these 13 | fortran routines. Typically, one would isolate the particular failing test, 14 | and modify the testlapack routine to print it to the terminal, for example 15 | in testlapack/dlasq3.go one might add 16 | 17 | printDlasq3FortranInput(test) 18 | os.Exit(1) 19 | 20 | This prints variable initialization for dlasq3 routine to the terminal, which 21 | can be copied and pasted into testdlasq3.f90. Please note that this process 22 | is not completely automated. Some of the other initialization may need to 23 | change, particularly the size allocation of the data array(s). -------------------------------------------------------------------------------- /internal/testdata/dlasqtest/disnan.f: -------------------------------------------------------------------------------- 1 | *> \brief \b DISNAN tests input for NaN. 2 | * 3 | * =========== DOCUMENTATION =========== 4 | * 5 | * Online html documentation available at 6 | * http://www.netlib.org/lapack/explore-html/ 7 | * 8 | *> \htmlonly 9 | *> Download DISNAN + dependencies 10 | *> 11 | *> [TGZ] 12 | *> 13 | *> [ZIP] 14 | *> 15 | *> [TXT] 16 | *> \endhtmlonly 17 | * 18 | * Definition: 19 | * =========== 20 | * 21 | * LOGICAL FUNCTION DISNAN( DIN ) 22 | * 23 | * .. Scalar Arguments .. 24 | * DOUBLE PRECISION DIN 25 | * .. 26 | * 27 | * 28 | *> \par Purpose: 29 | * ============= 30 | *> 31 | *> \verbatim 32 | *> 33 | *> DISNAN returns .TRUE. if its argument is NaN, and .FALSE. 34 | *> otherwise. To be replaced by the Fortran 2003 intrinsic in the 35 | *> future. 36 | *> \endverbatim 37 | * 38 | * Arguments: 39 | * ========== 40 | * 41 | *> \param[in] DIN 42 | *> \verbatim 43 | *> DIN is DOUBLE PRECISION 44 | *> Input to test for NaN. 45 | *> \endverbatim 46 | * 47 | * Authors: 48 | * ======== 49 | * 50 | *> \author Univ. of Tennessee 51 | *> \author Univ. of California Berkeley 52 | *> \author Univ. of Colorado Denver 53 | *> \author NAG Ltd. 54 | * 55 | *> \date September 2012 56 | * 57 | *> \ingroup auxOTHERauxiliary 58 | * 59 | * ===================================================================== 60 | LOGICAL FUNCTION DISNAN( DIN ) 61 | * 62 | * -- LAPACK auxiliary routine (version 3.4.2) -- 63 | * -- LAPACK is a software package provided by Univ. of Tennessee, -- 64 | * -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- 65 | * September 2012 66 | * 67 | * .. Scalar Arguments .. 68 | DOUBLE PRECISION DIN 69 | * .. 70 | * 71 | * ===================================================================== 72 | * 73 | * .. External Functions .. 74 | LOGICAL DLAISNAN 75 | EXTERNAL DLAISNAN 76 | * .. 77 | * .. Executable Statements .. 78 | DISNAN = DLAISNAN(DIN,DIN) 79 | RETURN 80 | END 81 | -------------------------------------------------------------------------------- /internal/testdata/dlasqtest/dlaisnan.f: -------------------------------------------------------------------------------- 1 | *> \brief \b DLAISNAN tests input for NaN by comparing two arguments for inequality. 2 | * 3 | * =========== DOCUMENTATION =========== 4 | * 5 | * Online html documentation available at 6 | * http://www.netlib.org/lapack/explore-html/ 7 | * 8 | *> \htmlonly 9 | *> Download DLAISNAN + dependencies 10 | *> 11 | *> [TGZ] 12 | *> 13 | *> [ZIP] 14 | *> 15 | *> [TXT] 16 | *> \endhtmlonly 17 | * 18 | * Definition: 19 | * =========== 20 | * 21 | * LOGICAL FUNCTION DLAISNAN( DIN1, DIN2 ) 22 | * 23 | * .. Scalar Arguments .. 24 | * DOUBLE PRECISION DIN1, DIN2 25 | * .. 26 | * 27 | * 28 | *> \par Purpose: 29 | * ============= 30 | *> 31 | *> \verbatim 32 | *> 33 | *> This routine is not for general use. It exists solely to avoid 34 | *> over-optimization in DISNAN. 35 | *> 36 | *> DLAISNAN checks for NaNs by comparing its two arguments for 37 | *> inequality. NaN is the only floating-point value where NaN != NaN 38 | *> returns .TRUE. To check for NaNs, pass the same variable as both 39 | *> arguments. 40 | *> 41 | *> A compiler must assume that the two arguments are 42 | *> not the same variable, and the test will not be optimized away. 43 | *> Interprocedural or whole-program optimization may delete this 44 | *> test. The ISNAN functions will be replaced by the correct 45 | *> Fortran 03 intrinsic once the intrinsic is widely available. 46 | *> \endverbatim 47 | * 48 | * Arguments: 49 | * ========== 50 | * 51 | *> \param[in] DIN1 52 | *> \verbatim 53 | *> DIN1 is DOUBLE PRECISION 54 | *> \endverbatim 55 | *> 56 | *> \param[in] DIN2 57 | *> \verbatim 58 | *> DIN2 is DOUBLE PRECISION 59 | *> Two numbers to compare for inequality. 60 | *> \endverbatim 61 | * 62 | * Authors: 63 | * ======== 64 | * 65 | *> \author Univ. of Tennessee 66 | *> \author Univ. of California Berkeley 67 | *> \author Univ. of Colorado Denver 68 | *> \author NAG Ltd. 69 | * 70 | *> \date September 2012 71 | * 72 | *> \ingroup auxOTHERauxiliary 73 | * 74 | * ===================================================================== 75 | LOGICAL FUNCTION DLAISNAN( DIN1, DIN2 ) 76 | * 77 | * -- LAPACK auxiliary routine (version 3.4.2) -- 78 | * -- LAPACK is a software package provided by Univ. of Tennessee, -- 79 | * -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- 80 | * September 2012 81 | * 82 | * .. Scalar Arguments .. 83 | DOUBLE PRECISION DIN1, DIN2 84 | * .. 85 | * 86 | * ===================================================================== 87 | * 88 | * .. Executable Statements .. 89 | DLAISNAN = (DIN1.NE.DIN2) 90 | RETURN 91 | END 92 | -------------------------------------------------------------------------------- /internal/testdata/dsterftest/Makefile: -------------------------------------------------------------------------------- 1 | FC = gfortran 2 | FFLAGS = -O2 3 | 4 | targets = testdsterf 5 | objects = disnan.o dlamch.o dlanst.o dlaisnan.o dlassq.o dlapy2.o lsame.o dlae2.o dlascl.o dlasrt.o dsterf.o xerbla.o 6 | 7 | default : $(targets) 8 | .PHONY : default 9 | 10 | testdsterf : testdsterf.o $(objects) 11 | 12 | % : %.o 13 | $(FC) $(FFLAGS) $^ -o $@ 14 | 15 | %.o : %.f90 16 | $(FC) $(FFLAGS) -c -o $@ $< 17 | 18 | clean : 19 | rm -f *.o $(targets) *.txt 20 | .PHONY : clean -------------------------------------------------------------------------------- /internal/testdata/dsterftest/disnan.f: -------------------------------------------------------------------------------- 1 | *> \brief \b DISNAN tests input for NaN. 2 | * 3 | * =========== DOCUMENTATION =========== 4 | * 5 | * Online html documentation available at 6 | * http://www.netlib.org/lapack/explore-html/ 7 | * 8 | *> \htmlonly 9 | *> Download DISNAN + dependencies 10 | *> 11 | *> [TGZ] 12 | *> 13 | *> [ZIP] 14 | *> 15 | *> [TXT] 16 | *> \endhtmlonly 17 | * 18 | * Definition: 19 | * =========== 20 | * 21 | * LOGICAL FUNCTION DISNAN( DIN ) 22 | * 23 | * .. Scalar Arguments .. 24 | * DOUBLE PRECISION DIN 25 | * .. 26 | * 27 | * 28 | *> \par Purpose: 29 | * ============= 30 | *> 31 | *> \verbatim 32 | *> 33 | *> DISNAN returns .TRUE. if its argument is NaN, and .FALSE. 34 | *> otherwise. To be replaced by the Fortran 2003 intrinsic in the 35 | *> future. 36 | *> \endverbatim 37 | * 38 | * Arguments: 39 | * ========== 40 | * 41 | *> \param[in] DIN 42 | *> \verbatim 43 | *> DIN is DOUBLE PRECISION 44 | *> Input to test for NaN. 45 | *> \endverbatim 46 | * 47 | * Authors: 48 | * ======== 49 | * 50 | *> \author Univ. of Tennessee 51 | *> \author Univ. of California Berkeley 52 | *> \author Univ. of Colorado Denver 53 | *> \author NAG Ltd. 54 | * 55 | *> \date September 2012 56 | * 57 | *> \ingroup auxOTHERauxiliary 58 | * 59 | * ===================================================================== 60 | LOGICAL FUNCTION DISNAN( DIN ) 61 | * 62 | * -- LAPACK auxiliary routine (version 3.4.2) -- 63 | * -- LAPACK is a software package provided by Univ. of Tennessee, -- 64 | * -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- 65 | * September 2012 66 | * 67 | * .. Scalar Arguments .. 68 | DOUBLE PRECISION DIN 69 | * .. 70 | * 71 | * ===================================================================== 72 | * 73 | * .. External Functions .. 74 | LOGICAL DLAISNAN 75 | EXTERNAL DLAISNAN 76 | * .. 77 | * .. Executable Statements .. 78 | DISNAN = DLAISNAN(DIN,DIN) 79 | RETURN 80 | END 81 | -------------------------------------------------------------------------------- /internal/testdata/dsterftest/dlaisnan.f: -------------------------------------------------------------------------------- 1 | *> \brief \b DLAISNAN tests input for NaN by comparing two arguments for inequality. 2 | * 3 | * =========== DOCUMENTATION =========== 4 | * 5 | * Online html documentation available at 6 | * http://www.netlib.org/lapack/explore-html/ 7 | * 8 | *> \htmlonly 9 | *> Download DLAISNAN + dependencies 10 | *> 11 | *> [TGZ] 12 | *> 13 | *> [ZIP] 14 | *> 15 | *> [TXT] 16 | *> \endhtmlonly 17 | * 18 | * Definition: 19 | * =========== 20 | * 21 | * LOGICAL FUNCTION DLAISNAN( DIN1, DIN2 ) 22 | * 23 | * .. Scalar Arguments .. 24 | * DOUBLE PRECISION DIN1, DIN2 25 | * .. 26 | * 27 | * 28 | *> \par Purpose: 29 | * ============= 30 | *> 31 | *> \verbatim 32 | *> 33 | *> This routine is not for general use. It exists solely to avoid 34 | *> over-optimization in DISNAN. 35 | *> 36 | *> DLAISNAN checks for NaNs by comparing its two arguments for 37 | *> inequality. NaN is the only floating-point value where NaN != NaN 38 | *> returns .TRUE. To check for NaNs, pass the same variable as both 39 | *> arguments. 40 | *> 41 | *> A compiler must assume that the two arguments are 42 | *> not the same variable, and the test will not be optimized away. 43 | *> Interprocedural or whole-program optimization may delete this 44 | *> test. The ISNAN functions will be replaced by the correct 45 | *> Fortran 03 intrinsic once the intrinsic is widely available. 46 | *> \endverbatim 47 | * 48 | * Arguments: 49 | * ========== 50 | * 51 | *> \param[in] DIN1 52 | *> \verbatim 53 | *> DIN1 is DOUBLE PRECISION 54 | *> \endverbatim 55 | *> 56 | *> \param[in] DIN2 57 | *> \verbatim 58 | *> DIN2 is DOUBLE PRECISION 59 | *> Two numbers to compare for inequality. 60 | *> \endverbatim 61 | * 62 | * Authors: 63 | * ======== 64 | * 65 | *> \author Univ. of Tennessee 66 | *> \author Univ. of California Berkeley 67 | *> \author Univ. of Colorado Denver 68 | *> \author NAG Ltd. 69 | * 70 | *> \date September 2012 71 | * 72 | *> \ingroup auxOTHERauxiliary 73 | * 74 | * ===================================================================== 75 | LOGICAL FUNCTION DLAISNAN( DIN1, DIN2 ) 76 | * 77 | * -- LAPACK auxiliary routine (version 3.4.2) -- 78 | * -- LAPACK is a software package provided by Univ. of Tennessee, -- 79 | * -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- 80 | * September 2012 81 | * 82 | * .. Scalar Arguments .. 83 | DOUBLE PRECISION DIN1, DIN2 84 | * .. 85 | * 86 | * ===================================================================== 87 | * 88 | * .. Executable Statements .. 89 | DLAISNAN = (DIN1.NE.DIN2) 90 | RETURN 91 | END 92 | -------------------------------------------------------------------------------- /internal/testdata/dsterftest/testdsterf.f90: -------------------------------------------------------------------------------- 1 | program testdsterf 2 | implicit none 3 | integer, parameter :: n = 4 4 | real(kind=8), dimension(n) :: d 5 | real(kind=8), dimension(n-1) :: e 6 | integer :: info,i 7 | 8 | d(1:4) = (/1D+00, 3D+00, 4D+00, 6D+00/) 9 | e(1:3) = (/2D+00, 4D+00, 5D+00/) 10 | 11 | call dsterf(n,d,e,info) 12 | DO i = 1, n 13 | print *, d(i) 14 | end do 15 | end -------------------------------------------------------------------------------- /internal/testdata/netlib/dscal.f: -------------------------------------------------------------------------------- 1 | *> \brief \b DSCAL 2 | * 3 | * =========== DOCUMENTATION =========== 4 | * 5 | * Online html documentation available at 6 | * http://www.netlib.org/lapack/explore-html/ 7 | * 8 | * Definition: 9 | * =========== 10 | * 11 | * SUBROUTINE DSCAL(N,DA,DX,INCX) 12 | * 13 | * .. Scalar Arguments .. 14 | * DOUBLE PRECISION DA 15 | * INTEGER INCX,N 16 | * .. 17 | * .. Array Arguments .. 18 | * DOUBLE PRECISION DX(*) 19 | * .. 20 | * 21 | * 22 | *> \par Purpose: 23 | * ============= 24 | *> 25 | *> \verbatim 26 | *> 27 | *> DSCAL scales a vector by a constant. 28 | *> uses unrolled loops for increment equal to one. 29 | *> \endverbatim 30 | * 31 | * Authors: 32 | * ======== 33 | * 34 | *> \author Univ. of Tennessee 35 | *> \author Univ. of California Berkeley 36 | *> \author Univ. of Colorado Denver 37 | *> \author NAG Ltd. 38 | * 39 | *> \date November 2011 40 | * 41 | *> \ingroup double_blas_level1 42 | * 43 | *> \par Further Details: 44 | * ===================== 45 | *> 46 | *> \verbatim 47 | *> 48 | *> jack dongarra, linpack, 3/11/78. 49 | *> modified 3/93 to return if incx .le. 0. 50 | *> modified 12/3/93, array(1) declarations changed to array(*) 51 | *> \endverbatim 52 | *> 53 | * ===================================================================== 54 | SUBROUTINE DSCAL(N,DA,DX,INCX) 55 | * 56 | * -- Reference BLAS level1 routine (version 3.4.0) -- 57 | * -- Reference BLAS is a software package provided by Univ. of Tennessee, -- 58 | * -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- 59 | * November 2011 60 | * 61 | * .. Scalar Arguments .. 62 | DOUBLE PRECISION DA 63 | INTEGER INCX,N 64 | * .. 65 | * .. Array Arguments .. 66 | DOUBLE PRECISION DX(*) 67 | * .. 68 | * 69 | * ===================================================================== 70 | * 71 | * .. Local Scalars .. 72 | INTEGER I,M,MP1,NINCX 73 | * .. 74 | * .. Intrinsic Functions .. 75 | INTRINSIC MOD 76 | * .. 77 | IF (N.LE.0 .OR. INCX.LE.0) RETURN 78 | IF (INCX.EQ.1) THEN 79 | * 80 | * code for increment equal to 1 81 | * 82 | * 83 | * clean-up loop 84 | * 85 | M = MOD(N,5) 86 | IF (M.NE.0) THEN 87 | DO I = 1,M 88 | DX(I) = DA*DX(I) 89 | END DO 90 | IF (N.LT.5) RETURN 91 | END IF 92 | MP1 = M + 1 93 | DO I = MP1,N,5 94 | DX(I) = DA*DX(I) 95 | DX(I+1) = DA*DX(I+1) 96 | DX(I+2) = DA*DX(I+2) 97 | DX(I+3) = DA*DX(I+3) 98 | DX(I+4) = DA*DX(I+4) 99 | END DO 100 | ELSE 101 | * 102 | * code for increment not equal to 1 103 | * 104 | NINCX = N*INCX 105 | DO I = 1,NINCX,INCX 106 | DX(I) = DA*DX(I) 107 | END DO 108 | END IF 109 | RETURN 110 | END 111 | -------------------------------------------------------------------------------- /internal/testdata/netlib/netlib.go: -------------------------------------------------------------------------------- 1 | // Copyright ©2016 The gonum Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package netlib 6 | 7 | // void dlahr2_(int* n, int* k, int* nb, double* a, int* lda, double* tau, double* t, int* ldt, double* y, int* ldy); 8 | // 9 | // void dlaqr5_(int* wantt, int* wantz, int* kacc22, int* n, int* ktop, int* kbot, int* nshfts, 10 | // double* sr, double* si, double* h, int* ldh, int* iloz, int* ihiz, 11 | // double* z, int* ldz, double* v, int* ldv, double* u, int* ldu, 12 | // int* nv, double* wv, int* ldwv, int* nh, double* wh, int* ldwh); 13 | import "C" 14 | 15 | func Dlahr2(n, k, nb int, a []float64, lda int, tau, t []float64, ldt int, y []float64, ldy int) { 16 | func() { 17 | n := C.int(n) 18 | k := C.int(k) 19 | nb := C.int(nb) 20 | lda := C.int(lda) 21 | ldt := C.int(ldt) 22 | ldy := C.int(ldy) 23 | C.dlahr2_((*C.int)(&n), (*C.int)(&k), (*C.int)(&nb), 24 | (*C.double)(&a[0]), (*C.int)(&lda), 25 | (*C.double)(&tau[0]), 26 | (*C.double)(&t[0]), (*C.int)(&ldt), 27 | (*C.double)(&y[0]), (*C.int)(&ldy)) 28 | }() 29 | } 30 | 31 | func Dlaqr5(wantt, wantz bool, kacc22 int, n, ktop, kbot int, nshfts int, sr, si []float64, h []float64, 32 | ldh int, iloz, ihiz int, z []float64, ldz int, v []float64, ldv int, 33 | u []float64, ldu int, nh int, wh []float64, ldwh int, nv int, wv []float64, ldwv int) { 34 | func() { 35 | wt := C.int(0) 36 | if wantt { 37 | wt = 1 38 | } 39 | wz := C.int(0) 40 | if wantz { 41 | wz = 1 42 | } 43 | kacc22 := C.int(kacc22) 44 | n := C.int(n) 45 | ktop := C.int(ktop) 46 | kbot := C.int(kbot) 47 | nshfts := C.int(nshfts) 48 | ldh := C.int(ldh) 49 | iloz := C.int(iloz) 50 | ihiz := C.int(ihiz) 51 | ldz := C.int(ldz) 52 | ldv := C.int(ldv) 53 | ldu := C.int(ldu) 54 | nh := C.int(nh) 55 | ldwh := C.int(ldwh) 56 | nv := C.int(nv) 57 | ldwv := C.int(ldwv) 58 | C.dlaqr5_((*C.int)(&wt), (*C.int)(&wz), (*C.int)(&kacc22), 59 | (*C.int)(&n), (*C.int)(&ktop), (*C.int)(&kbot), 60 | (*C.int)(&nshfts), (*C.double)(&sr[0]), (*C.double)(&si[0]), 61 | (*C.double)(&h[0]), (*C.int)(&ldh), 62 | (*C.int)(&iloz), (*C.int)(&ihiz), (*C.double)(&z[0]), (*C.int)(&ldz), 63 | (*C.double)(&v[0]), (*C.int)(&ldv), 64 | (*C.double)(&u[0]), (*C.int)(&ldu), 65 | (*C.int)(&nh), (*C.double)(&wh[0]), (*C.int)(&ldwh), 66 | (*C.int)(&nv), (*C.double)(&wv[0]), (*C.int)(&ldwv)) 67 | }() 68 | } 69 | -------------------------------------------------------------------------------- /internal/testdata/netlib/xerbla.f: -------------------------------------------------------------------------------- 1 | *> \brief \b XERBLA 2 | * 3 | * =========== DOCUMENTATION =========== 4 | * 5 | * Online html documentation available at 6 | * http://www.netlib.org/lapack/explore-html/ 7 | * 8 | * Definition: 9 | * =========== 10 | * 11 | * SUBROUTINE XERBLA( SRNAME, INFO ) 12 | * 13 | * .. Scalar Arguments .. 14 | * CHARACTER*(*) SRNAME 15 | * INTEGER INFO 16 | * .. 17 | * 18 | * 19 | *> \par Purpose: 20 | * ============= 21 | *> 22 | *> \verbatim 23 | *> 24 | *> XERBLA is an error handler for the LAPACK routines. 25 | *> It is called by an LAPACK routine if an input parameter has an 26 | *> invalid value. A message is printed and execution stops. 27 | *> 28 | *> Installers may consider modifying the STOP statement in order to 29 | *> call system-specific exception-handling facilities. 30 | *> \endverbatim 31 | * 32 | * Arguments: 33 | * ========== 34 | * 35 | *> \param[in] SRNAME 36 | *> \verbatim 37 | *> SRNAME is CHARACTER*(*) 38 | *> The name of the routine which called XERBLA. 39 | *> \endverbatim 40 | *> 41 | *> \param[in] INFO 42 | *> \verbatim 43 | *> INFO is INTEGER 44 | *> The position of the invalid parameter in the parameter list 45 | *> of the calling routine. 46 | *> \endverbatim 47 | * 48 | * Authors: 49 | * ======== 50 | * 51 | *> \author Univ. of Tennessee 52 | *> \author Univ. of California Berkeley 53 | *> \author Univ. of Colorado Denver 54 | *> \author NAG Ltd. 55 | * 56 | *> \date November 2011 57 | * 58 | *> \ingroup aux_blas 59 | * 60 | * ===================================================================== 61 | SUBROUTINE XERBLA( SRNAME, INFO ) 62 | * 63 | * -- Reference BLAS level1 routine (version 3.4.0) -- 64 | * -- Reference BLAS is a software package provided by Univ. of Tennessee, -- 65 | * -- Univ. of California Berkeley, Univ. of Colorado Denver and NAG Ltd..-- 66 | * November 2011 67 | * 68 | * .. Scalar Arguments .. 69 | CHARACTER*(*) SRNAME 70 | INTEGER INFO 71 | * .. 72 | * 73 | * ===================================================================== 74 | * 75 | * .. Intrinsic Functions .. 76 | INTRINSIC LEN_TRIM 77 | * .. 78 | * .. Executable Statements .. 79 | * 80 | WRITE( *, FMT = 9999 )SRNAME( 1:LEN_TRIM( SRNAME ) ), INFO 81 | * 82 | STOP 83 | * 84 | 9999 FORMAT( ' ** On entry to ', A, ' parameter number ', I2, ' had ', 85 | $ 'an illegal value' ) 86 | * 87 | * End of XERBLA 88 | * 89 | END 90 | -------------------------------------------------------------------------------- /native/bench_test.go: -------------------------------------------------------------------------------- 1 | // Copyright ©2016 The gonum Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // +build go1.7 6 | 7 | package native 8 | 9 | import ( 10 | "testing" 11 | 12 | "github.com/gonum/lapack/testlapack" 13 | ) 14 | 15 | func BenchmarkDgeev(b *testing.B) { testlapack.DgeevBenchmark(b, impl) } 16 | -------------------------------------------------------------------------------- /native/dgebak.go: -------------------------------------------------------------------------------- 1 | // Copyright ©2016 The gonum Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package native 6 | 7 | import ( 8 | "github.com/gonum/blas/blas64" 9 | "github.com/gonum/lapack" 10 | ) 11 | 12 | // Dgebak updates an n×m matrix V as 13 | // V = P D V, if side == lapack.RightEV, 14 | // V = P D^{-1} V, if side == lapack.LeftEV, 15 | // where P and D are n×n permutation and scaling matrices, respectively, 16 | // implicitly represented by job, scale, ilo and ihi as returned by Dgebal. 17 | // 18 | // Typically, columns of the matrix V contain the right or left (determined by 19 | // side) eigenvectors of the balanced matrix output by Dgebal, and Dgebak forms 20 | // the eigenvectors of the original matrix. 21 | // 22 | // Dgebak is an internal routine. It is exported for testing purposes. 23 | func (impl Implementation) Dgebak(job lapack.Job, side lapack.EVSide, n, ilo, ihi int, scale []float64, m int, v []float64, ldv int) { 24 | switch job { 25 | default: 26 | panic(badJob) 27 | case lapack.None, lapack.Permute, lapack.Scale, lapack.PermuteScale: 28 | } 29 | switch side { 30 | default: 31 | panic(badSide) 32 | case lapack.LeftEV, lapack.RightEV: 33 | } 34 | checkMatrix(n, m, v, ldv) 35 | switch { 36 | case ilo < 0 || max(0, n-1) < ilo: 37 | panic(badIlo) 38 | case ihi < min(ilo, n-1) || n <= ihi: 39 | panic(badIhi) 40 | } 41 | 42 | // Quick return if possible. 43 | if n == 0 || m == 0 || job == lapack.None { 44 | return 45 | } 46 | 47 | bi := blas64.Implementation() 48 | if ilo != ihi && job != lapack.Permute { 49 | // Backward balance. 50 | if side == lapack.RightEV { 51 | for i := ilo; i <= ihi; i++ { 52 | bi.Dscal(m, scale[i], v[i*ldv:], 1) 53 | } 54 | } else { 55 | for i := ilo; i <= ihi; i++ { 56 | bi.Dscal(m, 1/scale[i], v[i*ldv:], 1) 57 | } 58 | } 59 | } 60 | if job == lapack.Scale { 61 | return 62 | } 63 | // Backward permutation. 64 | for i := ilo - 1; i >= 0; i-- { 65 | k := int(scale[i]) 66 | if k == i { 67 | continue 68 | } 69 | bi.Dswap(m, v[i*ldv:], 1, v[k*ldv:], 1) 70 | } 71 | for i := ihi + 1; i < n; i++ { 72 | k := int(scale[i]) 73 | if k == i { 74 | continue 75 | } 76 | bi.Dswap(m, v[i*ldv:], 1, v[k*ldv:], 1) 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /native/dgebd2.go: -------------------------------------------------------------------------------- 1 | // Copyright ©2015 The gonum Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package native 6 | 7 | import "github.com/gonum/blas" 8 | 9 | // Dgebd2 reduces an m×n matrix A to upper or lower bidiagonal form by an orthogonal 10 | // transformation. 11 | // Q^T * A * P = B 12 | // if m >= n, B is upper diagonal, otherwise B is lower bidiagonal. 13 | // d is the diagonal, len = min(m,n) 14 | // e is the off-diagonal len = min(m,n)-1 15 | // 16 | // Dgebd2 is an internal routine. It is exported for testing purposes. 17 | func (impl Implementation) Dgebd2(m, n int, a []float64, lda int, d, e, tauQ, tauP, work []float64) { 18 | checkMatrix(m, n, a, lda) 19 | if len(d) < min(m, n) { 20 | panic(badD) 21 | } 22 | if len(e) < min(m, n)-1 { 23 | panic(badE) 24 | } 25 | if len(tauQ) < min(m, n) { 26 | panic(badTauQ) 27 | } 28 | if len(tauP) < min(m, n) { 29 | panic(badTauP) 30 | } 31 | if len(work) < max(m, n) { 32 | panic(badWork) 33 | } 34 | if m >= n { 35 | for i := 0; i < n; i++ { 36 | a[i*lda+i], tauQ[i] = impl.Dlarfg(m-i, a[i*lda+i], a[min(i+1, m-1)*lda+i:], lda) 37 | d[i] = a[i*lda+i] 38 | a[i*lda+i] = 1 39 | // Apply H_i to A[i:m, i+1:n] from the left. 40 | if i < n-1 { 41 | impl.Dlarf(blas.Left, m-i, n-i-1, a[i*lda+i:], lda, tauQ[i], a[i*lda+i+1:], lda, work) 42 | } 43 | a[i*lda+i] = d[i] 44 | if i < n-1 { 45 | a[i*lda+i+1], tauP[i] = impl.Dlarfg(n-i-1, a[i*lda+i+1], a[i*lda+min(i+2, n-1):], 1) 46 | e[i] = a[i*lda+i+1] 47 | a[i*lda+i+1] = 1 48 | impl.Dlarf(blas.Right, m-i-1, n-i-1, a[i*lda+i+1:], 1, tauP[i], a[(i+1)*lda+i+1:], lda, work) 49 | a[i*lda+i+1] = e[i] 50 | } else { 51 | tauP[i] = 0 52 | } 53 | } 54 | return 55 | } 56 | for i := 0; i < m; i++ { 57 | a[i*lda+i], tauP[i] = impl.Dlarfg(n-i, a[i*lda+i], a[i*lda+min(i+1, n-1):], 1) 58 | d[i] = a[i*lda+i] 59 | a[i*lda+i] = 1 60 | if i < m-1 { 61 | impl.Dlarf(blas.Right, m-i-1, n-i, a[i*lda+i:], 1, tauP[i], a[(i+1)*lda+i:], lda, work) 62 | } 63 | a[i*lda+i] = d[i] 64 | if i < m-1 { 65 | a[(i+1)*lda+i], tauQ[i] = impl.Dlarfg(m-i-1, a[(i+1)*lda+i], a[min(i+2, m-1)*lda+i:], lda) 66 | e[i] = a[(i+1)*lda+i] 67 | a[(i+1)*lda+i] = 1 68 | impl.Dlarf(blas.Left, m-i-1, n-i-1, a[(i+1)*lda+i:], lda, tauQ[i], a[(i+1)*lda+i+1:], lda, work) 69 | a[(i+1)*lda+i] = e[i] 70 | } else { 71 | tauQ[i] = 0 72 | } 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /native/dgecon.go: -------------------------------------------------------------------------------- 1 | // Copyright ©2015 The gonum Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package native 6 | 7 | import ( 8 | "math" 9 | 10 | "github.com/gonum/blas" 11 | "github.com/gonum/blas/blas64" 12 | "github.com/gonum/lapack" 13 | ) 14 | 15 | // Dgecon estimates the reciprocal of the condition number of the n×n matrix A 16 | // given the LU decomposition of the matrix. The condition number computed may 17 | // be based on the 1-norm or the ∞-norm. 18 | // 19 | // The slice a contains the result of the LU decomposition of A as computed by Dgetrf. 20 | // 21 | // anorm is the corresponding 1-norm or ∞-norm of the original matrix A. 22 | // 23 | // work is a temporary data slice of length at least 4*n and Dgecon will panic otherwise. 24 | // 25 | // iwork is a temporary data slice of length at least n and Dgecon will panic otherwise. 26 | func (impl Implementation) Dgecon(norm lapack.MatrixNorm, n int, a []float64, lda int, anorm float64, work []float64, iwork []int) float64 { 27 | checkMatrix(n, n, a, lda) 28 | if norm != lapack.MaxColumnSum && norm != lapack.MaxRowSum { 29 | panic(badNorm) 30 | } 31 | if len(work) < 4*n { 32 | panic(badWork) 33 | } 34 | if len(iwork) < n { 35 | panic(badWork) 36 | } 37 | 38 | if n == 0 { 39 | return 1 40 | } else if anorm == 0 { 41 | return 0 42 | } 43 | 44 | bi := blas64.Implementation() 45 | var rcond, ainvnm float64 46 | var kase int 47 | var normin bool 48 | isave := new([3]int) 49 | onenrm := norm == lapack.MaxColumnSum 50 | smlnum := dlamchS 51 | kase1 := 2 52 | if onenrm { 53 | kase1 = 1 54 | } 55 | for { 56 | ainvnm, kase = impl.Dlacn2(n, work[n:], work, iwork, ainvnm, kase, isave) 57 | if kase == 0 { 58 | if ainvnm != 0 { 59 | rcond = (1 / ainvnm) / anorm 60 | } 61 | return rcond 62 | } 63 | var sl, su float64 64 | if kase == kase1 { 65 | sl = impl.Dlatrs(blas.Lower, blas.NoTrans, blas.Unit, normin, n, a, lda, work, work[2*n:]) 66 | su = impl.Dlatrs(blas.Upper, blas.NoTrans, blas.NonUnit, normin, n, a, lda, work, work[3*n:]) 67 | } else { 68 | su = impl.Dlatrs(blas.Upper, blas.Trans, blas.NonUnit, normin, n, a, lda, work, work[3*n:]) 69 | sl = impl.Dlatrs(blas.Lower, blas.Trans, blas.Unit, normin, n, a, lda, work, work[2*n:]) 70 | } 71 | scale := sl * su 72 | normin = true 73 | if scale != 1 { 74 | ix := bi.Idamax(n, work, 1) 75 | if scale == 0 || scale < math.Abs(work[ix])*smlnum { 76 | return rcond 77 | } 78 | impl.Drscl(n, scale, work, 1) 79 | } 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /native/dgelq2.go: -------------------------------------------------------------------------------- 1 | // Copyright ©2015 The gonum Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package native 6 | 7 | import "github.com/gonum/blas" 8 | 9 | // Dgelq2 computes the LQ factorization of the m×n matrix A. 10 | // 11 | // In an LQ factorization, L is a lower triangular m×n matrix, and Q is an n×n 12 | // orthonormal matrix. 13 | // 14 | // a is modified to contain the information to construct L and Q. 15 | // The lower triangle of a contains the matrix L. The upper triangular elements 16 | // (not including the diagonal) contain the elementary reflectors. tau is modified 17 | // to contain the reflector scales. tau must have length of at least k = min(m,n) 18 | // and this function will panic otherwise. 19 | // 20 | // See Dgeqr2 for a description of the elementary reflectors and orthonormal 21 | // matrix Q. Q is constructed as a product of these elementary reflectors, 22 | // Q = H_{k-1} * ... * H_1 * H_0. 23 | // 24 | // work is temporary storage of length at least m and this function will panic otherwise. 25 | // 26 | // Dgelq2 is an internal routine. It is exported for testing purposes. 27 | func (impl Implementation) Dgelq2(m, n int, a []float64, lda int, tau, work []float64) { 28 | checkMatrix(m, n, a, lda) 29 | k := min(m, n) 30 | if len(tau) < k { 31 | panic(badTau) 32 | } 33 | if len(work) < m { 34 | panic(badWork) 35 | } 36 | for i := 0; i < k; i++ { 37 | a[i*lda+i], tau[i] = impl.Dlarfg(n-i, a[i*lda+i], a[i*lda+min(i+1, n-1):], 1) 38 | if i < m-1 { 39 | aii := a[i*lda+i] 40 | a[i*lda+i] = 1 41 | impl.Dlarf(blas.Right, m-i-1, n-i, 42 | a[i*lda+i:], 1, 43 | tau[i], 44 | a[(i+1)*lda+i:], lda, 45 | work) 46 | a[i*lda+i] = aii 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /native/dgelqf.go: -------------------------------------------------------------------------------- 1 | // Copyright ©2015 The gonum Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package native 6 | 7 | import ( 8 | "github.com/gonum/blas" 9 | "github.com/gonum/lapack" 10 | ) 11 | 12 | // Dgelqf computes the LQ factorization of the m×n matrix A using a blocked 13 | // algorithm. See the documentation for Dgelq2 for a description of the 14 | // parameters at entry and exit. 15 | // 16 | // work is temporary storage, and lwork specifies the usable memory length. 17 | // At minimum, lwork >= m, and this function will panic otherwise. 18 | // Dgelqf is a blocked LQ factorization, but the block size is limited 19 | // by the temporary space available. If lwork == -1, instead of performing Dgelqf, 20 | // the optimal work length will be stored into work[0]. 21 | // 22 | // tau must have length at least min(m,n), and this function will panic otherwise. 23 | func (impl Implementation) Dgelqf(m, n int, a []float64, lda int, tau, work []float64, lwork int) { 24 | nb := impl.Ilaenv(1, "DGELQF", " ", m, n, -1, -1) 25 | lworkopt := m * max(nb, 1) 26 | if lwork == -1 { 27 | work[0] = float64(lworkopt) 28 | return 29 | } 30 | checkMatrix(m, n, a, lda) 31 | if len(work) < lwork { 32 | panic(shortWork) 33 | } 34 | if lwork < m { 35 | panic(badWork) 36 | } 37 | k := min(m, n) 38 | if len(tau) < k { 39 | panic(badTau) 40 | } 41 | if k == 0 { 42 | return 43 | } 44 | // Find the optimal blocking size based on the size of available memory 45 | // and optimal machine parameters. 46 | nbmin := 2 47 | var nx int 48 | iws := m 49 | ldwork := nb 50 | if nb > 1 && k > nb { 51 | nx = max(0, impl.Ilaenv(3, "DGELQF", " ", m, n, -1, -1)) 52 | if nx < k { 53 | iws = m * nb 54 | if lwork < iws { 55 | nb = lwork / m 56 | nbmin = max(2, impl.Ilaenv(2, "DGELQF", " ", m, n, -1, -1)) 57 | } 58 | } 59 | } 60 | // Computed blocked LQ factorization. 61 | var i int 62 | if nb >= nbmin && nb < k && nx < k { 63 | for i = 0; i < k-nx; i += nb { 64 | ib := min(k-i, nb) 65 | impl.Dgelq2(ib, n-i, a[i*lda+i:], lda, tau[i:], work) 66 | if i+ib < m { 67 | impl.Dlarft(lapack.Forward, lapack.RowWise, n-i, ib, 68 | a[i*lda+i:], lda, 69 | tau[i:], 70 | work, ldwork) 71 | impl.Dlarfb(blas.Right, blas.NoTrans, lapack.Forward, lapack.RowWise, 72 | m-i-ib, n-i, ib, 73 | a[i*lda+i:], lda, 74 | work, ldwork, 75 | a[(i+ib)*lda+i:], lda, 76 | work[ib*ldwork:], ldwork) 77 | } 78 | } 79 | } 80 | // Perform unblocked LQ factorization on the remainder. 81 | if i < k { 82 | impl.Dgelq2(m-i, n-i, a[i*lda+i:], lda, tau[i:], work) 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /native/dgeql2.go: -------------------------------------------------------------------------------- 1 | // Copyright ©2016 The gonum Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package native 6 | 7 | import "github.com/gonum/blas" 8 | 9 | // Dgeql2 computes the QL factorization of the m×n matrix A. That is, Dgeql2 10 | // computes Q and L such that 11 | // A = Q * L 12 | // where Q is an m×m orthonormal matrix and L is a lower trapezoidal matrix. 13 | // 14 | // Q is represented as a product of elementary reflectors, 15 | // Q = H_{k-1} * ... * H_1 * H_0 16 | // where k = min(m,n) and each H_i has the form 17 | // H_i = I - tau[i] * v_i * v_i^T 18 | // Vector v_i has v[m-k+i+1:m] = 0, v[m-k+i] = 1, and v[:m-k+i+1] is stored on 19 | // exit in A[0:m-k+i-1, n-k+i]. 20 | // 21 | // tau must have length at least min(m,n), and Dgeql2 will panic otherwise. 22 | // 23 | // work is temporary memory storage and must have length at least n. 24 | // 25 | // Dgeql2 is an internal routine. It is exported for testing purposes. 26 | func (impl Implementation) Dgeql2(m, n int, a []float64, lda int, tau, work []float64) { 27 | checkMatrix(m, n, a, lda) 28 | if len(tau) < min(m, n) { 29 | panic(badTau) 30 | } 31 | if len(work) < n { 32 | panic(badWork) 33 | } 34 | k := min(m, n) 35 | var aii float64 36 | for i := k - 1; i >= 0; i-- { 37 | // Generate elementary reflector H_i to annihilate A[0:m-k+i-1, n-k+i]. 38 | aii, tau[i] = impl.Dlarfg(m-k+i+1, a[(m-k+i)*lda+n-k+i], a[n-k+i:], lda) 39 | 40 | // Apply H_i to A[0:m-k+i, 0:n-k+i-1] from the left. 41 | a[(m-k+i)*lda+n-k+i] = 1 42 | impl.Dlarf(blas.Left, m-k+i+1, n-k+i, a[n-k+i:], lda, tau[i], a, lda, work) 43 | a[(m-k+i)*lda+n-k+i] = aii 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /native/dgeqr2.go: -------------------------------------------------------------------------------- 1 | // Copyright ©2015 The gonum Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package native 6 | 7 | import "github.com/gonum/blas" 8 | 9 | // Dgeqr2 computes a QR factorization of the m×n matrix A. 10 | // 11 | // In a QR factorization, Q is an m×m orthonormal matrix, and R is an 12 | // upper triangular m×n matrix. 13 | // 14 | // A is modified to contain the information to construct Q and R. 15 | // The upper triangle of a contains the matrix R. The lower triangular elements 16 | // (not including the diagonal) contain the elementary reflectors. tau is modified 17 | // to contain the reflector scales. tau must have length at least min(m,n), and 18 | // this function will panic otherwise. 19 | // 20 | // The ith elementary reflector can be explicitly constructed by first extracting 21 | // the 22 | // v[j] = 0 j < i 23 | // v[j] = 1 j == i 24 | // v[j] = a[j*lda+i] j > i 25 | // and computing H_i = I - tau[i] * v * v^T. 26 | // 27 | // The orthonormal matrix Q can be constructed from a product of these elementary 28 | // reflectors, Q = H_0 * H_1 * ... * H_{k-1}, where k = min(m,n). 29 | // 30 | // work is temporary storage of length at least n and this function will panic otherwise. 31 | // 32 | // Dgeqr2 is an internal routine. It is exported for testing purposes. 33 | func (impl Implementation) Dgeqr2(m, n int, a []float64, lda int, tau, work []float64) { 34 | // TODO(btracey): This is oriented such that columns of a are eliminated. 35 | // This likely could be re-arranged to take better advantage of row-major 36 | // storage. 37 | checkMatrix(m, n, a, lda) 38 | if len(work) < n { 39 | panic(badWork) 40 | } 41 | k := min(m, n) 42 | if len(tau) < k { 43 | panic(badTau) 44 | } 45 | for i := 0; i < k; i++ { 46 | // Generate elementary reflector H_i. 47 | a[i*lda+i], tau[i] = impl.Dlarfg(m-i, a[i*lda+i], a[min((i+1), m-1)*lda+i:], lda) 48 | if i < n-1 { 49 | aii := a[i*lda+i] 50 | a[i*lda+i] = 1 51 | impl.Dlarf(blas.Left, m-i, n-i-1, 52 | a[i*lda+i:], lda, 53 | tau[i], 54 | a[i*lda+i+1:], lda, 55 | work) 56 | a[i*lda+i] = aii 57 | } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /native/dgerq2.go: -------------------------------------------------------------------------------- 1 | // Copyright ©2017 The gonum Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package native 6 | 7 | import "github.com/gonum/blas" 8 | 9 | // Dgerq2 computes an RQ factorization of the m×n matrix A, 10 | // A = R * Q. 11 | // On exit, if m <= n, the upper triangle of the subarray 12 | // A[0:m, n-m:n] contains the m×m upper triangular matrix R. 13 | // If m >= n, the elements on and above the (m-n)-th subdiagonal 14 | // contain the m×n upper trapezoidal matrix R. 15 | // The remaining elements, with tau, represent the 16 | // orthogonal matrix Q as a product of min(m,n) elementary 17 | // reflectors. 18 | // 19 | // The matrix Q is represented as a product of elementary reflectors 20 | // Q = H_0 H_1 . . . H_{min(m,n)-1}. 21 | // Each H(i) has the form 22 | // H_i = I - tau_i * v * v^T 23 | // where v is a vector with v[0:n-k+i-1] stored in A[m-k+i, 0:n-k+i-1], 24 | // v[n-k+i:n] = 0 and v[n-k+i] = 1. 25 | // 26 | // tau must have length min(m,n) and work must have length m, otherwise 27 | // Dgerq2 will panic. 28 | // 29 | // Dgerq2 is an internal routine. It is exported for testing purposes. 30 | func (impl Implementation) Dgerq2(m, n int, a []float64, lda int, tau, work []float64) { 31 | checkMatrix(m, n, a, lda) 32 | k := min(m, n) 33 | if len(tau) < k { 34 | panic(badTau) 35 | } 36 | if len(work) < m { 37 | panic(badWork) 38 | } 39 | 40 | for i := k - 1; i >= 0; i-- { 41 | // Generate elementary reflector H[i] to annihilate 42 | // A[m-k+i, 0:n-k+i-1]. 43 | mki := m - k + i 44 | nki := n - k + i 45 | var aii float64 46 | aii, tau[i] = impl.Dlarfg(nki+1, a[mki*lda+nki], a[mki*lda:], 1) 47 | 48 | // Apply H[i] to A[0:m-k+i-1, 0:n-k+i] from the right. 49 | a[mki*lda+nki] = 1 50 | impl.Dlarf(blas.Right, mki, nki+1, a[mki*lda:], 1, tau[i], a, lda, work) 51 | a[mki*lda+nki] = aii 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /native/dgetf2.go: -------------------------------------------------------------------------------- 1 | // Copyright ©2015 The gonum Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package native 6 | 7 | import ( 8 | "math" 9 | 10 | "github.com/gonum/blas/blas64" 11 | ) 12 | 13 | // Dgetf2 computes the LU decomposition of the m×n matrix A. 14 | // The LU decomposition is a factorization of a into 15 | // A = P * L * U 16 | // where P is a permutation matrix, L is a unit lower triangular matrix, and 17 | // U is a (usually) non-unit upper triangular matrix. On exit, L and U are stored 18 | // in place into a. 19 | // 20 | // ipiv is a permutation vector. It indicates that row i of the matrix was 21 | // changed with ipiv[i]. ipiv must have length at least min(m,n), and will panic 22 | // otherwise. ipiv is zero-indexed. 23 | // 24 | // Dgetf2 returns whether the matrix A is singular. The LU decomposition will 25 | // be computed regardless of the singularity of A, but division by zero 26 | // will occur if the false is returned and the result is used to solve a 27 | // system of equations. 28 | // 29 | // Dgetf2 is an internal routine. It is exported for testing purposes. 30 | func (Implementation) Dgetf2(m, n int, a []float64, lda int, ipiv []int) (ok bool) { 31 | mn := min(m, n) 32 | checkMatrix(m, n, a, lda) 33 | if len(ipiv) < mn { 34 | panic(badIpiv) 35 | } 36 | if m == 0 || n == 0 { 37 | return true 38 | } 39 | bi := blas64.Implementation() 40 | sfmin := dlamchS 41 | ok = true 42 | for j := 0; j < mn; j++ { 43 | // Find a pivot and test for singularity. 44 | jp := j + bi.Idamax(m-j, a[j*lda+j:], lda) 45 | ipiv[j] = jp 46 | if a[jp*lda+j] == 0 { 47 | ok = false 48 | } else { 49 | // Swap the rows if necessary. 50 | if jp != j { 51 | bi.Dswap(n, a[j*lda:], 1, a[jp*lda:], 1) 52 | } 53 | if j < m-1 { 54 | aj := a[j*lda+j] 55 | if math.Abs(aj) >= sfmin { 56 | bi.Dscal(m-j-1, 1/aj, a[(j+1)*lda+j:], lda) 57 | } else { 58 | for i := 0; i < m-j-1; i++ { 59 | a[(j+1)*lda+j] = a[(j+1)*lda+j] / a[lda*j+j] 60 | } 61 | } 62 | } 63 | } 64 | if j < mn-1 { 65 | bi.Dger(m-j-1, n-j-1, -1, a[(j+1)*lda+j:], lda, a[j*lda+j+1:], 1, a[(j+1)*lda+j+1:], lda) 66 | } 67 | } 68 | return ok 69 | } 70 | -------------------------------------------------------------------------------- /native/dgetrf.go: -------------------------------------------------------------------------------- 1 | // Copyright ©2015 The gonum Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package native 6 | 7 | import ( 8 | "github.com/gonum/blas" 9 | "github.com/gonum/blas/blas64" 10 | ) 11 | 12 | // Dgetrf computes the LU decomposition of the m×n matrix A. 13 | // The LU decomposition is a factorization of A into 14 | // A = P * L * U 15 | // where P is a permutation matrix, L is a unit lower triangular matrix, and 16 | // U is a (usually) non-unit upper triangular matrix. On exit, L and U are stored 17 | // in place into a. 18 | // 19 | // ipiv is a permutation vector. It indicates that row i of the matrix was 20 | // changed with ipiv[i]. ipiv must have length at least min(m,n), and will panic 21 | // otherwise. ipiv is zero-indexed. 22 | // 23 | // Dgetrf is the blocked version of the algorithm. 24 | // 25 | // Dgetrf returns whether the matrix A is singular. The LU decomposition will 26 | // be computed regardless of the singularity of A, but division by zero 27 | // will occur if the false is returned and the result is used to solve a 28 | // system of equations. 29 | func (impl Implementation) Dgetrf(m, n int, a []float64, lda int, ipiv []int) (ok bool) { 30 | mn := min(m, n) 31 | checkMatrix(m, n, a, lda) 32 | if len(ipiv) < mn { 33 | panic(badIpiv) 34 | } 35 | if m == 0 || n == 0 { 36 | return false 37 | } 38 | bi := blas64.Implementation() 39 | nb := impl.Ilaenv(1, "DGETRF", " ", m, n, -1, -1) 40 | if nb <= 1 || nb >= min(m, n) { 41 | // Use the unblocked algorithm. 42 | return impl.Dgetf2(m, n, a, lda, ipiv) 43 | } 44 | ok = true 45 | for j := 0; j < mn; j += nb { 46 | jb := min(mn-j, nb) 47 | blockOk := impl.Dgetf2(m-j, jb, a[j*lda+j:], lda, ipiv[j:]) 48 | if !blockOk { 49 | ok = false 50 | } 51 | for i := j; i <= min(m-1, j+jb-1); i++ { 52 | ipiv[i] = j + ipiv[i] 53 | } 54 | impl.Dlaswp(j, a, lda, j, j+jb-1, ipiv[:j+jb], 1) 55 | if j+jb < n { 56 | impl.Dlaswp(n-j-jb, a[j+jb:], lda, j, j+jb-1, ipiv[:j+jb], 1) 57 | bi.Dtrsm(blas.Left, blas.Lower, blas.NoTrans, blas.Unit, 58 | jb, n-j-jb, 1, 59 | a[j*lda+j:], lda, 60 | a[j*lda+j+jb:], lda) 61 | if j+jb < m { 62 | bi.Dgemm(blas.NoTrans, blas.NoTrans, m-j-jb, n-j-jb, jb, -1, 63 | a[(j+jb)*lda+j:], lda, 64 | a[j*lda+j+jb:], lda, 65 | 1, a[(j+jb)*lda+j+jb:], lda) 66 | } 67 | } 68 | } 69 | return ok 70 | } 71 | -------------------------------------------------------------------------------- /native/dgetri.go: -------------------------------------------------------------------------------- 1 | // Copyright ©2015 The gonum Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package native 6 | 7 | import ( 8 | "github.com/gonum/blas" 9 | "github.com/gonum/blas/blas64" 10 | ) 11 | 12 | // Dgetri computes the inverse of the matrix A using the LU factorization computed 13 | // by Dgetrf. On entry, a contains the PLU decomposition of A as computed by 14 | // Dgetrf and on exit contains the reciprocal of the original matrix. 15 | // 16 | // Dgetri will not perform the inversion if the matrix is singular, and returns 17 | // a boolean indicating whether the inversion was successful. 18 | // 19 | // work is temporary storage, and lwork specifies the usable memory length. 20 | // At minimum, lwork >= n and this function will panic otherwise. 21 | // Dgetri is a blocked inversion, but the block size is limited 22 | // by the temporary space available. If lwork == -1, instead of performing Dgetri, 23 | // the optimal work length will be stored into work[0]. 24 | func (impl Implementation) Dgetri(n int, a []float64, lda int, ipiv []int, work []float64, lwork int) (ok bool) { 25 | checkMatrix(n, n, a, lda) 26 | if len(ipiv) < n { 27 | panic(badIpiv) 28 | } 29 | nb := impl.Ilaenv(1, "DGETRI", " ", n, -1, -1, -1) 30 | if lwork == -1 { 31 | work[0] = float64(n * nb) 32 | return true 33 | } 34 | if lwork < n { 35 | panic(badWork) 36 | } 37 | if len(work) < lwork { 38 | panic(badWork) 39 | } 40 | if n == 0 { 41 | return true 42 | } 43 | ok = impl.Dtrtri(blas.Upper, blas.NonUnit, n, a, lda) 44 | if !ok { 45 | return false 46 | } 47 | nbmin := 2 48 | ldwork := nb 49 | if nb > 1 && nb < n { 50 | iws := max(ldwork*n, 1) 51 | if lwork < iws { 52 | nb = lwork / ldwork 53 | nbmin = max(2, impl.Ilaenv(2, "DGETRI", " ", n, -1, -1, -1)) 54 | } 55 | } 56 | bi := blas64.Implementation() 57 | // TODO(btracey): Replace this with a more row-major oriented algorithm. 58 | if nb < nbmin || nb >= n { 59 | // Unblocked code. 60 | for j := n - 1; j >= 0; j-- { 61 | for i := j + 1; i < n; i++ { 62 | work[i*ldwork] = a[i*lda+j] 63 | a[i*lda+j] = 0 64 | } 65 | if j < n { 66 | bi.Dgemv(blas.NoTrans, n, n-j-1, -1, a[(j+1):], lda, work[(j+1)*ldwork:], ldwork, 1, a[j:], lda) 67 | } 68 | } 69 | } else { 70 | nn := ((n - 1) / nb) * nb 71 | for j := nn; j >= 0; j -= nb { 72 | jb := min(nb, n-j) 73 | for jj := j; jj < j+jb-1; jj++ { 74 | for i := jj + 1; i < n; i++ { 75 | work[i*ldwork+(jj-j)] = a[i*lda+jj] 76 | a[i*lda+jj] = 0 77 | } 78 | } 79 | if j+jb < n { 80 | bi.Dgemm(blas.NoTrans, blas.NoTrans, n, jb, n-j-jb, -1, a[(j+jb):], lda, work[(j+jb)*ldwork:], ldwork, 1, a[j:], lda) 81 | bi.Dtrsm(blas.Right, blas.Lower, blas.NoTrans, blas.Unit, n, jb, 1, work[j*ldwork:], ldwork, a[j:], lda) 82 | } 83 | } 84 | } 85 | for j := n - 2; j >= 0; j-- { 86 | jp := ipiv[j] 87 | if jp != j { 88 | bi.Dswap(n, a[j:], lda, a[jp:], lda) 89 | } 90 | } 91 | return true 92 | } 93 | -------------------------------------------------------------------------------- /native/dgetrs.go: -------------------------------------------------------------------------------- 1 | // Copyright ©2015 The gonum Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package native 6 | 7 | import ( 8 | "github.com/gonum/blas" 9 | "github.com/gonum/blas/blas64" 10 | ) 11 | 12 | // Dgetrs solves a system of equations using an LU factorization. 13 | // The system of equations solved is 14 | // A * X = B if trans == blas.Trans 15 | // A^T * X = B if trans == blas.NoTrans 16 | // A is a general n×n matrix with stride lda. B is a general matrix of size n×nrhs. 17 | // 18 | // On entry b contains the elements of the matrix B. On exit, b contains the 19 | // elements of X, the solution to the system of equations. 20 | // 21 | // a and ipiv contain the LU factorization of A and the permutation indices as 22 | // computed by Dgetrf. ipiv is zero-indexed. 23 | func (impl Implementation) Dgetrs(trans blas.Transpose, n, nrhs int, a []float64, lda int, ipiv []int, b []float64, ldb int) { 24 | checkMatrix(n, n, a, lda) 25 | checkMatrix(n, nrhs, b, ldb) 26 | if len(ipiv) < n { 27 | panic(badIpiv) 28 | } 29 | if n == 0 || nrhs == 0 { 30 | return 31 | } 32 | if trans != blas.Trans && trans != blas.NoTrans { 33 | panic(badTrans) 34 | } 35 | bi := blas64.Implementation() 36 | if trans == blas.NoTrans { 37 | // Solve A * X = B. 38 | impl.Dlaswp(nrhs, b, ldb, 0, n-1, ipiv, 1) 39 | // Solve L * X = B, updating b. 40 | bi.Dtrsm(blas.Left, blas.Lower, blas.NoTrans, blas.Unit, 41 | n, nrhs, 1, a, lda, b, ldb) 42 | // Solve U * X = B, updating b. 43 | bi.Dtrsm(blas.Left, blas.Upper, blas.NoTrans, blas.NonUnit, 44 | n, nrhs, 1, a, lda, b, ldb) 45 | return 46 | } 47 | // Solve A^T * X = B. 48 | // Solve U^T * X = B, updating b. 49 | bi.Dtrsm(blas.Left, blas.Upper, blas.Trans, blas.NonUnit, 50 | n, nrhs, 1, a, lda, b, ldb) 51 | // Solve L^T * X = B, updating b. 52 | bi.Dtrsm(blas.Left, blas.Lower, blas.Trans, blas.Unit, 53 | n, nrhs, 1, a, lda, b, ldb) 54 | impl.Dlaswp(nrhs, b, ldb, 0, n-1, ipiv, -1) 55 | } 56 | -------------------------------------------------------------------------------- /native/dlacpy.go: -------------------------------------------------------------------------------- 1 | // Copyright ©2015 The gonum Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package native 6 | 7 | import "github.com/gonum/blas" 8 | 9 | // Dlacpy copies the elements of A specified by uplo into B. Uplo can specify 10 | // a triangular portion with blas.Upper or blas.Lower, or can specify all of the 11 | // elemest with blas.All. 12 | // 13 | // Dlacpy is an internal routine. It is exported for testing purposes. 14 | func (impl Implementation) Dlacpy(uplo blas.Uplo, m, n int, a []float64, lda int, b []float64, ldb int) { 15 | checkMatrix(m, n, a, lda) 16 | checkMatrix(m, n, b, ldb) 17 | switch uplo { 18 | default: 19 | panic(badUplo) 20 | case blas.Upper: 21 | for i := 0; i < m; i++ { 22 | for j := i; j < n; j++ { 23 | b[i*ldb+j] = a[i*lda+j] 24 | } 25 | } 26 | 27 | case blas.Lower: 28 | for i := 0; i < m; i++ { 29 | for j := 0; j < min(i+1, n); j++ { 30 | b[i*ldb+j] = a[i*lda+j] 31 | } 32 | } 33 | case blas.All: 34 | for i := 0; i < m; i++ { 35 | for j := 0; j < n; j++ { 36 | b[i*ldb+j] = a[i*lda+j] 37 | } 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /native/dlae2.go: -------------------------------------------------------------------------------- 1 | // Copyright ©2016 The gonum Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package native 6 | 7 | import "math" 8 | 9 | // Dlae2 computes the eigenvalues of a 2×2 symmetric matrix 10 | // [a b] 11 | // [b c] 12 | // and returns the eigenvalue with the larger absolute value as rt1 and the 13 | // smaller as rt2. 14 | // 15 | // Dlae2 is an internal routine. It is exported for testing purposes. 16 | func (impl Implementation) Dlae2(a, b, c float64) (rt1, rt2 float64) { 17 | sm := a + c 18 | df := a - c 19 | adf := math.Abs(df) 20 | tb := b + b 21 | ab := math.Abs(tb) 22 | acmx := c 23 | acmn := a 24 | if math.Abs(a) > math.Abs(c) { 25 | acmx = a 26 | acmn = c 27 | } 28 | var rt float64 29 | if adf > ab { 30 | rt = adf * math.Sqrt(1+(ab/adf)*(ab/adf)) 31 | } else if adf < ab { 32 | rt = ab * math.Sqrt(1+(adf/ab)*(adf/ab)) 33 | } else { 34 | rt = ab * math.Sqrt2 35 | } 36 | if sm < 0 { 37 | rt1 = 0.5 * (sm - rt) 38 | rt2 = (acmx/rt1)*acmn - (b/rt1)*b 39 | return rt1, rt2 40 | } 41 | if sm > 0 { 42 | rt1 = 0.5 * (sm + rt) 43 | rt2 = (acmx/rt1)*acmn - (b/rt1)*b 44 | return rt1, rt2 45 | } 46 | rt1 = 0.5 * rt 47 | rt2 = -0.5 * rt 48 | return rt1, rt2 49 | } 50 | -------------------------------------------------------------------------------- /native/dlaev2.go: -------------------------------------------------------------------------------- 1 | // Copyright ©2015 The gonum Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package native 6 | 7 | import "math" 8 | 9 | // Dlaev2 computes the Eigen decomposition of a symmetric 2×2 matrix. 10 | // The matrix is given by 11 | // [a b] 12 | // [b c] 13 | // Dlaev2 returns rt1 and rt2, the eigenvalues of the matrix where |RT1| > |RT2|, 14 | // and [cs1, sn1] which is the unit right eigenvalue for RT1. 15 | // [ cs1 sn1] [a b] [cs1 -sn1] = [rt1 0] 16 | // [-sn1 cs1] [b c] [sn1 cs1] [ 0 rt2] 17 | // 18 | // Dlaev2 is an internal routine. It is exported for testing purposes. 19 | func (impl Implementation) Dlaev2(a, b, c float64) (rt1, rt2, cs1, sn1 float64) { 20 | sm := a + c 21 | df := a - c 22 | adf := math.Abs(df) 23 | tb := b + b 24 | ab := math.Abs(tb) 25 | acmx := c 26 | acmn := a 27 | if math.Abs(a) > math.Abs(c) { 28 | acmx = a 29 | acmn = c 30 | } 31 | var rt float64 32 | if adf > ab { 33 | rt = adf * math.Sqrt(1+(ab/adf)*(ab/adf)) 34 | } else if adf < ab { 35 | rt = ab * math.Sqrt(1+(adf/ab)*(adf/ab)) 36 | } else { 37 | rt = ab * math.Sqrt(2) 38 | } 39 | var sgn1 float64 40 | if sm < 0 { 41 | rt1 = 0.5 * (sm - rt) 42 | sgn1 = -1 43 | rt2 = (acmx/rt1)*acmn - (b/rt1)*b 44 | } else if sm > 0 { 45 | rt1 = 0.5 * (sm + rt) 46 | sgn1 = 1 47 | rt2 = (acmx/rt1)*acmn - (b/rt1)*b 48 | } else { 49 | rt1 = 0.5 * rt 50 | rt2 = -0.5 * rt 51 | sgn1 = 1 52 | } 53 | var cs, sgn2 float64 54 | if df >= 0 { 55 | cs = df + rt 56 | sgn2 = 1 57 | } else { 58 | cs = df - rt 59 | sgn2 = -1 60 | } 61 | acs := math.Abs(cs) 62 | if acs > ab { 63 | ct := -tb / cs 64 | sn1 = 1 / math.Sqrt(1+ct*ct) 65 | cs1 = ct * sn1 66 | } else { 67 | if ab == 0 { 68 | cs1 = 1 69 | sn1 = 0 70 | } else { 71 | tn := -cs / tb 72 | cs1 = 1 / math.Sqrt(1+tn*tn) 73 | sn1 = tn * cs1 74 | } 75 | } 76 | if sgn1 == sgn2 { 77 | tn := cs1 78 | cs1 = -sn1 79 | sn1 = tn 80 | } 81 | return rt1, rt2, cs1, sn1 82 | } 83 | -------------------------------------------------------------------------------- /native/dlange.go: -------------------------------------------------------------------------------- 1 | // Copyright ©2015 The gonum Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package native 6 | 7 | import ( 8 | "math" 9 | 10 | "github.com/gonum/lapack" 11 | ) 12 | 13 | // Dlange computes the matrix norm of the general m×n matrix a. The input norm 14 | // specifies the norm computed. 15 | // lapack.MaxAbs: the maximum absolute value of an element. 16 | // lapack.MaxColumnSum: the maximum column sum of the absolute values of the entries. 17 | // lapack.MaxRowSum: the maximum row sum of the absolute values of the entries. 18 | // lapack.NormFrob: the square root of the sum of the squares of the entries. 19 | // If norm == lapack.MaxColumnSum, work must be of length n, and this function will panic otherwise. 20 | // There are no restrictions on work for the other matrix norms. 21 | func (impl Implementation) Dlange(norm lapack.MatrixNorm, m, n int, a []float64, lda int, work []float64) float64 { 22 | // TODO(btracey): These should probably be refactored to use BLAS calls. 23 | checkMatrix(m, n, a, lda) 24 | switch norm { 25 | case lapack.MaxRowSum, lapack.MaxColumnSum, lapack.NormFrob, lapack.MaxAbs: 26 | default: 27 | panic(badNorm) 28 | } 29 | if norm == lapack.MaxColumnSum && len(work) < n { 30 | panic(badWork) 31 | } 32 | if m == 0 && n == 0 { 33 | return 0 34 | } 35 | if norm == lapack.MaxAbs { 36 | var value float64 37 | for i := 0; i < m; i++ { 38 | for j := 0; j < n; j++ { 39 | value = math.Max(value, math.Abs(a[i*lda+j])) 40 | } 41 | } 42 | return value 43 | } 44 | if norm == lapack.MaxColumnSum { 45 | if len(work) < n { 46 | panic(badWork) 47 | } 48 | for i := 0; i < n; i++ { 49 | work[i] = 0 50 | } 51 | for i := 0; i < m; i++ { 52 | for j := 0; j < n; j++ { 53 | work[j] += math.Abs(a[i*lda+j]) 54 | } 55 | } 56 | var value float64 57 | for i := 0; i < n; i++ { 58 | value = math.Max(value, work[i]) 59 | } 60 | return value 61 | } 62 | if norm == lapack.MaxRowSum { 63 | var value float64 64 | for i := 0; i < m; i++ { 65 | var sum float64 66 | for j := 0; j < n; j++ { 67 | sum += math.Abs(a[i*lda+j]) 68 | } 69 | value = math.Max(value, sum) 70 | } 71 | return value 72 | } 73 | if norm == lapack.NormFrob { 74 | var value float64 75 | scale := 0.0 76 | sum := 1.0 77 | for i := 0; i < m; i++ { 78 | scale, sum = impl.Dlassq(n, a[i*lda:], 1, scale, sum) 79 | } 80 | value = scale * math.Sqrt(sum) 81 | return value 82 | } 83 | panic("lapack: bad matrix norm") 84 | } 85 | -------------------------------------------------------------------------------- /native/dlanst.go: -------------------------------------------------------------------------------- 1 | // Copyright ©2016 The gonum Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package native 6 | 7 | import ( 8 | "math" 9 | 10 | "github.com/gonum/lapack" 11 | ) 12 | 13 | // Dlanst computes the specified norm of a symmetric tridiagonal matrix A. 14 | // The diagonal elements of A are stored in d and the off-diagonal elements 15 | // are stored in e. 16 | func (impl Implementation) Dlanst(norm lapack.MatrixNorm, n int, d, e []float64) float64 { 17 | if len(d) < n { 18 | panic(badD) 19 | } 20 | if len(e) < n-1 { 21 | panic(badE) 22 | } 23 | if n <= 0 { 24 | return 0 25 | } 26 | switch norm { 27 | default: 28 | panic(badNorm) 29 | case lapack.MaxAbs: 30 | anorm := math.Abs(d[n-1]) 31 | for i := 0; i < n-1; i++ { 32 | sum := math.Abs(d[i]) 33 | if anorm < sum || math.IsNaN(sum) { 34 | anorm = sum 35 | } 36 | sum = math.Abs(e[i]) 37 | if anorm < sum || math.IsNaN(sum) { 38 | anorm = sum 39 | } 40 | } 41 | return anorm 42 | case lapack.MaxColumnSum, lapack.MaxRowSum: 43 | if n == 1 { 44 | return math.Abs(d[0]) 45 | } 46 | anorm := math.Abs(d[0]) + math.Abs(e[0]) 47 | sum := math.Abs(e[n-2]) + math.Abs(d[n-1]) 48 | if anorm < sum || math.IsNaN(sum) { 49 | anorm = sum 50 | } 51 | for i := 1; i < n-1; i++ { 52 | sum := math.Abs(d[i]) + math.Abs(e[i]) + math.Abs(e[i-1]) 53 | if anorm < sum || math.IsNaN(sum) { 54 | anorm = sum 55 | } 56 | } 57 | return anorm 58 | case lapack.NormFrob: 59 | var scale float64 60 | sum := 1.0 61 | if n > 1 { 62 | scale, sum = impl.Dlassq(n-1, e, 1, scale, sum) 63 | sum = 2 * sum 64 | } 65 | scale, sum = impl.Dlassq(n, d, 1, scale, sum) 66 | return scale * math.Sqrt(sum) 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /native/dlapll.go: -------------------------------------------------------------------------------- 1 | // Copyright ©2017 The gonum Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package native 6 | 7 | import "github.com/gonum/blas/blas64" 8 | 9 | // Dlapll returns the smallest singular value of the n×2 matrix A = [ x y ]. 10 | // The function first computes the QR factorization of A = Q*R, and then computes 11 | // the SVD of the 2-by-2 upper triangular matrix r. 12 | // 13 | // The contents of x and y are overwritten during the call. 14 | // 15 | // Dlapll is an internal routine. It is exported for testing purposes. 16 | func (impl Implementation) Dlapll(n int, x []float64, incX int, y []float64, incY int) float64 { 17 | checkVector(n, x, incX) 18 | checkVector(n, y, incY) 19 | 20 | if n <= 1 { 21 | return 0 22 | } 23 | 24 | // Compute the QR factorization of the N-by-2 matrix [ X Y ]. 25 | a00, tau := impl.Dlarfg(n, x[0], x[incX:], incX) 26 | x[0] = 1 27 | 28 | bi := blas64.Implementation() 29 | c := -tau * bi.Ddot(n, x, incX, y, incY) 30 | bi.Daxpy(n, c, x, incX, y, incY) 31 | a11, _ := impl.Dlarfg(n-1, y[incY], y[2*incY:], incY) 32 | 33 | // Compute the SVD of 2-by-2 upper triangular matrix. 34 | ssmin, _ := impl.Dlas2(a00, y[0], a11) 35 | return ssmin 36 | } 37 | -------------------------------------------------------------------------------- /native/dlapmt.go: -------------------------------------------------------------------------------- 1 | // Copyright ©2017 The gonum Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package native 6 | 7 | import "github.com/gonum/blas/blas64" 8 | 9 | // Dlapmt rearranges the columns of the m×n matrix X as specified by the 10 | // permutation k_0, k_1, ..., k_n-1 of the integers 0, ..., n-1. 11 | // 12 | // If forward is true a forward permutation is performed: 13 | // 14 | // X[0:m, k[j]] is moved to X[0:m, j] for j = 0, 1, ..., n-1. 15 | // 16 | // otherwise a backward permutation is performed: 17 | // 18 | // X[0:m, j] is moved to X[0:m, k[j]] for j = 0, 1, ..., n-1. 19 | // 20 | // k must have length n, otherwise Dlapmt will panic. k is zero-indexed. 21 | func (impl Implementation) Dlapmt(forward bool, m, n int, x []float64, ldx int, k []int) { 22 | checkMatrix(m, n, x, ldx) 23 | if len(k) != n { 24 | panic(badKperm) 25 | } 26 | 27 | if n <= 1 { 28 | return 29 | } 30 | 31 | for i, v := range k { 32 | v++ 33 | k[i] = -v 34 | } 35 | 36 | bi := blas64.Implementation() 37 | 38 | if forward { 39 | for j, v := range k { 40 | if v >= 0 { 41 | continue 42 | } 43 | k[j] = -v 44 | i := -v - 1 45 | for k[i] < 0 { 46 | bi.Dswap(m, x[j:], ldx, x[i:], ldx) 47 | 48 | k[i] = -k[i] 49 | j = i 50 | i = k[i] - 1 51 | } 52 | } 53 | } else { 54 | for i, v := range k { 55 | if v >= 0 { 56 | continue 57 | } 58 | k[i] = -v 59 | j := -v - 1 60 | for j != i { 61 | bi.Dswap(m, x[j:], ldx, x[i:], ldx) 62 | 63 | k[j] = -k[j] 64 | j = k[j] - 1 65 | } 66 | } 67 | } 68 | 69 | for i := range k { 70 | k[i]-- 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /native/dlapy2.go: -------------------------------------------------------------------------------- 1 | // Copyright ©2015 The gonum Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package native 6 | 7 | import "math" 8 | 9 | // Dlapy2 is the LAPACK version of math.Hypot. 10 | // 11 | // Dlapy2 is an internal routine. It is exported for testing purposes. 12 | func (Implementation) Dlapy2(x, y float64) float64 { 13 | return math.Hypot(x, y) 14 | } 15 | -------------------------------------------------------------------------------- /native/dlaqr1.go: -------------------------------------------------------------------------------- 1 | // Copyright ©2016 The gonum Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package native 6 | 7 | import "math" 8 | 9 | // Dlaqr1 sets v to a scalar multiple of the first column of the product 10 | // (H - (sr1 + i*si1)*I)*(H - (sr2 + i*si2)*I) 11 | // where H is a 2×2 or 3×3 matrix, I is the identity matrix of the same size, 12 | // and i is the imaginary unit. Scaling is done to avoid overflows and most 13 | // underflows. 14 | // 15 | // n is the order of H and must be either 2 or 3. It must hold that either sr1 = 16 | // sr2 and si1 = -si2, or si1 = si2 = 0. The length of v must be equal to n. If 17 | // any of these conditions is not met, Dlaqr1 will panic. 18 | // 19 | // Dlaqr1 is an internal routine. It is exported for testing purposes. 20 | func (impl Implementation) Dlaqr1(n int, h []float64, ldh int, sr1, si1, sr2, si2 float64, v []float64) { 21 | if n != 2 && n != 3 { 22 | panic(badDims) 23 | } 24 | checkMatrix(n, n, h, ldh) 25 | if len(v) != n { 26 | panic(badSlice) 27 | } 28 | if !((sr1 == sr2 && si1 == -si2) || (si1 == 0 && si2 == 0)) { 29 | panic(badShifts) 30 | } 31 | 32 | if n == 2 { 33 | s := math.Abs(h[0]-sr2) + math.Abs(si2) + math.Abs(h[ldh]) 34 | if s == 0 { 35 | v[0] = 0 36 | v[1] = 0 37 | } else { 38 | h21s := h[ldh] / s 39 | v[0] = h21s*h[1] + (h[0]-sr1)*((h[0]-sr2)/s) - si1*(si2/s) 40 | v[1] = h21s * (h[0] + h[ldh+1] - sr1 - sr2) 41 | } 42 | return 43 | } 44 | 45 | s := math.Abs(h[0]-sr2) + math.Abs(si2) + math.Abs(h[ldh]) + math.Abs(h[2*ldh]) 46 | if s == 0 { 47 | v[0] = 0 48 | v[1] = 0 49 | v[2] = 0 50 | } else { 51 | h21s := h[ldh] / s 52 | h31s := h[2*ldh] / s 53 | v[0] = (h[0]-sr1)*((h[0]-sr2)/s) - si1*(si2/s) + h[1]*h21s + h[2]*h31s 54 | v[1] = h21s*(h[0]+h[ldh+1]-sr1-sr2) + h[ldh+2]*h31s 55 | v[2] = h31s*(h[0]+h[2*ldh+2]-sr1-sr2) + h21s*h[2*ldh+1] 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /native/dlarf.go: -------------------------------------------------------------------------------- 1 | // Copyright ©2015 The gonum Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package native 6 | 7 | import ( 8 | "github.com/gonum/blas" 9 | "github.com/gonum/blas/blas64" 10 | ) 11 | 12 | // Dlarf applies an elementary reflector to a general rectangular matrix c. 13 | // This computes 14 | // c = h * c if side == Left 15 | // c = c * h if side == right 16 | // where 17 | // h = 1 - tau * v * v^T 18 | // and c is an m * n matrix. 19 | // 20 | // work is temporary storage of length at least m if side == Left and at least 21 | // n if side == Right. This function will panic if this length requirement is not met. 22 | // 23 | // Dlarf is an internal routine. It is exported for testing purposes. 24 | func (impl Implementation) Dlarf(side blas.Side, m, n int, v []float64, incv int, tau float64, c []float64, ldc int, work []float64) { 25 | applyleft := side == blas.Left 26 | if (applyleft && len(work) < n) || (!applyleft && len(work) < m) { 27 | panic(badWork) 28 | } 29 | checkMatrix(m, n, c, ldc) 30 | 31 | // v has length m if applyleft and n otherwise. 32 | lenV := n 33 | if applyleft { 34 | lenV = m 35 | } 36 | 37 | checkVector(lenV, v, incv) 38 | 39 | lastv := 0 // last non-zero element of v 40 | lastc := 0 // last non-zero row/column of c 41 | if tau != 0 { 42 | var i int 43 | if applyleft { 44 | lastv = m - 1 45 | } else { 46 | lastv = n - 1 47 | } 48 | if incv > 0 { 49 | i = lastv * incv 50 | } 51 | 52 | // Look for the last non-zero row in v. 53 | for lastv >= 0 && v[i] == 0 { 54 | lastv-- 55 | i -= incv 56 | } 57 | if applyleft { 58 | // Scan for the last non-zero column in C[0:lastv, :] 59 | lastc = impl.Iladlc(lastv+1, n, c, ldc) 60 | } else { 61 | // Scan for the last non-zero row in C[:, 0:lastv] 62 | lastc = impl.Iladlr(m, lastv+1, c, ldc) 63 | } 64 | } 65 | if lastv == -1 || lastc == -1 { 66 | return 67 | } 68 | // Sometimes 1-indexing is nicer ... 69 | bi := blas64.Implementation() 70 | if applyleft { 71 | // Form H * C 72 | // w[0:lastc+1] = c[1:lastv+1, 1:lastc+1]^T * v[1:lastv+1,1] 73 | bi.Dgemv(blas.Trans, lastv+1, lastc+1, 1, c, ldc, v, incv, 0, work, 1) 74 | // c[0: lastv, 0: lastc] = c[...] - w[0:lastv, 1] * v[1:lastc, 1]^T 75 | bi.Dger(lastv+1, lastc+1, -tau, v, incv, work, 1, c, ldc) 76 | return 77 | } 78 | // Form C*H 79 | // w[0:lastc+1,1] := c[0:lastc+1,0:lastv+1] * v[0:lastv+1,1] 80 | bi.Dgemv(blas.NoTrans, lastc+1, lastv+1, 1, c, ldc, v, incv, 0, work, 1) 81 | // c[0:lastc+1,0:lastv+1] = c[...] - w[0:lastc+1,0] * v[0:lastv+1,0]^T 82 | bi.Dger(lastc+1, lastv+1, -tau, work, 1, v, incv, c, ldc) 83 | } 84 | -------------------------------------------------------------------------------- /native/dlarfg.go: -------------------------------------------------------------------------------- 1 | // Copyright ©2015 The gonum Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package native 6 | 7 | import ( 8 | "math" 9 | 10 | "github.com/gonum/blas/blas64" 11 | ) 12 | 13 | // Dlarfg generates an elementary reflector for a Householder matrix. It creates 14 | // a real elementary reflector of order n such that 15 | // H * (alpha) = (beta) 16 | // ( x) ( 0) 17 | // H^T * H = I 18 | // H is represented in the form 19 | // H = 1 - tau * (1; v) * (1 v^T) 20 | // where tau is a real scalar. 21 | // 22 | // On entry, x contains the vector x, on exit it contains v. 23 | // 24 | // Dlarfg is an internal routine. It is exported for testing purposes. 25 | func (impl Implementation) Dlarfg(n int, alpha float64, x []float64, incX int) (beta, tau float64) { 26 | if n < 0 { 27 | panic(nLT0) 28 | } 29 | if n <= 1 { 30 | return alpha, 0 31 | } 32 | checkVector(n-1, x, incX) 33 | bi := blas64.Implementation() 34 | xnorm := bi.Dnrm2(n-1, x, incX) 35 | if xnorm == 0 { 36 | return alpha, 0 37 | } 38 | beta = -math.Copysign(impl.Dlapy2(alpha, xnorm), alpha) 39 | safmin := dlamchS / dlamchE 40 | knt := 0 41 | if math.Abs(beta) < safmin { 42 | // xnorm and beta may be inaccurate, scale x and recompute. 43 | rsafmn := 1 / safmin 44 | for { 45 | knt++ 46 | bi.Dscal(n-1, rsafmn, x, incX) 47 | beta *= rsafmn 48 | alpha *= rsafmn 49 | if math.Abs(beta) >= safmin { 50 | break 51 | } 52 | } 53 | xnorm = bi.Dnrm2(n-1, x, incX) 54 | beta = -math.Copysign(impl.Dlapy2(alpha, xnorm), alpha) 55 | } 56 | tau = (beta - alpha) / beta 57 | bi.Dscal(n-1, 1/(alpha-beta), x, incX) 58 | for j := 0; j < knt; j++ { 59 | beta *= safmin 60 | } 61 | return beta, tau 62 | } 63 | -------------------------------------------------------------------------------- /native/dlartg.go: -------------------------------------------------------------------------------- 1 | // Copyright ©2015 The gonum Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package native 6 | 7 | import "math" 8 | 9 | // Dlartg generates a plane rotation so that 10 | // [ cs sn] * [f] = [r] 11 | // [-sn cs] [g] = [0] 12 | // This is a more accurate version of BLAS drotg, with the other differences that 13 | // if g = 0, then cs = 1 and sn = 0, and if f = 0 and g != 0, then cs = 0 and sn = 1. 14 | // If abs(f) > abs(g), cs will be positive. 15 | // 16 | // Dlartg is an internal routine. It is exported for testing purposes. 17 | func (impl Implementation) Dlartg(f, g float64) (cs, sn, r float64) { 18 | safmn2 := math.Pow(dlamchB, math.Trunc(math.Log(dlamchS/dlamchE)/math.Log(dlamchB)/2)) 19 | safmx2 := 1 / safmn2 20 | if g == 0 { 21 | cs = 1 22 | sn = 0 23 | r = f 24 | return cs, sn, r 25 | } 26 | if f == 0 { 27 | cs = 0 28 | sn = 1 29 | r = g 30 | return cs, sn, r 31 | } 32 | f1 := f 33 | g1 := g 34 | scale := math.Max(math.Abs(f1), math.Abs(g1)) 35 | if scale >= safmx2 { 36 | var count int 37 | for { 38 | count++ 39 | f1 *= safmn2 40 | g1 *= safmn2 41 | scale = math.Max(math.Abs(f1), math.Abs(g1)) 42 | if scale < safmx2 { 43 | break 44 | } 45 | } 46 | r = math.Sqrt(f1*f1 + g1*g1) 47 | cs = f1 / r 48 | sn = g1 / r 49 | for i := 0; i < count; i++ { 50 | r *= safmx2 51 | } 52 | } else if scale <= safmn2 { 53 | var count int 54 | for { 55 | count++ 56 | f1 *= safmx2 57 | g1 *= safmx2 58 | scale = math.Max(math.Abs(f1), math.Abs(g1)) 59 | if scale >= safmn2 { 60 | break 61 | } 62 | } 63 | r = math.Sqrt(f1*f1 + g1*g1) 64 | cs = f1 / r 65 | sn = g1 / r 66 | for i := 0; i < count; i++ { 67 | r *= safmn2 68 | } 69 | } else { 70 | r = math.Sqrt(f1*f1 + g1*g1) 71 | cs = f1 / r 72 | sn = g1 / r 73 | } 74 | if math.Abs(f) > math.Abs(g) && cs < 0 { 75 | cs *= -1 76 | sn *= -1 77 | r *= -1 78 | } 79 | return cs, sn, r 80 | } 81 | -------------------------------------------------------------------------------- /native/dlas2.go: -------------------------------------------------------------------------------- 1 | // Copyright ©2015 The gonum Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package native 6 | 7 | import "math" 8 | 9 | // Dlas2 computes the singular values of the 2×2 matrix defined by 10 | // [F G] 11 | // [0 H] 12 | // The smaller and larger singular values are returned in that order. 13 | // 14 | // Dlas2 is an internal routine. It is exported for testing purposes. 15 | func (impl Implementation) Dlas2(f, g, h float64) (ssmin, ssmax float64) { 16 | fa := math.Abs(f) 17 | ga := math.Abs(g) 18 | ha := math.Abs(h) 19 | fhmin := math.Min(fa, ha) 20 | fhmax := math.Max(fa, ha) 21 | if fhmin == 0 { 22 | if fhmax == 0 { 23 | return 0, ga 24 | } 25 | v := math.Min(fhmax, ga) / math.Max(fhmax, ga) 26 | return 0, math.Max(fhmax, ga) * math.Sqrt(1+v*v) 27 | } 28 | if ga < fhmax { 29 | as := 1 + fhmin/fhmax 30 | at := (fhmax - fhmin) / fhmax 31 | au := (ga / fhmax) * (ga / fhmax) 32 | c := 2 / (math.Sqrt(as*as+au) + math.Sqrt(at*at+au)) 33 | return fhmin * c, fhmax / c 34 | } 35 | au := fhmax / ga 36 | if au == 0 { 37 | return fhmin * fhmax / ga, ga 38 | } 39 | as := 1 + fhmin/fhmax 40 | at := (fhmax - fhmin) / fhmax 41 | c := 1 / (math.Sqrt(1+(as*au)*(as*au)) + math.Sqrt(1+(at*au)*(at*au))) 42 | return 2 * (fhmin * c) * au, ga / (c + c) 43 | } 44 | -------------------------------------------------------------------------------- /native/dlascl.go: -------------------------------------------------------------------------------- 1 | // Copyright ©2015 The gonum Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package native 6 | 7 | import ( 8 | "math" 9 | 10 | "github.com/gonum/lapack" 11 | ) 12 | 13 | // Dlascl multiplies an m×n matrix by the scalar cto/cfrom. 14 | // 15 | // cfrom must not be zero, and cto and cfrom must not be NaN, otherwise Dlascl 16 | // will panic. 17 | // 18 | // Dlascl is an internal routine. It is exported for testing purposes. 19 | func (impl Implementation) Dlascl(kind lapack.MatrixType, kl, ku int, cfrom, cto float64, m, n int, a []float64, lda int) { 20 | checkMatrix(m, n, a, lda) 21 | if cfrom == 0 { 22 | panic(zeroDiv) 23 | } 24 | if math.IsNaN(cfrom) || math.IsNaN(cto) { 25 | panic(nanScale) 26 | } 27 | if n == 0 || m == 0 { 28 | return 29 | } 30 | smlnum := dlamchS 31 | bignum := 1 / smlnum 32 | cfromc := cfrom 33 | ctoc := cto 34 | cfrom1 := cfromc * smlnum 35 | for { 36 | var done bool 37 | var mul, ctol float64 38 | if cfrom1 == cfromc { 39 | // cfromc is inf. 40 | mul = ctoc / cfromc 41 | done = true 42 | ctol = ctoc 43 | } else { 44 | ctol = ctoc / bignum 45 | if ctol == ctoc { 46 | // ctoc is either 0 or inf. 47 | mul = ctoc 48 | done = true 49 | cfromc = 1 50 | } else if math.Abs(cfrom1) > math.Abs(ctoc) && ctoc != 0 { 51 | mul = smlnum 52 | done = false 53 | cfromc = cfrom1 54 | } else if math.Abs(ctol) > math.Abs(cfromc) { 55 | mul = bignum 56 | done = false 57 | ctoc = ctol 58 | } else { 59 | mul = ctoc / cfromc 60 | done = true 61 | } 62 | } 63 | switch kind { 64 | default: 65 | panic("lapack: not implemented") 66 | case lapack.General: 67 | for i := 0; i < m; i++ { 68 | for j := 0; j < n; j++ { 69 | a[i*lda+j] = a[i*lda+j] * mul 70 | } 71 | } 72 | case lapack.UpperTri: 73 | for i := 0; i < m; i++ { 74 | for j := i; j < n; j++ { 75 | a[i*lda+j] = a[i*lda+j] * mul 76 | } 77 | } 78 | case lapack.LowerTri: 79 | for i := 0; i < m; i++ { 80 | for j := 0; j <= min(i, n-1); j++ { 81 | a[i*lda+j] = a[i*lda+j] * mul 82 | } 83 | } 84 | } 85 | if done { 86 | break 87 | } 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /native/dlaset.go: -------------------------------------------------------------------------------- 1 | // Copyright ©2015 The gonum Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package native 6 | 7 | import "github.com/gonum/blas" 8 | 9 | // Dlaset sets the off-diagonal elements of A to alpha, and the diagonal 10 | // elements to beta. If uplo == blas.Upper, only the elements in the upper 11 | // triangular part are set. If uplo == blas.Lower, only the elements in the 12 | // lower triangular part are set. If uplo is otherwise, all of the elements of A 13 | // are set. 14 | // 15 | // Dlaset is an internal routine. It is exported for testing purposes. 16 | func (impl Implementation) Dlaset(uplo blas.Uplo, m, n int, alpha, beta float64, a []float64, lda int) { 17 | checkMatrix(m, n, a, lda) 18 | if uplo == blas.Upper { 19 | for i := 0; i < m; i++ { 20 | for j := i + 1; j < n; j++ { 21 | a[i*lda+j] = alpha 22 | } 23 | } 24 | } else if uplo == blas.Lower { 25 | for i := 0; i < m; i++ { 26 | for j := 0; j < min(i+1, n); j++ { 27 | a[i*lda+j] = alpha 28 | } 29 | } 30 | } else { 31 | for i := 0; i < m; i++ { 32 | for j := 0; j < n; j++ { 33 | a[i*lda+j] = alpha 34 | } 35 | } 36 | } 37 | for i := 0; i < min(m, n); i++ { 38 | a[i*lda+i] = beta 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /native/dlasq1.go: -------------------------------------------------------------------------------- 1 | // Copyright ©2015 The gonum Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package native 6 | 7 | import ( 8 | "math" 9 | 10 | "github.com/gonum/blas/blas64" 11 | "github.com/gonum/lapack" 12 | ) 13 | 14 | // Dlasq1 computes the singular values of an n×n bidiagonal matrix with diagonal 15 | // d and off-diagonal e. On exit, d contains the singular values in decreasing 16 | // order, and e is overwritten. d must have length at least n, e must have 17 | // length at least n-1, and the input work must have length at least 4*n. Dlasq1 18 | // will panic if these conditions are not met. 19 | // 20 | // Dlasq1 is an internal routine. It is exported for testing purposes. 21 | func (impl Implementation) Dlasq1(n int, d, e, work []float64) (info int) { 22 | // TODO(btracey): replace info with an error. 23 | if n < 0 { 24 | panic(nLT0) 25 | } 26 | if len(work) < 4*n { 27 | panic(badWork) 28 | } 29 | if len(d) < n { 30 | panic("lapack: length of d less than n") 31 | } 32 | if len(e) < n-1 { 33 | panic("lapack: length of e less than n-1") 34 | } 35 | if n == 0 { 36 | return info 37 | } 38 | if n == 1 { 39 | d[0] = math.Abs(d[0]) 40 | return info 41 | } 42 | if n == 2 { 43 | d[1], d[0] = impl.Dlas2(d[0], e[0], d[1]) 44 | return info 45 | } 46 | // Estimate the largest singular value. 47 | var sigmx float64 48 | for i := 0; i < n-1; i++ { 49 | d[i] = math.Abs(d[i]) 50 | sigmx = math.Max(sigmx, math.Abs(e[i])) 51 | } 52 | d[n-1] = math.Abs(d[n-1]) 53 | // Early return if sigmx is zero (matrix is already diagonal). 54 | if sigmx == 0 { 55 | impl.Dlasrt(lapack.SortDecreasing, n, d) 56 | return info 57 | } 58 | 59 | for i := 0; i < n; i++ { 60 | sigmx = math.Max(sigmx, d[i]) 61 | } 62 | 63 | // Copy D and E into WORK (in the Z format) and scale (squaring the 64 | // input data makes scaling by a power of the radix pointless). 65 | 66 | eps := dlamchP 67 | safmin := dlamchS 68 | scale := math.Sqrt(eps / safmin) 69 | bi := blas64.Implementation() 70 | bi.Dcopy(n, d, 1, work, 2) 71 | bi.Dcopy(n-1, e, 1, work[1:], 2) 72 | impl.Dlascl(lapack.General, 0, 0, sigmx, scale, 2*n-1, 1, work, 1) 73 | 74 | // Compute the q's and e's. 75 | for i := 0; i < 2*n-1; i++ { 76 | work[i] *= work[i] 77 | } 78 | work[2*n-1] = 0 79 | 80 | info = impl.Dlasq2(n, work) 81 | if info == 0 { 82 | for i := 0; i < n; i++ { 83 | d[i] = math.Sqrt(work[i]) 84 | } 85 | impl.Dlascl(lapack.General, 0, 0, scale, sigmx, n, 1, d, 1) 86 | } else if info == 2 { 87 | // Maximum number of iterations exceeded. Move data from work 88 | // into D and E so the calling subroutine can try to finish. 89 | for i := 0; i < n; i++ { 90 | d[i] = math.Sqrt(work[2*i]) 91 | e[i] = math.Sqrt(work[2*i+1]) 92 | } 93 | impl.Dlascl(lapack.General, 0, 0, scale, sigmx, n, 1, d, 1) 94 | impl.Dlascl(lapack.General, 0, 0, scale, sigmx, n, 1, e, 1) 95 | } 96 | return info 97 | } 98 | -------------------------------------------------------------------------------- /native/dlasrt.go: -------------------------------------------------------------------------------- 1 | // Copyright ©2015 The gonum Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package native 6 | 7 | import ( 8 | "sort" 9 | 10 | "github.com/gonum/lapack" 11 | ) 12 | 13 | // Dlasrt sorts the numbers in the input slice d. If s == lapack.SortIncreasing, 14 | // the elements are sorted in increasing order. If s == lapack.SortDecreasing, 15 | // the elements are sorted in decreasing order. For other values of s Dlasrt 16 | // will panic. 17 | // 18 | // Dlasrt is an internal routine. It is exported for testing purposes. 19 | func (impl Implementation) Dlasrt(s lapack.Sort, n int, d []float64) { 20 | checkVector(n, d, 1) 21 | d = d[:n] 22 | switch s { 23 | default: 24 | panic(badSort) 25 | case lapack.SortIncreasing: 26 | sort.Float64s(d) 27 | case lapack.SortDecreasing: 28 | sort.Sort(sort.Reverse(sort.Float64Slice(d))) 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /native/dlassq.go: -------------------------------------------------------------------------------- 1 | // Copyright ©2015 The gonum Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package native 6 | 7 | import "math" 8 | 9 | // Dlassq updates a sum of squares in scaled form. The input parameters scale and 10 | // sumsq represent the current scale and total sum of squares. These values are 11 | // updated with the information in the first n elements of the vector specified 12 | // by x and incX. 13 | // 14 | // Dlassq is an internal routine. It is exported for testing purposes. 15 | func (impl Implementation) Dlassq(n int, x []float64, incx int, scale float64, sumsq float64) (scl, smsq float64) { 16 | if n <= 0 { 17 | return scale, sumsq 18 | } 19 | for ix := 0; ix <= (n-1)*incx; ix += incx { 20 | absxi := math.Abs(x[ix]) 21 | if absxi > 0 || math.IsNaN(absxi) { 22 | if scale < absxi { 23 | sumsq = 1 + sumsq*(scale/absxi)*(scale/absxi) 24 | scale = absxi 25 | } else { 26 | sumsq += (absxi / scale) * (absxi / scale) 27 | } 28 | } 29 | } 30 | return scale, sumsq 31 | } 32 | -------------------------------------------------------------------------------- /native/dlaswp.go: -------------------------------------------------------------------------------- 1 | // Copyright ©2015 The gonum Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package native 6 | 7 | import "github.com/gonum/blas/blas64" 8 | 9 | // Dlaswp swaps the rows k1 to k2 of a rectangular matrix A according to the 10 | // indices in ipiv so that row k is swapped with ipiv[k]. 11 | // 12 | // n is the number of columns of A and incX is the increment for ipiv. If incX 13 | // is 1, the swaps are applied from k1 to k2. If incX is -1, the swaps are 14 | // applied in reverse order from k2 to k1. For other values of incX Dlaswp will 15 | // panic. ipiv must have length k2+1, otherwise Dlaswp will panic. 16 | // 17 | // The indices k1, k2, and the elements of ipiv are zero-based. 18 | // 19 | // Dlaswp is an internal routine. It is exported for testing purposes. 20 | func (impl Implementation) Dlaswp(n int, a []float64, lda int, k1, k2 int, ipiv []int, incX int) { 21 | switch { 22 | case n < 0: 23 | panic(nLT0) 24 | case k2 < 0: 25 | panic(badK2) 26 | case k1 < 0 || k2 < k1: 27 | panic(badK1) 28 | case len(ipiv) != k2+1: 29 | panic(badIpiv) 30 | case incX != 1 && incX != -1: 31 | panic(absIncNotOne) 32 | } 33 | 34 | if n == 0 { 35 | return 36 | } 37 | bi := blas64.Implementation() 38 | if incX == 1 { 39 | for k := k1; k <= k2; k++ { 40 | bi.Dswap(n, a[k*lda:], 1, a[ipiv[k]*lda:], 1) 41 | } 42 | return 43 | } 44 | for k := k2; k >= k1; k-- { 45 | bi.Dswap(n, a[k*lda:], 1, a[ipiv[k]*lda:], 1) 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /native/doc.go: -------------------------------------------------------------------------------- 1 | // Copyright ©2015 The gonum Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // This repository is no longer maintained. 6 | // Development has moved to https://github.com/gonum/gonum. 7 | // 8 | // Package native is a pure-go implementation of the LAPACK API. The LAPACK API defines 9 | // a set of algorithms for advanced matrix operations. 10 | // 11 | // The function definitions and implementations follow that of the netlib reference 12 | // implementation. Please see http://www.netlib.org/lapack/explore-html/ for more 13 | // information, and http://www.netlib.org/lapack/explore-html/d4/de1/_l_i_c_e_n_s_e_source.html 14 | // for more license information. 15 | // 16 | // Slice function arguments frequently represent vectors and matrices. The data 17 | // layout is identical to that found in https://godoc.org/github.com/gonum/blas/native. 18 | // 19 | // Most LAPACK functions are built on top the routines defined in the BLAS API, 20 | // and as such the computation time for many LAPACK functions is 21 | // dominated by BLAS calls. Here, BLAS is accessed through the 22 | // the blas64 package (https://godoc.org/github.com/gonum/blas/blas64). In particular, 23 | // this implies that an external BLAS library will be used if it is 24 | // registered in blas64. 25 | // 26 | // The full LAPACK capability has not been implemented at present. The full 27 | // API is very large, containing approximately 200 functions for double precision 28 | // alone. Future additions will be focused on supporting the gonum matrix 29 | // package (https://godoc.org/github.com/gonum/matrix/mat64), though pull requests 30 | // with implementations and tests for LAPACK function are encouraged. 31 | package native 32 | -------------------------------------------------------------------------------- /native/dorg2l.go: -------------------------------------------------------------------------------- 1 | // Copyright ©2016 The gonum Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package native 6 | 7 | import ( 8 | "github.com/gonum/blas" 9 | "github.com/gonum/blas/blas64" 10 | ) 11 | 12 | // Dorg2l generates an m×n matrix Q with orthonormal columns which is defined 13 | // as the last n columns of a product of k elementary reflectors of order m. 14 | // Q = H_{k-1} * ... * H_1 * H_0 15 | // See Dgelqf for more information. It must be that m >= n >= k. 16 | // 17 | // tau contains the scalar reflectors computed by Dgeqlf. tau must have length 18 | // at least k, and Dorg2l will panic otherwise. 19 | // 20 | // work contains temporary memory, and must have length at least n. Dorg2l will 21 | // panic otherwise. 22 | // 23 | // Dorg2l is an internal routine. It is exported for testing purposes. 24 | func (impl Implementation) Dorg2l(m, n, k int, a []float64, lda int, tau, work []float64) { 25 | checkMatrix(m, n, a, lda) 26 | if len(tau) < k { 27 | panic(badTau) 28 | } 29 | if len(work) < n { 30 | panic(badWork) 31 | } 32 | if m < n { 33 | panic(mLTN) 34 | } 35 | if k > n { 36 | panic(kGTN) 37 | } 38 | if n == 0 { 39 | return 40 | } 41 | 42 | // Initialize columns 0:n-k to columns of the unit matrix. 43 | for j := 0; j < n-k; j++ { 44 | for l := 0; l < m; l++ { 45 | a[l*lda+j] = 0 46 | } 47 | a[(m-n+j)*lda+j] = 1 48 | } 49 | 50 | bi := blas64.Implementation() 51 | for i := 0; i < k; i++ { 52 | ii := n - k + i 53 | 54 | // Apply H_i to A[0:m-k+i, 0:n-k+i] from the left. 55 | a[(m-n+ii)*lda+ii] = 1 56 | impl.Dlarf(blas.Left, m-n+ii+1, ii, a[ii:], lda, tau[i], a, lda, work) 57 | bi.Dscal(m-n+ii, -tau[i], a[ii:], lda) 58 | a[(m-n+ii)*lda+ii] = 1 - tau[i] 59 | 60 | // Set A[m-k+i:m, n-k+i+1] to zero. 61 | for l := m - n + ii + 1; l < m; l++ { 62 | a[l*lda+ii] = 0 63 | } 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /native/dorg2r.go: -------------------------------------------------------------------------------- 1 | // Copyright ©2015 The gonum Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package native 6 | 7 | import ( 8 | "github.com/gonum/blas" 9 | "github.com/gonum/blas/blas64" 10 | ) 11 | 12 | // Dorg2r generates an m×n matrix Q with orthonormal columns defined by the 13 | // product of elementary reflectors as computed by Dgeqrf. 14 | // Q = H_0 * H_1 * ... * H_{k-1} 15 | // len(tau) >= k, 0 <= k <= n, 0 <= n <= m, len(work) >= n. 16 | // Dorg2r will panic if these conditions are not met. 17 | // 18 | // Dorg2r is an internal routine. It is exported for testing purposes. 19 | func (impl Implementation) Dorg2r(m, n, k int, a []float64, lda int, tau []float64, work []float64) { 20 | checkMatrix(m, n, a, lda) 21 | if len(tau) < k { 22 | panic(badTau) 23 | } 24 | if len(work) < n { 25 | panic(badWork) 26 | } 27 | if k > n { 28 | panic(kGTN) 29 | } 30 | if n > m { 31 | panic(mLTN) 32 | } 33 | if len(work) < n { 34 | panic(badWork) 35 | } 36 | if n == 0 { 37 | return 38 | } 39 | bi := blas64.Implementation() 40 | // Initialize columns k+1:n to columns of the unit matrix. 41 | for l := 0; l < m; l++ { 42 | for j := k; j < n; j++ { 43 | a[l*lda+j] = 0 44 | } 45 | } 46 | for j := k; j < n; j++ { 47 | a[j*lda+j] = 1 48 | } 49 | for i := k - 1; i >= 0; i-- { 50 | for i := range work { 51 | work[i] = 0 52 | } 53 | if i < n-1 { 54 | a[i*lda+i] = 1 55 | impl.Dlarf(blas.Left, m-i, n-i-1, a[i*lda+i:], lda, tau[i], a[i*lda+i+1:], lda, work) 56 | } 57 | if i < m-1 { 58 | bi.Dscal(m-i-1, -tau[i], a[(i+1)*lda+i:], lda) 59 | } 60 | a[i*lda+i] = 1 - tau[i] 61 | for l := 0; l < i; l++ { 62 | a[l*lda+i] = 0 63 | } 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /native/dorgl2.go: -------------------------------------------------------------------------------- 1 | // Copyright ©2015 The gonum Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package native 6 | 7 | import ( 8 | "github.com/gonum/blas" 9 | "github.com/gonum/blas/blas64" 10 | ) 11 | 12 | // Dorgl2 generates an m×n matrix Q with orthonormal rows defined by the 13 | // first m rows product of elementary reflectors as computed by Dgelqf. 14 | // Q = H_0 * H_1 * ... * H_{k-1} 15 | // len(tau) >= k, 0 <= k <= m, 0 <= m <= n, len(work) >= m. 16 | // Dorgl2 will panic if these conditions are not met. 17 | // 18 | // Dorgl2 is an internal routine. It is exported for testing purposes. 19 | func (impl Implementation) Dorgl2(m, n, k int, a []float64, lda int, tau, work []float64) { 20 | checkMatrix(m, n, a, lda) 21 | if len(tau) < k { 22 | panic(badTau) 23 | } 24 | if k > m { 25 | panic(kGTM) 26 | } 27 | if k > m { 28 | panic(kGTM) 29 | } 30 | if m > n { 31 | panic(nLTM) 32 | } 33 | if len(work) < m { 34 | panic(badWork) 35 | } 36 | if m == 0 { 37 | return 38 | } 39 | bi := blas64.Implementation() 40 | if k < m { 41 | for i := k; i < m; i++ { 42 | for j := 0; j < n; j++ { 43 | a[i*lda+j] = 0 44 | } 45 | } 46 | for j := k; j < m; j++ { 47 | a[j*lda+j] = 1 48 | } 49 | } 50 | for i := k - 1; i >= 0; i-- { 51 | if i < n-1 { 52 | if i < m-1 { 53 | a[i*lda+i] = 1 54 | impl.Dlarf(blas.Right, m-i-1, n-i, a[i*lda+i:], 1, tau[i], a[(i+1)*lda+i:], lda, work) 55 | } 56 | bi.Dscal(n-i-1, -tau[i], a[i*lda+i+1:], 1) 57 | } 58 | a[i*lda+i] = 1 - tau[i] 59 | for l := 0; l < i; l++ { 60 | a[i*lda+l] = 0 61 | } 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /native/dorm2r.go: -------------------------------------------------------------------------------- 1 | // Copyright ©2015 The gonum Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package native 6 | 7 | import "github.com/gonum/blas" 8 | 9 | // Dorm2r multiplies a general matrix C by an orthogonal matrix from a QR factorization 10 | // determined by Dgeqrf. 11 | // C = Q * C if side == blas.Left and trans == blas.NoTrans 12 | // C = Q^T * C if side == blas.Left and trans == blas.Trans 13 | // C = C * Q if side == blas.Right and trans == blas.NoTrans 14 | // C = C * Q^T if side == blas.Right and trans == blas.Trans 15 | // If side == blas.Left, a is a matrix of size m×k, and if side == blas.Right 16 | // a is of size n×k. 17 | // 18 | // tau contains the Householder factors and is of length at least k and this function 19 | // will panic otherwise. 20 | // 21 | // work is temporary storage of length at least n if side == blas.Left 22 | // and at least m if side == blas.Right and this function will panic otherwise. 23 | // 24 | // Dorm2r is an internal routine. It is exported for testing purposes. 25 | func (impl Implementation) Dorm2r(side blas.Side, trans blas.Transpose, m, n, k int, a []float64, lda int, tau, c []float64, ldc int, work []float64) { 26 | if side != blas.Left && side != blas.Right { 27 | panic(badSide) 28 | } 29 | if trans != blas.Trans && trans != blas.NoTrans { 30 | panic(badTrans) 31 | } 32 | 33 | left := side == blas.Left 34 | notran := trans == blas.NoTrans 35 | if left { 36 | // Q is m x m 37 | checkMatrix(m, k, a, lda) 38 | if len(work) < n { 39 | panic(badWork) 40 | } 41 | } else { 42 | // Q is n x n 43 | checkMatrix(n, k, a, lda) 44 | if len(work) < m { 45 | panic(badWork) 46 | } 47 | } 48 | checkMatrix(m, n, c, ldc) 49 | if m == 0 || n == 0 || k == 0 { 50 | return 51 | } 52 | if len(tau) < k { 53 | panic(badTau) 54 | } 55 | if left { 56 | if notran { 57 | for i := k - 1; i >= 0; i-- { 58 | aii := a[i*lda+i] 59 | a[i*lda+i] = 1 60 | impl.Dlarf(side, m-i, n, a[i*lda+i:], lda, tau[i], c[i*ldc:], ldc, work) 61 | a[i*lda+i] = aii 62 | } 63 | return 64 | } 65 | for i := 0; i < k; i++ { 66 | aii := a[i*lda+i] 67 | a[i*lda+i] = 1 68 | impl.Dlarf(side, m-i, n, a[i*lda+i:], lda, tau[i], c[i*ldc:], ldc, work) 69 | a[i*lda+i] = aii 70 | } 71 | return 72 | } 73 | if notran { 74 | for i := 0; i < k; i++ { 75 | aii := a[i*lda+i] 76 | a[i*lda+i] = 1 77 | impl.Dlarf(side, m, n-i, a[i*lda+i:], lda, tau[i], c[i:], ldc, work) 78 | a[i*lda+i] = aii 79 | } 80 | return 81 | } 82 | for i := k - 1; i >= 0; i-- { 83 | aii := a[i*lda+i] 84 | a[i*lda+i] = 1 85 | impl.Dlarf(side, m, n-i, a[i*lda+i:], lda, tau[i], c[i:], ldc, work) 86 | a[i*lda+i] = aii 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /native/dorml2.go: -------------------------------------------------------------------------------- 1 | // Copyright ©2015 The gonum Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package native 6 | 7 | import "github.com/gonum/blas" 8 | 9 | // Dorml2 multiplies a general matrix C by an orthogonal matrix from an LQ factorization 10 | // determined by Dgelqf. 11 | // C = Q * C if side == blas.Left and trans == blas.NoTrans 12 | // C = Q^T * C if side == blas.Left and trans == blas.Trans 13 | // C = C * Q if side == blas.Right and trans == blas.NoTrans 14 | // C = C * Q^T if side == blas.Right and trans == blas.Trans 15 | // If side == blas.Left, a is a matrix of side k×m, and if side == blas.Right 16 | // a is of size k×n. 17 | // 18 | // tau contains the Householder factors and is of length at least k and this function will 19 | // panic otherwise. 20 | // 21 | // work is temporary storage of length at least n if side == blas.Left 22 | // and at least m if side == blas.Right and this function will panic otherwise. 23 | // 24 | // Dorml2 is an internal routine. It is exported for testing purposes. 25 | func (impl Implementation) Dorml2(side blas.Side, trans blas.Transpose, m, n, k int, a []float64, lda int, tau, c []float64, ldc int, work []float64) { 26 | if side != blas.Left && side != blas.Right { 27 | panic(badSide) 28 | } 29 | if trans != blas.Trans && trans != blas.NoTrans { 30 | panic(badTrans) 31 | } 32 | 33 | left := side == blas.Left 34 | notran := trans == blas.NoTrans 35 | if left { 36 | checkMatrix(k, m, a, lda) 37 | if len(work) < n { 38 | panic(badWork) 39 | } 40 | } else { 41 | checkMatrix(k, n, a, lda) 42 | if len(work) < m { 43 | panic(badWork) 44 | } 45 | } 46 | checkMatrix(m, n, c, ldc) 47 | if m == 0 || n == 0 || k == 0 { 48 | return 49 | } 50 | switch { 51 | case left && notran: 52 | for i := 0; i < k; i++ { 53 | aii := a[i*lda+i] 54 | a[i*lda+i] = 1 55 | impl.Dlarf(side, m-i, n, a[i*lda+i:], 1, tau[i], c[i*ldc:], ldc, work) 56 | a[i*lda+i] = aii 57 | } 58 | 59 | case left && !notran: 60 | for i := k - 1; i >= 0; i-- { 61 | aii := a[i*lda+i] 62 | a[i*lda+i] = 1 63 | impl.Dlarf(side, m-i, n, a[i*lda+i:], 1, tau[i], c[i*ldc:], ldc, work) 64 | a[i*lda+i] = aii 65 | } 66 | 67 | case !left && notran: 68 | for i := k - 1; i >= 0; i-- { 69 | aii := a[i*lda+i] 70 | a[i*lda+i] = 1 71 | impl.Dlarf(side, m, n-i, a[i*lda+i:], 1, tau[i], c[i:], ldc, work) 72 | a[i*lda+i] = aii 73 | } 74 | 75 | case !left && !notran: 76 | for i := 0; i < k; i++ { 77 | aii := a[i*lda+i] 78 | a[i*lda+i] = 1 79 | impl.Dlarf(side, m, n-i, a[i*lda+i:], 1, tau[i], c[i:], ldc, work) 80 | a[i*lda+i] = aii 81 | } 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /native/dormr2.go: -------------------------------------------------------------------------------- 1 | // Copyright ©2015 The gonum Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package native 6 | 7 | import "github.com/gonum/blas" 8 | 9 | // Dormr2 multiplies a general matrix C by an orthogonal matrix from a RQ factorization 10 | // determined by Dgerqf. 11 | // C = Q * C if side == blas.Left and trans == blas.NoTrans 12 | // C = Q^T * C if side == blas.Left and trans == blas.Trans 13 | // C = C * Q if side == blas.Right and trans == blas.NoTrans 14 | // C = C * Q^T if side == blas.Right and trans == blas.Trans 15 | // If side == blas.Left, a is a matrix of size k×m, and if side == blas.Right 16 | // a is of size k×n. 17 | // 18 | // tau contains the Householder factors and is of length at least k and this function 19 | // will panic otherwise. 20 | // 21 | // work is temporary storage of length at least n if side == blas.Left 22 | // and at least m if side == blas.Right and this function will panic otherwise. 23 | // 24 | // Dormr2 is an internal routine. It is exported for testing purposes. 25 | func (impl Implementation) Dormr2(side blas.Side, trans blas.Transpose, m, n, k int, a []float64, lda int, tau, c []float64, ldc int, work []float64) { 26 | if side != blas.Left && side != blas.Right { 27 | panic(badSide) 28 | } 29 | if trans != blas.Trans && trans != blas.NoTrans { 30 | panic(badTrans) 31 | } 32 | 33 | left := side == blas.Left 34 | notran := trans == blas.NoTrans 35 | if left { 36 | if k > m { 37 | panic(kGTM) 38 | } 39 | checkMatrix(k, m, a, lda) 40 | if len(work) < n { 41 | panic(badWork) 42 | } 43 | } else { 44 | if k > n { 45 | panic(kGTN) 46 | } 47 | checkMatrix(k, n, a, lda) 48 | if len(work) < m { 49 | panic(badWork) 50 | } 51 | } 52 | if len(tau) < k { 53 | panic(badTau) 54 | } 55 | checkMatrix(m, n, c, ldc) 56 | 57 | if m == 0 || n == 0 || k == 0 { 58 | return 59 | } 60 | if left { 61 | if notran { 62 | for i := k - 1; i >= 0; i-- { 63 | aii := a[i*lda+(m-k+i)] 64 | a[i*lda+(m-k+i)] = 1 65 | impl.Dlarf(side, m-k+i+1, n, a[i*lda:], 1, tau[i], c, ldc, work) 66 | a[i*lda+(m-k+i)] = aii 67 | } 68 | return 69 | } 70 | for i := 0; i < k; i++ { 71 | aii := a[i*lda+(m-k+i)] 72 | a[i*lda+(m-k+i)] = 1 73 | impl.Dlarf(side, m-k+i+1, n, a[i*lda:], 1, tau[i], c, ldc, work) 74 | a[i*lda+(m-k+i)] = aii 75 | } 76 | return 77 | } 78 | if notran { 79 | for i := 0; i < k; i++ { 80 | aii := a[i*lda+(n-k+i)] 81 | a[i*lda+(n-k+i)] = 1 82 | impl.Dlarf(side, m, n-k+i+1, a[i*lda:], 1, tau[i], c, ldc, work) 83 | a[i*lda+(n-k+i)] = aii 84 | } 85 | return 86 | } 87 | for i := k - 1; i >= 0; i-- { 88 | aii := a[i*lda+(n-k+i)] 89 | a[i*lda+(n-k+i)] = 1 90 | impl.Dlarf(side, m, n-k+i+1, a[i*lda:], 1, tau[i], c, ldc, work) 91 | a[i*lda+(n-k+i)] = aii 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /native/dpocon.go: -------------------------------------------------------------------------------- 1 | // Copyright ©2015 The gonum Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package native 6 | 7 | import ( 8 | "math" 9 | 10 | "github.com/gonum/blas" 11 | "github.com/gonum/blas/blas64" 12 | ) 13 | 14 | // Dpocon estimates the reciprocal of the condition number of a positive-definite 15 | // matrix A given the Cholesky decomposition of A. The condition number computed 16 | // is based on the 1-norm and the ∞-norm. 17 | // 18 | // anorm is the 1-norm and the ∞-norm of the original matrix A. 19 | // 20 | // work is a temporary data slice of length at least 3*n and Dpocon will panic otherwise. 21 | // 22 | // iwork is a temporary data slice of length at least n and Dpocon will panic otherwise. 23 | func (impl Implementation) Dpocon(uplo blas.Uplo, n int, a []float64, lda int, anorm float64, work []float64, iwork []int) float64 { 24 | checkMatrix(n, n, a, lda) 25 | if uplo != blas.Upper && uplo != blas.Lower { 26 | panic(badUplo) 27 | } 28 | if len(work) < 3*n { 29 | panic(badWork) 30 | } 31 | if len(iwork) < n { 32 | panic(badWork) 33 | } 34 | var rcond float64 35 | if n == 0 { 36 | return 1 37 | } 38 | if anorm == 0 { 39 | return rcond 40 | } 41 | 42 | bi := blas64.Implementation() 43 | var ainvnm float64 44 | smlnum := dlamchS 45 | upper := uplo == blas.Upper 46 | var kase int 47 | var normin bool 48 | isave := new([3]int) 49 | var sl, su float64 50 | for { 51 | ainvnm, kase = impl.Dlacn2(n, work[n:], work, iwork, ainvnm, kase, isave) 52 | if kase == 0 { 53 | if ainvnm != 0 { 54 | rcond = (1 / ainvnm) / anorm 55 | } 56 | return rcond 57 | } 58 | if upper { 59 | sl = impl.Dlatrs(blas.Upper, blas.Trans, blas.NonUnit, normin, n, a, lda, work, work[2*n:]) 60 | normin = true 61 | su = impl.Dlatrs(blas.Upper, blas.NoTrans, blas.NonUnit, normin, n, a, lda, work, work[2*n:]) 62 | } else { 63 | sl = impl.Dlatrs(blas.Lower, blas.NoTrans, blas.NonUnit, normin, n, a, lda, work, work[2*n:]) 64 | normin = true 65 | su = impl.Dlatrs(blas.Lower, blas.Trans, blas.NonUnit, normin, n, a, lda, work, work[2*n:]) 66 | } 67 | scale := sl * su 68 | if scale != 1 { 69 | ix := bi.Idamax(n, work, 1) 70 | if scale == 0 || scale < math.Abs(work[ix])*smlnum { 71 | return rcond 72 | } 73 | impl.Drscl(n, scale, work, 1) 74 | } 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /native/dpotf2.go: -------------------------------------------------------------------------------- 1 | // Copyright ©2015 The gonum Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package native 6 | 7 | import ( 8 | "math" 9 | 10 | "github.com/gonum/blas" 11 | "github.com/gonum/blas/blas64" 12 | ) 13 | 14 | // Dpotf2 computes the Cholesky decomposition of the symmetric positive definite 15 | // matrix a. If ul == blas.Upper, then a is stored as an upper-triangular matrix, 16 | // and a = U^T U is stored in place into a. If ul == blas.Lower, then a = L L^T 17 | // is computed and stored in-place into a. If a is not positive definite, false 18 | // is returned. This is the unblocked version of the algorithm. 19 | // 20 | // Dpotf2 is an internal routine. It is exported for testing purposes. 21 | func (Implementation) Dpotf2(ul blas.Uplo, n int, a []float64, lda int) (ok bool) { 22 | if ul != blas.Upper && ul != blas.Lower { 23 | panic(badUplo) 24 | } 25 | checkMatrix(n, n, a, lda) 26 | 27 | if n == 0 { 28 | return true 29 | } 30 | 31 | bi := blas64.Implementation() 32 | if ul == blas.Upper { 33 | for j := 0; j < n; j++ { 34 | ajj := a[j*lda+j] 35 | if j != 0 { 36 | ajj -= bi.Ddot(j, a[j:], lda, a[j:], lda) 37 | } 38 | if ajj <= 0 || math.IsNaN(ajj) { 39 | a[j*lda+j] = ajj 40 | return false 41 | } 42 | ajj = math.Sqrt(ajj) 43 | a[j*lda+j] = ajj 44 | if j < n-1 { 45 | bi.Dgemv(blas.Trans, j, n-j-1, 46 | -1, a[j+1:], lda, a[j:], lda, 47 | 1, a[j*lda+j+1:], 1) 48 | bi.Dscal(n-j-1, 1/ajj, a[j*lda+j+1:], 1) 49 | } 50 | } 51 | return true 52 | } 53 | for j := 0; j < n; j++ { 54 | ajj := a[j*lda+j] 55 | if j != 0 { 56 | ajj -= bi.Ddot(j, a[j*lda:], 1, a[j*lda:], 1) 57 | } 58 | if ajj <= 0 || math.IsNaN(ajj) { 59 | a[j*lda+j] = ajj 60 | return false 61 | } 62 | ajj = math.Sqrt(ajj) 63 | a[j*lda+j] = ajj 64 | if j < n-1 { 65 | bi.Dgemv(blas.NoTrans, n-j-1, j, 66 | -1, a[(j+1)*lda:], lda, a[j*lda:], 1, 67 | 1, a[(j+1)*lda+j:], lda) 68 | bi.Dscal(n-j-1, 1/ajj, a[(j+1)*lda+j:], lda) 69 | } 70 | } 71 | return true 72 | } 73 | -------------------------------------------------------------------------------- /native/dpotrf.go: -------------------------------------------------------------------------------- 1 | // Copyright ©2015 The gonum Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package native 6 | 7 | import ( 8 | "github.com/gonum/blas" 9 | "github.com/gonum/blas/blas64" 10 | ) 11 | 12 | // Dpotrf computes the Cholesky decomposition of the symmetric positive definite 13 | // matrix a. If ul == blas.Upper, then a is stored as an upper-triangular matrix, 14 | // and a = U^T U is stored in place into a. If ul == blas.Lower, then a = L L^T 15 | // is computed and stored in-place into a. If a is not positive definite, false 16 | // is returned. This is the blocked version of the algorithm. 17 | func (impl Implementation) Dpotrf(ul blas.Uplo, n int, a []float64, lda int) (ok bool) { 18 | if ul != blas.Upper && ul != blas.Lower { 19 | panic(badUplo) 20 | } 21 | checkMatrix(n, n, a, lda) 22 | 23 | if n == 0 { 24 | return true 25 | } 26 | 27 | nb := impl.Ilaenv(1, "DPOTRF", string(ul), n, -1, -1, -1) 28 | if nb <= 1 || n <= nb { 29 | return impl.Dpotf2(ul, n, a, lda) 30 | } 31 | bi := blas64.Implementation() 32 | if ul == blas.Upper { 33 | for j := 0; j < n; j += nb { 34 | jb := min(nb, n-j) 35 | bi.Dsyrk(blas.Upper, blas.Trans, jb, j, 36 | -1, a[j:], lda, 37 | 1, a[j*lda+j:], lda) 38 | ok = impl.Dpotf2(blas.Upper, jb, a[j*lda+j:], lda) 39 | if !ok { 40 | return ok 41 | } 42 | if j+jb < n { 43 | bi.Dgemm(blas.Trans, blas.NoTrans, jb, n-j-jb, j, 44 | -1, a[j:], lda, a[j+jb:], lda, 45 | 1, a[j*lda+j+jb:], lda) 46 | bi.Dtrsm(blas.Left, blas.Upper, blas.Trans, blas.NonUnit, jb, n-j-jb, 47 | 1, a[j*lda+j:], lda, 48 | a[j*lda+j+jb:], lda) 49 | } 50 | } 51 | return true 52 | } 53 | for j := 0; j < n; j += nb { 54 | jb := min(nb, n-j) 55 | bi.Dsyrk(blas.Lower, blas.NoTrans, jb, j, 56 | -1, a[j*lda:], lda, 57 | 1, a[j*lda+j:], lda) 58 | ok := impl.Dpotf2(blas.Lower, jb, a[j*lda+j:], lda) 59 | if !ok { 60 | return ok 61 | } 62 | if j+jb < n { 63 | bi.Dgemm(blas.NoTrans, blas.Trans, n-j-jb, jb, j, 64 | -1, a[(j+jb)*lda:], lda, a[j*lda:], lda, 65 | 1, a[(j+jb)*lda+j:], lda) 66 | bi.Dtrsm(blas.Right, blas.Lower, blas.Trans, blas.NonUnit, n-j-jb, jb, 67 | 1, a[j*lda+j:], lda, 68 | a[(j+jb)*lda+j:], lda) 69 | } 70 | } 71 | return true 72 | } 73 | -------------------------------------------------------------------------------- /native/drscl.go: -------------------------------------------------------------------------------- 1 | // Copyright ©2015 The gonum Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package native 6 | 7 | import ( 8 | "math" 9 | 10 | "github.com/gonum/blas/blas64" 11 | ) 12 | 13 | // Drscl multiplies the vector x by 1/a being careful to avoid overflow or 14 | // underflow where possible. 15 | // 16 | // Drscl is an internal routine. It is exported for testing purposes. 17 | func (impl Implementation) Drscl(n int, a float64, x []float64, incX int) { 18 | checkVector(n, x, incX) 19 | bi := blas64.Implementation() 20 | cden := a 21 | cnum := 1.0 22 | smlnum := dlamchS 23 | bignum := 1 / smlnum 24 | for { 25 | cden1 := cden * smlnum 26 | cnum1 := cnum / bignum 27 | var mul float64 28 | var done bool 29 | switch { 30 | case cnum != 0 && math.Abs(cden1) > math.Abs(cnum): 31 | mul = smlnum 32 | done = false 33 | cden = cden1 34 | case math.Abs(cnum1) > math.Abs(cden): 35 | mul = bignum 36 | done = false 37 | cnum = cnum1 38 | default: 39 | mul = cnum / cden 40 | done = true 41 | } 42 | bi.Dscal(n, mul, x, incX) 43 | if done { 44 | break 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /native/dtrcon.go: -------------------------------------------------------------------------------- 1 | // Copyright ©2015 The gonum Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package native 6 | 7 | import ( 8 | "math" 9 | 10 | "github.com/gonum/blas" 11 | "github.com/gonum/blas/blas64" 12 | "github.com/gonum/lapack" 13 | ) 14 | 15 | // Dtrcon estimates the reciprocal of the condition number of a triangular matrix A. 16 | // The condition number computed may be based on the 1-norm or the ∞-norm. 17 | // 18 | // work is a temporary data slice of length at least 3*n and Dtrcon will panic otherwise. 19 | // 20 | // iwork is a temporary data slice of length at least n and Dtrcon will panic otherwise. 21 | func (impl Implementation) Dtrcon(norm lapack.MatrixNorm, uplo blas.Uplo, diag blas.Diag, n int, a []float64, lda int, work []float64, iwork []int) float64 { 22 | if norm != lapack.MaxColumnSum && norm != lapack.MaxRowSum { 23 | panic(badNorm) 24 | } 25 | if uplo != blas.Upper && uplo != blas.Lower { 26 | panic(badUplo) 27 | } 28 | if diag != blas.NonUnit && diag != blas.Unit { 29 | panic(badDiag) 30 | } 31 | if len(work) < 3*n { 32 | panic(badWork) 33 | } 34 | if len(iwork) < n { 35 | panic(badWork) 36 | } 37 | if n == 0 { 38 | return 1 39 | } 40 | bi := blas64.Implementation() 41 | 42 | var rcond float64 43 | smlnum := dlamchS * float64(n) 44 | 45 | anorm := impl.Dlantr(norm, uplo, diag, n, n, a, lda, work) 46 | 47 | if anorm <= 0 { 48 | return rcond 49 | } 50 | var ainvnm float64 51 | var normin bool 52 | kase1 := 2 53 | if norm == lapack.MaxColumnSum { 54 | kase1 = 1 55 | } 56 | var kase int 57 | isave := new([3]int) 58 | var scale float64 59 | for { 60 | ainvnm, kase = impl.Dlacn2(n, work[n:], work, iwork, ainvnm, kase, isave) 61 | if kase == 0 { 62 | if ainvnm != 0 { 63 | rcond = (1 / anorm) / ainvnm 64 | } 65 | return rcond 66 | } 67 | if kase == kase1 { 68 | scale = impl.Dlatrs(uplo, blas.NoTrans, diag, normin, n, a, lda, work, work[2*n:]) 69 | } else { 70 | scale = impl.Dlatrs(uplo, blas.Trans, diag, normin, n, a, lda, work, work[2*n:]) 71 | } 72 | normin = true 73 | if scale != 1 { 74 | ix := bi.Idamax(n, work, 1) 75 | xnorm := math.Abs(work[ix]) 76 | if scale == 0 || scale < xnorm*smlnum { 77 | return rcond 78 | } 79 | impl.Drscl(n, scale, work, 1) 80 | } 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /native/dtrti2.go: -------------------------------------------------------------------------------- 1 | // Copyright ©2015 The gonum Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package native 6 | 7 | import ( 8 | "github.com/gonum/blas" 9 | "github.com/gonum/blas/blas64" 10 | ) 11 | 12 | // Dtrti2 computes the inverse of a triangular matrix, storing the result in place 13 | // into a. This is the BLAS level 2 version of the algorithm. 14 | // 15 | // Dtrti2 is an internal routine. It is exported for testing purposes. 16 | func (impl Implementation) Dtrti2(uplo blas.Uplo, diag blas.Diag, n int, a []float64, lda int) { 17 | checkMatrix(n, n, a, lda) 18 | if uplo != blas.Upper && uplo != blas.Lower { 19 | panic(badUplo) 20 | } 21 | if diag != blas.NonUnit && diag != blas.Unit { 22 | panic(badDiag) 23 | } 24 | bi := blas64.Implementation() 25 | 26 | nonUnit := diag == blas.NonUnit 27 | // TODO(btracey): Replace this with a row-major ordering. 28 | if uplo == blas.Upper { 29 | for j := 0; j < n; j++ { 30 | var ajj float64 31 | if nonUnit { 32 | ajj = 1 / a[j*lda+j] 33 | a[j*lda+j] = ajj 34 | ajj *= -1 35 | } else { 36 | ajj = -1 37 | } 38 | bi.Dtrmv(blas.Upper, blas.NoTrans, diag, j, a, lda, a[j:], lda) 39 | bi.Dscal(j, ajj, a[j:], lda) 40 | } 41 | return 42 | } 43 | for j := n - 1; j >= 0; j-- { 44 | var ajj float64 45 | if nonUnit { 46 | ajj = 1 / a[j*lda+j] 47 | a[j*lda+j] = ajj 48 | ajj *= -1 49 | } else { 50 | ajj = -1 51 | } 52 | if j < n-1 { 53 | bi.Dtrmv(blas.Lower, blas.NoTrans, diag, n-j-1, a[(j+1)*lda+j+1:], lda, a[(j+1)*lda+j:], lda) 54 | bi.Dscal(n-j-1, ajj, a[(j+1)*lda+j:], lda) 55 | } 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /native/dtrtri.go: -------------------------------------------------------------------------------- 1 | // Copyright ©2015 The gonum Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package native 6 | 7 | import ( 8 | "github.com/gonum/blas" 9 | "github.com/gonum/blas/blas64" 10 | ) 11 | 12 | // Dtrtri computes the inverse of a triangular matrix, storing the result in place 13 | // into a. This is the BLAS level 3 version of the algorithm which builds upon 14 | // Dtrti2 to operate on matrix blocks instead of only individual columns. 15 | // 16 | // Dtrtri will not perform the inversion if the matrix is singular, and returns 17 | // a boolean indicating whether the inversion was successful. 18 | func (impl Implementation) Dtrtri(uplo blas.Uplo, diag blas.Diag, n int, a []float64, lda int) (ok bool) { 19 | checkMatrix(n, n, a, lda) 20 | if uplo != blas.Upper && uplo != blas.Lower { 21 | panic(badUplo) 22 | } 23 | if diag != blas.NonUnit && diag != blas.Unit { 24 | panic(badDiag) 25 | } 26 | if n == 0 { 27 | return false 28 | } 29 | nonUnit := diag == blas.NonUnit 30 | if nonUnit { 31 | for i := 0; i < n; i++ { 32 | if a[i*lda+i] == 0 { 33 | return false 34 | } 35 | } 36 | } 37 | 38 | bi := blas64.Implementation() 39 | 40 | nb := impl.Ilaenv(1, "DTRTRI", "UD", n, -1, -1, -1) 41 | if nb <= 1 || nb > n { 42 | impl.Dtrti2(uplo, diag, n, a, lda) 43 | return true 44 | } 45 | if uplo == blas.Upper { 46 | for j := 0; j < n; j += nb { 47 | jb := min(nb, n-j) 48 | bi.Dtrmm(blas.Left, blas.Upper, blas.NoTrans, diag, j, jb, 1, a, lda, a[j:], lda) 49 | bi.Dtrsm(blas.Right, blas.Upper, blas.NoTrans, diag, j, jb, -1, a[j*lda+j:], lda, a[j:], lda) 50 | impl.Dtrti2(blas.Upper, diag, jb, a[j*lda+j:], lda) 51 | } 52 | return true 53 | } 54 | nn := ((n - 1) / nb) * nb 55 | for j := nn; j >= 0; j -= nb { 56 | jb := min(nb, n-j) 57 | if j+jb <= n-1 { 58 | bi.Dtrmm(blas.Left, blas.Lower, blas.NoTrans, diag, n-j-jb, jb, 1, a[(j+jb)*lda+j+jb:], lda, a[(j+jb)*lda+j:], lda) 59 | bi.Dtrsm(blas.Right, blas.Lower, blas.NoTrans, diag, n-j-jb, jb, -1, a[j*lda+j:], lda, a[(j+jb)*lda+j:], lda) 60 | } 61 | impl.Dtrti2(blas.Lower, diag, jb, a[j*lda+j:], lda) 62 | } 63 | return true 64 | } 65 | -------------------------------------------------------------------------------- /native/dtrtrs.go: -------------------------------------------------------------------------------- 1 | // Copyright ©2015 The gonum Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package native 6 | 7 | import ( 8 | "github.com/gonum/blas" 9 | "github.com/gonum/blas/blas64" 10 | ) 11 | 12 | // Dtrtrs solves a triangular system of the form A * X = B or A^T * X = B. Dtrtrs 13 | // returns whether the solve completed successfully. If A is singular, no solve is performed. 14 | func (impl Implementation) Dtrtrs(uplo blas.Uplo, trans blas.Transpose, diag blas.Diag, n, nrhs int, a []float64, lda int, b []float64, ldb int) (ok bool) { 15 | nounit := diag == blas.NonUnit 16 | if n == 0 { 17 | return false 18 | } 19 | // Check for singularity. 20 | if nounit { 21 | for i := 0; i < n; i++ { 22 | if a[i*lda+i] == 0 { 23 | return false 24 | } 25 | } 26 | } 27 | bi := blas64.Implementation() 28 | bi.Dtrsm(blas.Left, uplo, trans, diag, n, nrhs, 1, a, lda, b, ldb) 29 | return true 30 | } 31 | -------------------------------------------------------------------------------- /native/iladlc.go: -------------------------------------------------------------------------------- 1 | // Copyright ©2015 The gonum Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package native 6 | 7 | // Iladlc scans a matrix for its last non-zero column. Returns -1 if the matrix 8 | // is all zeros. 9 | // 10 | // Iladlc is an internal routine. It is exported for testing purposes. 11 | func (Implementation) Iladlc(m, n int, a []float64, lda int) int { 12 | if n == 0 || m == 0 { 13 | return n - 1 14 | } 15 | checkMatrix(m, n, a, lda) 16 | 17 | // Test common case where corner is non-zero. 18 | if a[n-1] != 0 || a[(m-1)*lda+(n-1)] != 0 { 19 | return n - 1 20 | } 21 | 22 | // Scan each row tracking the highest column seen. 23 | highest := -1 24 | for i := 0; i < m; i++ { 25 | for j := n - 1; j >= 0; j-- { 26 | if a[i*lda+j] != 0 { 27 | highest = max(highest, j) 28 | break 29 | } 30 | } 31 | } 32 | return highest 33 | } 34 | -------------------------------------------------------------------------------- /native/iladlr.go: -------------------------------------------------------------------------------- 1 | // Copyright ©2015 The gonum Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package native 6 | 7 | // Iladlr scans a matrix for its last non-zero row. Returns -1 if the matrix 8 | // is all zeros. 9 | // 10 | // Iladlr is an internal routine. It is exported for testing purposes. 11 | func (Implementation) Iladlr(m, n int, a []float64, lda int) int { 12 | if m == 0 { 13 | return m - 1 14 | } 15 | 16 | checkMatrix(m, n, a, lda) 17 | 18 | // Check the common case where the corner is non-zero 19 | if a[(m-1)*lda] != 0 || a[(m-1)*lda+n-1] != 0 { 20 | return m - 1 21 | } 22 | for i := m - 1; i >= 0; i-- { 23 | for j := 0; j < n; j++ { 24 | if a[i*lda+j] != 0 { 25 | return i 26 | } 27 | } 28 | } 29 | return -1 30 | } 31 | -------------------------------------------------------------------------------- /testlapack/dgebd2.go: -------------------------------------------------------------------------------- 1 | // Copyright ©2015 The gonum Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package testlapack 6 | 7 | import ( 8 | "math/rand" 9 | "testing" 10 | ) 11 | 12 | type Dgebd2er interface { 13 | Dgebd2(m, n int, a []float64, lda int, d, e, tauq, taup, work []float64) 14 | } 15 | 16 | func Dgebd2Test(t *testing.T, impl Dgebd2er) { 17 | rnd := rand.New(rand.NewSource(1)) 18 | for _, test := range []struct { 19 | m, n, lda int 20 | }{ 21 | {3, 4, 0}, 22 | {4, 3, 0}, 23 | {3, 4, 10}, 24 | {4, 3, 10}, 25 | } { 26 | m := test.m 27 | n := test.n 28 | lda := test.lda 29 | if lda == 0 { 30 | lda = n 31 | } 32 | nb := min(m, n) // 'nb' name parallel with Dlabrd code. 33 | a := make([]float64, m*lda) 34 | for i := range a { 35 | a[i] = rnd.NormFloat64() 36 | } 37 | d := nanSlice(nb) 38 | e := nanSlice(nb - 1) 39 | tauP := nanSlice(nb) 40 | tauQ := nanSlice(nb) 41 | work := nanSlice(max(m, n)) 42 | aCopy := make([]float64, len(a)) 43 | copy(aCopy, a) 44 | impl.Dgebd2(m, n, a, lda, d, e, tauQ, tauP, work) 45 | if m >= n && nb == n { 46 | tauP[n-1] = 0 47 | } 48 | if m < n && nb == m { 49 | tauQ[m-1] = 0 50 | } 51 | 52 | checkBidiagonal(t, m, n, nb, a, lda, d, e, tauP, tauQ, aCopy) 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /testlapack/dgecon.go: -------------------------------------------------------------------------------- 1 | // Copyright ©2015 The gonum Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package testlapack 6 | 7 | import ( 8 | "log" 9 | "testing" 10 | 11 | "github.com/gonum/floats" 12 | "github.com/gonum/lapack" 13 | ) 14 | 15 | type Dgeconer interface { 16 | Dlanger 17 | Dgetrfer 18 | Dgecon(norm lapack.MatrixNorm, n int, a []float64, lda int, anorm float64, work []float64, iwork []int) float64 19 | } 20 | 21 | func DgeconTest(t *testing.T, impl Dgeconer) { 22 | for _, test := range []struct { 23 | m int 24 | n int 25 | a []float64 26 | condOne float64 27 | condInf float64 28 | }{ 29 | { 30 | a: []float64{ 31 | 8, 1, 6, 32 | 3, 5, 7, 33 | 4, 9, 2, 34 | }, 35 | m: 3, 36 | n: 3, 37 | condOne: 3.0 / 16, 38 | condInf: 3.0 / 16, 39 | }, 40 | { 41 | a: []float64{ 42 | 2, 9, 3, 2, 43 | 10, 9, 9, 3, 44 | 1, 1, 5, 2, 45 | 8, 4, 10, 2, 46 | }, 47 | m: 4, 48 | n: 4, 49 | condOne: 0.024740155174938, 50 | condInf: 0.012034465570035, 51 | }, 52 | // Dgecon does not match Dpocon for this case. https://github.com/xianyi/OpenBLAS/issues/664. 53 | { 54 | a: []float64{ 55 | 2.9995576045549965, -2.0898894566158663, 3.965560740124006, 56 | -2.0898894566158663, 1.9634729526261008, -2.8681002706874104, 57 | 3.965560740124006, -2.8681002706874104, 5.502416670471008, 58 | }, 59 | m: 3, 60 | n: 3, 61 | condOne: 0.024054837369015203, 62 | condInf: 0.024054837369015203, 63 | }, 64 | } { 65 | m := test.m 66 | n := test.n 67 | lda := n 68 | a := make([]float64, len(test.a)) 69 | copy(a, test.a) 70 | ipiv := make([]int, min(m, n)) 71 | 72 | // Find the norms of the original matrix. 73 | work := make([]float64, 4*n) 74 | oneNorm := impl.Dlange(lapack.MaxColumnSum, m, n, a, lda, work) 75 | infNorm := impl.Dlange(lapack.MaxRowSum, m, n, a, lda, work) 76 | 77 | // Compute LU factorization of a. 78 | impl.Dgetrf(m, n, a, lda, ipiv) 79 | 80 | // Compute the condition number 81 | iwork := make([]int, n) 82 | condOne := impl.Dgecon(lapack.MaxColumnSum, n, a, lda, oneNorm, work, iwork) 83 | condInf := impl.Dgecon(lapack.MaxRowSum, n, a, lda, infNorm, work, iwork) 84 | 85 | // Error if not the same order, otherwise log the difference. 86 | if !floats.EqualWithinAbsOrRel(condOne, test.condOne, 1e0, 1e0) { 87 | t.Errorf("One norm mismatch. Want %v, got %v.", test.condOne, condOne) 88 | } else if !floats.EqualWithinAbsOrRel(condOne, test.condOne, 1e-14, 1e-14) { 89 | log.Printf("Dgecon one norm mismatch. Want %v, got %v.", test.condOne, condOne) 90 | } 91 | if !floats.EqualWithinAbsOrRel(condInf, test.condInf, 1e0, 1e0) { 92 | t.Errorf("One norm mismatch. Want %v, got %v.", test.condInf, condInf) 93 | } else if !floats.EqualWithinAbsOrRel(condInf, test.condInf, 1e-14, 1e-14) { 94 | log.Printf("Dgecon one norm mismatch. Want %v, got %v.", test.condInf, condInf) 95 | } 96 | } 97 | } 98 | -------------------------------------------------------------------------------- /testlapack/dgeev_bench.go: -------------------------------------------------------------------------------- 1 | // Copyright ©2016 The gonum Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // +build go1.7 6 | 7 | package testlapack 8 | 9 | import ( 10 | "math/rand" 11 | "testing" 12 | 13 | "github.com/gonum/blas/blas64" 14 | "github.com/gonum/lapack" 15 | ) 16 | 17 | var resultGeneral blas64.General 18 | 19 | func DgeevBenchmark(b *testing.B, impl Dgeever) { 20 | rnd := rand.New(rand.NewSource(1)) 21 | benchmarks := []struct { 22 | name string 23 | a blas64.General 24 | }{ 25 | {"AntisymRandom3", NewAntisymRandom(3, rnd).Matrix()}, 26 | {"AntisymRandom4", NewAntisymRandom(4, rnd).Matrix()}, 27 | {"AntisymRandom5", NewAntisymRandom(5, rnd).Matrix()}, 28 | {"AntisymRandom10", NewAntisymRandom(10, rnd).Matrix()}, 29 | {"AntisymRandom50", NewAntisymRandom(50, rnd).Matrix()}, 30 | {"AntisymRandom100", NewAntisymRandom(100, rnd).Matrix()}, 31 | {"AntisymRandom200", NewAntisymRandom(200, rnd).Matrix()}, 32 | {"AntisymRandom500", NewAntisymRandom(500, rnd).Matrix()}, 33 | {"Circulant3", Circulant(3).Matrix()}, 34 | {"Circulant4", Circulant(4).Matrix()}, 35 | {"Circulant5", Circulant(5).Matrix()}, 36 | {"Circulant10", Circulant(10).Matrix()}, 37 | {"Circulant50", Circulant(50).Matrix()}, 38 | {"Circulant100", Circulant(100).Matrix()}, 39 | {"Circulant200", Circulant(200).Matrix()}, 40 | {"Circulant500", Circulant(500).Matrix()}, 41 | } 42 | for _, bm := range benchmarks { 43 | n := bm.a.Rows 44 | a := zeros(n, n, n) 45 | vl := zeros(n, n, n) 46 | vr := zeros(n, n, n) 47 | wr := make([]float64, n) 48 | wi := make([]float64, n) 49 | work := make([]float64, 1) 50 | impl.Dgeev(lapack.ComputeLeftEV, lapack.ComputeRightEV, n, nil, n, nil, nil, nil, n, nil, n, work, -1) 51 | work = make([]float64, int(work[0])) 52 | b.Run(bm.name, func(b *testing.B) { 53 | for i := 0; i < b.N; i++ { 54 | b.StopTimer() 55 | copyGeneral(a, bm.a) 56 | b.StartTimer() 57 | impl.Dgeev(lapack.ComputeLeftEV, lapack.ComputeRightEV, n, a.Data, a.Stride, wr, wi, 58 | vl.Data, vl.Stride, vr.Data, vr.Stride, work, len(work)) 59 | } 60 | resultGeneral = a 61 | }) 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /testlapack/dgelq2.go: -------------------------------------------------------------------------------- 1 | // Copyright ©2015 The gonum Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package testlapack 6 | 7 | import ( 8 | "math" 9 | "math/rand" 10 | "testing" 11 | 12 | "github.com/gonum/blas" 13 | "github.com/gonum/blas/blas64" 14 | "github.com/gonum/floats" 15 | ) 16 | 17 | type Dgelq2er interface { 18 | Dgelq2(m, n int, a []float64, lda int, tau, work []float64) 19 | } 20 | 21 | func Dgelq2Test(t *testing.T, impl Dgelq2er) { 22 | rnd := rand.New(rand.NewSource(1)) 23 | for c, test := range []struct { 24 | m, n, lda int 25 | }{ 26 | {1, 1, 0}, 27 | {2, 2, 0}, 28 | {3, 2, 0}, 29 | {2, 3, 0}, 30 | {1, 12, 0}, 31 | {2, 6, 0}, 32 | {3, 4, 0}, 33 | {4, 3, 0}, 34 | {6, 2, 0}, 35 | {1, 12, 0}, 36 | {1, 1, 20}, 37 | {2, 2, 20}, 38 | {3, 2, 20}, 39 | {2, 3, 20}, 40 | {1, 12, 20}, 41 | {2, 6, 20}, 42 | {3, 4, 20}, 43 | {4, 3, 20}, 44 | {6, 2, 20}, 45 | {1, 12, 20}, 46 | } { 47 | n := test.n 48 | m := test.m 49 | lda := test.lda 50 | if lda == 0 { 51 | lda = test.n 52 | } 53 | k := min(m, n) 54 | tau := make([]float64, k) 55 | for i := range tau { 56 | tau[i] = rnd.Float64() 57 | } 58 | work := make([]float64, m) 59 | for i := range work { 60 | work[i] = rnd.Float64() 61 | } 62 | a := make([]float64, m*lda) 63 | for i := 0; i < m*lda; i++ { 64 | a[i] = rnd.Float64() 65 | } 66 | aCopy := make([]float64, len(a)) 67 | copy(aCopy, a) 68 | impl.Dgelq2(m, n, a, lda, tau, work) 69 | 70 | Q := constructQ("LQ", m, n, a, lda, tau) 71 | 72 | // Check that Q is orthonormal 73 | for i := 0; i < Q.Rows; i++ { 74 | nrm := blas64.Nrm2(Q.Cols, blas64.Vector{Inc: 1, Data: Q.Data[i*Q.Stride:]}) 75 | if math.Abs(nrm-1) > 1e-14 { 76 | t.Errorf("Q not normal. Norm is %v", nrm) 77 | } 78 | for j := 0; j < i; j++ { 79 | dot := blas64.Dot(Q.Rows, 80 | blas64.Vector{Inc: 1, Data: Q.Data[i*Q.Stride:]}, 81 | blas64.Vector{Inc: 1, Data: Q.Data[j*Q.Stride:]}, 82 | ) 83 | if math.Abs(dot) > 1e-14 { 84 | t.Errorf("Q not orthogonal. Dot is %v", dot) 85 | } 86 | } 87 | } 88 | 89 | L := blas64.General{ 90 | Rows: m, 91 | Cols: n, 92 | Stride: n, 93 | Data: make([]float64, m*n), 94 | } 95 | for i := 0; i < m; i++ { 96 | for j := 0; j <= min(i, n-1); j++ { 97 | L.Data[i*L.Stride+j] = a[i*lda+j] 98 | } 99 | } 100 | 101 | ans := blas64.General{ 102 | Rows: m, 103 | Cols: n, 104 | Stride: lda, 105 | Data: make([]float64, m*lda), 106 | } 107 | copy(ans.Data, aCopy) 108 | blas64.Gemm(blas.NoTrans, blas.NoTrans, 1, L, Q, 0, ans) 109 | if !floats.EqualApprox(aCopy, ans.Data, 1e-14) { 110 | t.Errorf("Case %v, LQ mismatch. Want %v, got %v.", c, aCopy, ans.Data) 111 | } 112 | } 113 | } 114 | -------------------------------------------------------------------------------- /testlapack/dgelqf.go: -------------------------------------------------------------------------------- 1 | // Copyright ©2015 The gonum Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package testlapack 6 | 7 | import ( 8 | "math/rand" 9 | "testing" 10 | 11 | "github.com/gonum/floats" 12 | ) 13 | 14 | type Dgelqfer interface { 15 | Dgelq2er 16 | Dgelqf(m, n int, a []float64, lda int, tau, work []float64, lwork int) 17 | } 18 | 19 | func DgelqfTest(t *testing.T, impl Dgelqfer) { 20 | rnd := rand.New(rand.NewSource(1)) 21 | for c, test := range []struct { 22 | m, n, lda int 23 | }{ 24 | {10, 5, 0}, 25 | {5, 10, 0}, 26 | {10, 10, 0}, 27 | {300, 5, 0}, 28 | {3, 500, 0}, 29 | {200, 200, 0}, 30 | {300, 200, 0}, 31 | {204, 300, 0}, 32 | {1, 3000, 0}, 33 | {3000, 1, 0}, 34 | {10, 5, 30}, 35 | {5, 10, 30}, 36 | {10, 10, 30}, 37 | {300, 5, 500}, 38 | {3, 500, 600}, 39 | {200, 200, 300}, 40 | {300, 200, 300}, 41 | {204, 300, 400}, 42 | {1, 3000, 4000}, 43 | {3000, 1, 4000}, 44 | } { 45 | m := test.m 46 | n := test.n 47 | lda := test.lda 48 | if lda == 0 { 49 | lda = n 50 | } 51 | a := make([]float64, m*lda) 52 | for i := 0; i < m; i++ { 53 | for j := 0; j < n; j++ { 54 | a[i*lda+j] = rnd.Float64() 55 | } 56 | } 57 | tau := make([]float64, n) 58 | for i := 0; i < n; i++ { 59 | tau[i] = rnd.Float64() 60 | } 61 | aCopy := make([]float64, len(a)) 62 | copy(aCopy, a) 63 | ans := make([]float64, len(a)) 64 | copy(ans, a) 65 | work := make([]float64, m) 66 | for i := range work { 67 | work[i] = rnd.Float64() 68 | } 69 | // Compute unblocked QR. 70 | impl.Dgelq2(m, n, ans, lda, tau, work) 71 | // Compute blocked QR with small work. 72 | impl.Dgelqf(m, n, a, lda, tau, work, len(work)) 73 | if !floats.EqualApprox(ans, a, 1e-12) { 74 | t.Errorf("Case %v, mismatch small work.", c) 75 | } 76 | // Try the full length of work. 77 | impl.Dgelqf(m, n, a, lda, tau, work, -1) 78 | lwork := int(work[0]) 79 | work = make([]float64, lwork) 80 | copy(a, aCopy) 81 | impl.Dgelqf(m, n, a, lda, tau, work, lwork) 82 | if !floats.EqualApprox(ans, a, 1e-12) { 83 | t.Errorf("Case %v, mismatch large work.", c) 84 | } 85 | 86 | // Try a slightly smaller version of work to test blocking code. 87 | if len(work) <= m { 88 | continue 89 | } 90 | work = work[1:] 91 | lwork-- 92 | copy(a, aCopy) 93 | impl.Dgelqf(m, n, a, lda, tau, work, lwork) 94 | if !floats.EqualApprox(ans, a, 1e-12) { 95 | t.Errorf("Case %v, mismatch large work.", c) 96 | } 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /testlapack/dgeql2.go: -------------------------------------------------------------------------------- 1 | // Copyright ©2016 The gonum Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package testlapack 6 | 7 | import ( 8 | "math/rand" 9 | "testing" 10 | 11 | "github.com/gonum/blas" 12 | "github.com/gonum/blas/blas64" 13 | "github.com/gonum/floats" 14 | ) 15 | 16 | type Dgeql2er interface { 17 | Dgeql2(m, n int, a []float64, lda int, tau, work []float64) 18 | } 19 | 20 | func Dgeql2Test(t *testing.T, impl Dgeql2er) { 21 | rnd := rand.New(rand.NewSource(1)) 22 | // TODO(btracey): Add tests for m < n. 23 | for _, test := range []struct { 24 | m, n, lda int 25 | }{ 26 | {5, 5, 0}, 27 | {5, 3, 0}, 28 | {5, 4, 0}, 29 | } { 30 | m := test.m 31 | n := test.n 32 | lda := test.lda 33 | if lda == 0 { 34 | lda = n 35 | } 36 | a := make([]float64, m*lda) 37 | for i := range a { 38 | a[i] = rnd.NormFloat64() 39 | } 40 | tau := nanSlice(min(m, n)) 41 | work := nanSlice(n) 42 | 43 | aCopy := make([]float64, len(a)) 44 | copy(aCopy, a) 45 | impl.Dgeql2(m, n, a, lda, tau, work) 46 | 47 | k := min(m, n) 48 | // Construct Q. 49 | q := blas64.General{ 50 | Rows: m, 51 | Cols: m, 52 | Stride: m, 53 | Data: make([]float64, m*m), 54 | } 55 | for i := 0; i < m; i++ { 56 | q.Data[i*q.Stride+i] = 1 57 | } 58 | for i := 0; i < k; i++ { 59 | h := blas64.General{Rows: m, Cols: m, Stride: m, Data: make([]float64, m*m)} 60 | for j := 0; j < m; j++ { 61 | h.Data[j*h.Stride+j] = 1 62 | } 63 | v := blas64.Vector{Inc: 1, Data: make([]float64, m)} 64 | v.Data[m-k+i] = 1 65 | for j := 0; j < m-k+i; j++ { 66 | v.Data[j] = a[j*lda+n-k+i] 67 | } 68 | blas64.Ger(-tau[i], v, v, h) 69 | qTmp := blas64.General{Rows: q.Rows, Cols: q.Cols, Stride: q.Stride, Data: make([]float64, len(q.Data))} 70 | copy(qTmp.Data, q.Data) 71 | blas64.Gemm(blas.NoTrans, blas.NoTrans, 1, h, qTmp, 0, q) 72 | } 73 | if !isOrthonormal(q) { 74 | t.Errorf("Q is not orthonormal") 75 | } 76 | l := blas64.General{ 77 | Rows: m, 78 | Cols: n, 79 | Stride: n, 80 | Data: make([]float64, m*n), 81 | } 82 | if m >= n { 83 | for i := m - n; i < m; i++ { 84 | for j := 0; j <= min(i-(m-n), n-1); j++ { 85 | l.Data[i*l.Stride+j] = a[i*lda+j] 86 | } 87 | } 88 | } else { 89 | panic("untested") 90 | } 91 | ans := blas64.General{Rows: m, Cols: n, Stride: lda, Data: make([]float64, len(a))} 92 | copy(ans.Data, a) 93 | 94 | blas64.Gemm(blas.NoTrans, blas.NoTrans, 1, q, l, 0, ans) 95 | if !floats.EqualApprox(ans.Data, aCopy, 1e-10) { 96 | t.Errorf("Reconstruction mismatch: m = %v, n = %v", m, n) 97 | } 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /testlapack/dgeqr2.go: -------------------------------------------------------------------------------- 1 | // Copyright ©2015 The gonum Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package testlapack 6 | 7 | import ( 8 | "math" 9 | "math/rand" 10 | "testing" 11 | 12 | "github.com/gonum/blas" 13 | "github.com/gonum/blas/blas64" 14 | "github.com/gonum/floats" 15 | ) 16 | 17 | type Dgeqr2er interface { 18 | Dgeqr2(m, n int, a []float64, lda int, tau []float64, work []float64) 19 | } 20 | 21 | func Dgeqr2Test(t *testing.T, impl Dgeqr2er) { 22 | rnd := rand.New(rand.NewSource(1)) 23 | for c, test := range []struct { 24 | m, n, lda int 25 | }{ 26 | {1, 1, 0}, 27 | {2, 2, 0}, 28 | {3, 2, 0}, 29 | {2, 3, 0}, 30 | {1, 12, 0}, 31 | {2, 6, 0}, 32 | {3, 4, 0}, 33 | {4, 3, 0}, 34 | {6, 2, 0}, 35 | {12, 1, 0}, 36 | {1, 1, 20}, 37 | {2, 2, 20}, 38 | {3, 2, 20}, 39 | {2, 3, 20}, 40 | {1, 12, 20}, 41 | {2, 6, 20}, 42 | {3, 4, 20}, 43 | {4, 3, 20}, 44 | {6, 2, 20}, 45 | {12, 1, 20}, 46 | } { 47 | n := test.n 48 | m := test.m 49 | lda := test.lda 50 | if lda == 0 { 51 | lda = test.n 52 | } 53 | a := make([]float64, m*lda) 54 | for i := range a { 55 | a[i] = rnd.Float64() 56 | } 57 | aCopy := make([]float64, len(a)) 58 | k := min(m, n) 59 | tau := make([]float64, k) 60 | for i := range tau { 61 | tau[i] = rnd.Float64() 62 | } 63 | work := make([]float64, n) 64 | for i := range work { 65 | work[i] = rnd.Float64() 66 | } 67 | copy(aCopy, a) 68 | impl.Dgeqr2(m, n, a, lda, tau, work) 69 | 70 | // Test that the QR factorization has completed successfully. Compute 71 | // Q based on the vectors. 72 | q := constructQ("QR", m, n, a, lda, tau) 73 | 74 | // Check that q is orthonormal 75 | for i := 0; i < m; i++ { 76 | nrm := blas64.Nrm2(m, blas64.Vector{Inc: 1, Data: q.Data[i*m:]}) 77 | if math.Abs(nrm-1) > 1e-14 { 78 | t.Errorf("Case %v, q not normal", c) 79 | } 80 | for j := 0; j < i; j++ { 81 | dot := blas64.Dot(m, blas64.Vector{Inc: 1, Data: q.Data[i*m:]}, blas64.Vector{Inc: 1, Data: q.Data[j*m:]}) 82 | if math.Abs(dot) > 1e-14 { 83 | t.Errorf("Case %v, q not orthogonal", c) 84 | } 85 | } 86 | } 87 | // Check that A = Q * R 88 | r := blas64.General{ 89 | Rows: m, 90 | Cols: n, 91 | Stride: n, 92 | Data: make([]float64, m*n), 93 | } 94 | for i := 0; i < m; i++ { 95 | for j := i; j < n; j++ { 96 | r.Data[i*n+j] = a[i*lda+j] 97 | } 98 | } 99 | atmp := blas64.General{ 100 | Rows: m, 101 | Cols: n, 102 | Stride: lda, 103 | Data: make([]float64, m*lda), 104 | } 105 | copy(atmp.Data, a) 106 | blas64.Gemm(blas.NoTrans, blas.NoTrans, 1, q, r, 0, atmp) 107 | if !floats.EqualApprox(atmp.Data, aCopy, 1e-14) { 108 | t.Errorf("Q*R != a") 109 | } 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /testlapack/dgeqrf.go: -------------------------------------------------------------------------------- 1 | // Copyright ©2015 The gonum Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package testlapack 6 | 7 | import ( 8 | "math/rand" 9 | "testing" 10 | 11 | "github.com/gonum/floats" 12 | ) 13 | 14 | type Dgeqrfer interface { 15 | Dgeqr2er 16 | Dgeqrf(m, n int, a []float64, lda int, tau, work []float64, lwork int) 17 | } 18 | 19 | func DgeqrfTest(t *testing.T, impl Dgeqrfer) { 20 | rnd := rand.New(rand.NewSource(1)) 21 | for c, test := range []struct { 22 | m, n, lda int 23 | }{ 24 | {10, 5, 0}, 25 | {5, 10, 0}, 26 | {10, 10, 0}, 27 | {300, 5, 0}, 28 | {3, 500, 0}, 29 | {200, 200, 0}, 30 | {300, 200, 0}, 31 | {204, 300, 0}, 32 | {1, 3000, 0}, 33 | {3000, 1, 0}, 34 | {10, 5, 20}, 35 | {5, 10, 20}, 36 | {10, 10, 20}, 37 | {300, 5, 400}, 38 | {3, 500, 600}, 39 | {200, 200, 300}, 40 | {300, 200, 300}, 41 | {204, 300, 400}, 42 | {1, 3000, 4000}, 43 | {3000, 1, 4000}, 44 | } { 45 | m := test.m 46 | n := test.n 47 | lda := test.lda 48 | if lda == 0 { 49 | lda = test.n 50 | } 51 | a := make([]float64, m*lda) 52 | for i := 0; i < m; i++ { 53 | for j := 0; j < n; j++ { 54 | a[i*lda+j] = rnd.Float64() 55 | } 56 | } 57 | tau := make([]float64, n) 58 | for i := 0; i < n; i++ { 59 | tau[i] = rnd.Float64() 60 | } 61 | aCopy := make([]float64, len(a)) 62 | copy(aCopy, a) 63 | ans := make([]float64, len(a)) 64 | copy(ans, a) 65 | work := make([]float64, n) 66 | // Compute unblocked QR. 67 | impl.Dgeqr2(m, n, ans, lda, tau, work) 68 | // Compute blocked QR with small work. 69 | impl.Dgeqrf(m, n, a, lda, tau, work, len(work)) 70 | if !floats.EqualApprox(ans, a, 1e-12) { 71 | t.Errorf("Case %v, mismatch small work.", c) 72 | } 73 | // Try the full length of work. 74 | impl.Dgeqrf(m, n, a, lda, tau, work, -1) 75 | lwork := int(work[0]) 76 | work = make([]float64, lwork) 77 | copy(a, aCopy) 78 | impl.Dgeqrf(m, n, a, lda, tau, work, lwork) 79 | if !floats.EqualApprox(ans, a, 1e-12) { 80 | t.Errorf("Case %v, mismatch large work.", c) 81 | } 82 | 83 | // Try a slightly smaller version of work to test blocking. 84 | if len(work) <= n { 85 | continue 86 | } 87 | work = work[1:] 88 | lwork-- 89 | copy(a, aCopy) 90 | impl.Dgeqrf(m, n, a, lda, tau, work, lwork) 91 | if !floats.EqualApprox(ans, a, 1e-12) { 92 | t.Errorf("Case %v, mismatch large work.", c) 93 | } 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /testlapack/dgetrf.go: -------------------------------------------------------------------------------- 1 | // Copyright ©2015 The gonum Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package testlapack 6 | 7 | import ( 8 | "math/rand" 9 | "testing" 10 | ) 11 | 12 | type Dgetrfer interface { 13 | Dgetrf(m, n int, a []float64, lda int, ipiv []int) bool 14 | } 15 | 16 | func DgetrfTest(t *testing.T, impl Dgetrfer) { 17 | rnd := rand.New(rand.NewSource(1)) 18 | for _, test := range []struct { 19 | m, n, lda int 20 | }{ 21 | {10, 5, 0}, 22 | {5, 10, 0}, 23 | {10, 10, 0}, 24 | {300, 5, 0}, 25 | {3, 500, 0}, 26 | {4, 5, 0}, 27 | {300, 200, 0}, 28 | {204, 300, 0}, 29 | {1, 3000, 0}, 30 | {3000, 1, 0}, 31 | {10, 5, 20}, 32 | {5, 10, 20}, 33 | {10, 10, 20}, 34 | {300, 5, 400}, 35 | {3, 500, 600}, 36 | {200, 200, 300}, 37 | {300, 200, 300}, 38 | {204, 300, 400}, 39 | {1, 3000, 4000}, 40 | {3000, 1, 4000}, 41 | } { 42 | m := test.m 43 | n := test.n 44 | lda := test.lda 45 | if lda == 0 { 46 | lda = n 47 | } 48 | a := make([]float64, m*lda) 49 | for i := range a { 50 | a[i] = rnd.Float64() 51 | } 52 | mn := min(m, n) 53 | ipiv := make([]int, mn) 54 | for i := range ipiv { 55 | ipiv[i] = rnd.Int() 56 | } 57 | 58 | // Cannot compare the outputs of Dgetrf and Dgetf2 because the pivoting may 59 | // happen differently. Instead check that the LPQ factorization is correct. 60 | aCopy := make([]float64, len(a)) 61 | copy(aCopy, a) 62 | ok := impl.Dgetrf(m, n, a, lda, ipiv) 63 | checkPLU(t, ok, m, n, lda, ipiv, a, aCopy, 1e-10, false) 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /testlapack/dgetri.go: -------------------------------------------------------------------------------- 1 | // Copyright ©2015 The gonum Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package testlapack 6 | 7 | import ( 8 | "math" 9 | "math/rand" 10 | "testing" 11 | 12 | "github.com/gonum/blas" 13 | "github.com/gonum/blas/blas64" 14 | ) 15 | 16 | type Dgetrier interface { 17 | Dgetrfer 18 | Dgetri(n int, a []float64, lda int, ipiv []int, work []float64, lwork int) bool 19 | } 20 | 21 | func DgetriTest(t *testing.T, impl Dgetrier) { 22 | rnd := rand.New(rand.NewSource(1)) 23 | bi := blas64.Implementation() 24 | for _, test := range []struct { 25 | n, lda int 26 | }{ 27 | {5, 0}, 28 | {5, 8}, 29 | {45, 0}, 30 | {45, 50}, 31 | {65, 0}, 32 | {65, 70}, 33 | {150, 0}, 34 | {150, 250}, 35 | } { 36 | n := test.n 37 | lda := test.lda 38 | if lda == 0 { 39 | lda = n 40 | } 41 | // Generate a random well conditioned matrix 42 | perm := rnd.Perm(n) 43 | a := make([]float64, n*lda) 44 | for i := 0; i < n; i++ { 45 | a[i*lda+perm[i]] = 1 46 | } 47 | for i := range a { 48 | a[i] += 0.01 * rnd.Float64() 49 | } 50 | aCopy := make([]float64, len(a)) 51 | copy(aCopy, a) 52 | ipiv := make([]int, n) 53 | // Compute LU decomposition. 54 | impl.Dgetrf(n, n, a, lda, ipiv) 55 | // Compute inverse. 56 | work := make([]float64, 1) 57 | impl.Dgetri(n, a, lda, ipiv, work, -1) 58 | work = make([]float64, int(work[0])) 59 | lwork := len(work) 60 | 61 | ok := impl.Dgetri(n, a, lda, ipiv, work, lwork) 62 | if !ok { 63 | t.Errorf("Unexpected singular matrix.") 64 | } 65 | 66 | // Check that A(inv) * A = I. 67 | ans := make([]float64, len(a)) 68 | bi.Dgemm(blas.NoTrans, blas.NoTrans, n, n, n, 1, aCopy, lda, a, lda, 0, ans, lda) 69 | isEye := true 70 | for i := 0; i < n; i++ { 71 | for j := 0; j < n; j++ { 72 | if i == j { 73 | // This tolerance is so high because computing matrix inverses 74 | // is very unstable. 75 | if math.Abs(ans[i*lda+j]-1) > 5e-2 { 76 | isEye = false 77 | } 78 | } else { 79 | if math.Abs(ans[i*lda+j]) > 5e-2 { 80 | isEye = false 81 | } 82 | } 83 | } 84 | } 85 | if !isEye { 86 | t.Errorf("Inv(A) * A != I. n = %v, lda = %v", n, lda) 87 | } 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /testlapack/dlabrd.go: -------------------------------------------------------------------------------- 1 | // Copyright ©2015 The gonum Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package testlapack 6 | 7 | import ( 8 | "math" 9 | "math/rand" 10 | "testing" 11 | ) 12 | 13 | type Dlabrder interface { 14 | Dlabrd(m, n, nb int, a []float64, lda int, d, e, tauq, taup, x []float64, ldx int, y []float64, ldy int) 15 | } 16 | 17 | func DlabrdTest(t *testing.T, impl Dlabrder) { 18 | rnd := rand.New(rand.NewSource(1)) 19 | for _, test := range []struct { 20 | m, n, nb, lda, ldx, ldy int 21 | }{ 22 | {4, 5, 2, 0, 0, 0}, 23 | {4, 5, 4, 0, 0, 0}, 24 | {5, 5, 2, 0, 0, 0}, 25 | {5, 5, 5, 0, 0, 0}, 26 | {5, 4, 4, 0, 0, 0}, 27 | {5, 4, 4, 0, 0, 0}, 28 | 29 | {4, 5, 2, 10, 11, 12}, 30 | {4, 5, 4, 10, 11, 12}, 31 | {5, 5, 2, 10, 11, 12}, 32 | {5, 5, 5, 10, 11, 12}, 33 | {5, 4, 2, 10, 11, 12}, 34 | {5, 4, 4, 10, 11, 12}, 35 | 36 | {4, 5, 2, 11, 12, 10}, 37 | {4, 5, 4, 11, 12, 10}, 38 | {5, 5, 2, 11, 12, 10}, 39 | {5, 5, 5, 11, 12, 10}, 40 | {5, 4, 2, 11, 12, 10}, 41 | {5, 4, 4, 11, 12, 10}, 42 | 43 | {4, 5, 2, 12, 11, 10}, 44 | {4, 5, 4, 12, 11, 10}, 45 | {5, 5, 2, 12, 11, 10}, 46 | {5, 5, 5, 12, 11, 10}, 47 | {5, 4, 2, 12, 11, 10}, 48 | {5, 4, 4, 12, 11, 10}, 49 | } { 50 | m := test.m 51 | n := test.n 52 | nb := test.nb 53 | lda := test.lda 54 | if lda == 0 { 55 | lda = n 56 | } 57 | ldy := test.ldy 58 | if ldy == 0 { 59 | ldy = nb 60 | } 61 | ldx := test.ldx 62 | if ldx == 0 { 63 | ldx = nb 64 | } 65 | a := make([]float64, m*lda) 66 | for i := range a { 67 | a[i] = rnd.NormFloat64() 68 | } 69 | d := make([]float64, nb) 70 | for i := range d { 71 | d[i] = math.NaN() 72 | } 73 | e := make([]float64, nb) 74 | for i := range e { 75 | e[i] = math.NaN() 76 | } 77 | tauP := make([]float64, nb) 78 | for i := range tauP { 79 | tauP[i] = math.NaN() 80 | } 81 | tauQ := make([]float64, nb) 82 | for i := range tauP { 83 | tauQ[i] = math.NaN() 84 | } 85 | x := make([]float64, m*ldx) 86 | for i := range x { 87 | x[i] = rnd.NormFloat64() 88 | } 89 | y := make([]float64, n*ldy) 90 | for i := range y { 91 | y[i] = rnd.NormFloat64() 92 | } 93 | aCopy := make([]float64, len(a)) 94 | copy(aCopy, a) 95 | 96 | // Compute the reduction. 97 | impl.Dlabrd(m, n, nb, a, lda, d, e, tauQ, tauP, x, ldx, y, ldy) 98 | 99 | if m >= n && nb == n { 100 | tauP[n-1] = 0 101 | } 102 | if m < n && nb == m { 103 | tauQ[m-1] = 0 104 | } 105 | checkBidiagonal(t, m, n, nb, a, lda, d, e, tauP, tauQ, aCopy) 106 | } 107 | } 108 | -------------------------------------------------------------------------------- /testlapack/dlacn2.go: -------------------------------------------------------------------------------- 1 | // Copyright ©2016 The gonum Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package testlapack 6 | 7 | import ( 8 | "math" 9 | "math/rand" 10 | "testing" 11 | 12 | "github.com/gonum/blas" 13 | "github.com/gonum/blas/blas64" 14 | ) 15 | 16 | type Dlacn2er interface { 17 | Dlacn2(n int, v, x []float64, isgn []int, est float64, kase int, isave *[3]int) (float64, int) 18 | } 19 | 20 | func Dlacn2Test(t *testing.T, impl Dlacn2er) { 21 | rnd := rand.New(rand.NewSource(1)) 22 | for _, n := range []int{1, 2, 3, 4, 5, 7, 10, 15, 20, 100} { 23 | for cas := 0; cas < 10; cas++ { 24 | a := randomGeneral(n, n, n, rnd) 25 | 26 | // Compute the 1-norm of A explicitly. 27 | var norm1 float64 28 | for j := 0; j < n; j++ { 29 | var sum float64 30 | for i := 0; i < n; i++ { 31 | sum += math.Abs(a.Data[i*a.Stride+j]) 32 | } 33 | if sum > norm1 { 34 | norm1 = sum 35 | } 36 | } 37 | 38 | // Compute the estimate of 1-norm using Dlanc2. 39 | x := make([]float64, n) 40 | work := make([]float64, n) 41 | v := make([]float64, n) 42 | isgn := make([]int, n) 43 | var ( 44 | kase int 45 | isave [3]int 46 | got float64 47 | ) 48 | loop: 49 | for { 50 | got, kase = impl.Dlacn2(n, v, x, isgn, got, kase, &isave) 51 | switch kase { 52 | default: 53 | panic("Dlacn2 returned invalid value of kase") 54 | case 0: 55 | break loop 56 | case 1: 57 | blas64.Gemv(blas.NoTrans, 1, a, blas64.Vector{1, x}, 0, blas64.Vector{1, work}) 58 | copy(x, work) 59 | case 2: 60 | blas64.Gemv(blas.Trans, 1, a, blas64.Vector{1, x}, 0, blas64.Vector{1, work}) 61 | copy(x, work) 62 | } 63 | } 64 | 65 | // Check that got is either accurate enough or a 66 | // lower estimate of the 1-norm of A. 67 | if math.Abs(got-norm1) > 1e-8 && got > norm1 { 68 | t.Errorf("Case n=%v: not lower estimate. 1-norm %v, estimate %v", n, norm1, got) 69 | } 70 | } 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /testlapack/dlacpy.go: -------------------------------------------------------------------------------- 1 | // Copyright ©2015 The gonum Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package testlapack 6 | 7 | import ( 8 | "fmt" 9 | "math/rand" 10 | "testing" 11 | 12 | "github.com/gonum/blas" 13 | ) 14 | 15 | type Dlacpyer interface { 16 | Dlacpy(uplo blas.Uplo, m, n int, a []float64, lda int, b []float64, ldb int) 17 | } 18 | 19 | func DlacpyTest(t *testing.T, impl Dlacpyer) { 20 | rnd := rand.New(rand.NewSource(1)) 21 | for _, uplo := range []blas.Uplo{blas.Upper, blas.Lower, blas.All} { 22 | for _, test := range []struct { 23 | m, n, lda, ldb int 24 | }{ 25 | {3, 5, 0, 0}, 26 | {5, 5, 0, 0}, 27 | {7, 5, 0, 0}, 28 | 29 | {3, 5, 10, 12}, 30 | {5, 5, 10, 12}, 31 | {7, 5, 10, 12}, 32 | } { 33 | m := test.m 34 | n := test.n 35 | lda := test.lda 36 | if lda == 0 { 37 | lda = n 38 | } 39 | ldb := test.ldb 40 | if ldb == 0 { 41 | ldb = n 42 | } 43 | a := make([]float64, m*lda) 44 | for i := range a { 45 | a[i] = rnd.Float64() 46 | } 47 | b := make([]float64, m*ldb) 48 | for i := range b { 49 | b[i] = rnd.Float64() 50 | } 51 | impl.Dlacpy(uplo, m, n, a, lda, b, ldb) 52 | equal := true 53 | switch uplo { 54 | case blas.Upper: 55 | for i := 0; i < m; i++ { 56 | for j := i; j < n; j++ { 57 | if b[i*ldb+j] != a[i*lda+j] { 58 | equal = false 59 | goto DoneCheck 60 | } 61 | } 62 | } 63 | case blas.Lower: 64 | for i := 0; i < m; i++ { 65 | for j := 0; j < min(i, n); j++ { 66 | if b[i*ldb+j] != a[i*lda+j] { 67 | equal = false 68 | goto DoneCheck 69 | } 70 | } 71 | } 72 | case blas.All: 73 | for i := 0; i < m; i++ { 74 | for j := 0; j < n; j++ { 75 | if b[i*ldb+j] != a[i*lda+j] { 76 | equal = false 77 | goto DoneCheck 78 | } 79 | } 80 | } 81 | } 82 | DoneCheck: 83 | if !equal { 84 | fmt.Println(blas.Lower) 85 | t.Errorf("Matrices not equal after copy. Uplo = %d, m = %d, n = %d", uplo, m, n) 86 | } 87 | } 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /testlapack/dlae2.go: -------------------------------------------------------------------------------- 1 | // Copyright ©2016 The gonum Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package testlapack 6 | 7 | import ( 8 | "fmt" 9 | "math" 10 | "testing" 11 | ) 12 | 13 | type Dlae2er interface { 14 | Dlae2(a, b, c float64) (rt1, rt2 float64) 15 | } 16 | 17 | func Dlae2Test(t *testing.T, impl Dlae2er) { 18 | for _, test := range []struct { 19 | a, b, c float64 20 | }{ 21 | {-10, 5, 3}, 22 | {3, 5, -10}, 23 | {0, 3, 0}, 24 | {1, 3, 1}, 25 | {1, -3, 1}, 26 | {5, 0, 3}, 27 | {3, 0, -5}, 28 | {1, 3, 1.02}, 29 | {1.02, 3, 1}, 30 | {1, -3, -9}, 31 | } { 32 | a := test.a 33 | b := test.b 34 | c := test.c 35 | rt1, rt2 := impl.Dlae2(a, b, c) 36 | 37 | errStr := fmt.Sprintf("a = %v, b = %v, c = %v", a, b, c) 38 | // Check if rt1 and rt2 are eigenvalues by checking if det(a - λI) = 0 39 | a1 := a - rt1 40 | c1 := c - rt1 41 | det := a1*c1 - b*b 42 | if math.Abs(det) > 1e-10 { 43 | t.Errorf("First eigenvalue mismatch. %s. Det = %v", errStr, det) 44 | } 45 | 46 | a2 := a - rt2 47 | c2 := c - rt2 48 | det = a2*c2 - b*b 49 | if math.Abs(det) > 1e-10 { 50 | t.Errorf("Second eigenvalue mismatch. %s. Det = %v", errStr, det) 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /testlapack/dlaev2.go: -------------------------------------------------------------------------------- 1 | // Copyright ©2015 The gonum Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package testlapack 6 | 7 | import ( 8 | "math" 9 | "math/rand" 10 | "testing" 11 | ) 12 | 13 | type Dlaev2er interface { 14 | Dlaev2(a, b, c float64) (rt1, rt2, cs1, sn1 float64) 15 | } 16 | 17 | func Dlaev2Test(t *testing.T, impl Dlaev2er) { 18 | rnd := rand.New(rand.NewSource(1)) 19 | for trial := 0; trial < 100; trial++ { 20 | a := rnd.NormFloat64() 21 | b := rnd.NormFloat64() 22 | c := rnd.NormFloat64() 23 | 24 | rt1, rt2, cs1, sn1 := impl.Dlaev2(a, b, c) 25 | tmp := mul2by2([2][2]float64{{cs1, sn1}, {-sn1, cs1}}, [2][2]float64{{a, b}, {b, c}}) 26 | ans := mul2by2(tmp, [2][2]float64{{cs1, -sn1}, {sn1, cs1}}) 27 | if math.Abs(ans[0][0]-rt1) > 1e-14 { 28 | t.Errorf("Largest eigenvalue mismatch. Returned %v, mul %v", rt1, ans[0][0]) 29 | } 30 | if math.Abs(ans[1][0]) > 1e-14 || math.Abs(ans[0][1]) > 1e-14 { 31 | t.Errorf("Non-zero off diagonal. ans[1][0] = %v, ans[0][1] = %v", ans[1][0], ans[0][1]) 32 | } 33 | if math.Abs(ans[1][1]-rt2) > 1e-14 { 34 | t.Errorf("Smallest eigenvalue mismatch. Returned %v, mul %v", rt2, ans[1][1]) 35 | } 36 | } 37 | } 38 | 39 | func mul2by2(a, b [2][2]float64) [2][2]float64 { 40 | var c [2][2]float64 41 | c[0][0] = a[0][0]*b[0][0] + a[0][1]*b[1][0] 42 | c[0][1] = a[0][0]*b[0][1] + a[0][1]*b[1][1] 43 | c[1][0] = a[1][0]*b[0][0] + a[1][1]*b[1][0] 44 | c[1][1] = a[1][0]*b[0][1] + a[1][1]*b[1][1] 45 | return c 46 | } 47 | -------------------------------------------------------------------------------- /testlapack/dlange.go: -------------------------------------------------------------------------------- 1 | // Copyright ©2015 The gonum Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package testlapack 6 | 7 | import ( 8 | "math" 9 | "math/rand" 10 | "testing" 11 | 12 | "github.com/gonum/blas/blas64" 13 | "github.com/gonum/lapack" 14 | ) 15 | 16 | type Dlanger interface { 17 | Dlange(norm lapack.MatrixNorm, m, n int, a []float64, lda int, work []float64) float64 18 | } 19 | 20 | func DlangeTest(t *testing.T, impl Dlanger) { 21 | rnd := rand.New(rand.NewSource(1)) 22 | for _, test := range []struct { 23 | m, n, lda int 24 | }{ 25 | {4, 3, 0}, 26 | {3, 4, 0}, 27 | {4, 3, 100}, 28 | {3, 4, 100}, 29 | } { 30 | m := test.m 31 | n := test.n 32 | lda := test.lda 33 | if lda == 0 { 34 | lda = n 35 | } 36 | a := make([]float64, m*lda) 37 | for i := range a { 38 | a[i] = rnd.Float64() - 0.5 39 | } 40 | work := make([]float64, n) 41 | for i := range work { 42 | work[i] = rnd.Float64() 43 | } 44 | aCopy := make([]float64, len(a)) 45 | copy(aCopy, a) 46 | 47 | // Test MaxAbs norm. 48 | norm := impl.Dlange(lapack.MaxAbs, m, n, a, lda, work) 49 | var ans float64 50 | for i := 0; i < m; i++ { 51 | idx := blas64.Iamax(n, blas64.Vector{Inc: 1, Data: aCopy[i*lda:]}) 52 | ans = math.Max(ans, math.Abs(a[i*lda+idx])) 53 | } 54 | // Should be strictly equal because there is no floating point summation error. 55 | if ans != norm { 56 | t.Errorf("MaxAbs mismatch. Want %v, got %v.", ans, norm) 57 | } 58 | 59 | // Test MaxColumnSum norm. 60 | norm = impl.Dlange(lapack.MaxColumnSum, m, n, a, lda, work) 61 | ans = 0 62 | for i := 0; i < n; i++ { 63 | sum := blas64.Asum(m, blas64.Vector{Inc: lda, Data: aCopy[i:]}) 64 | ans = math.Max(ans, sum) 65 | } 66 | if math.Abs(norm-ans) > 1e-14 { 67 | t.Errorf("MaxColumnSum mismatch. Want %v, got %v.", ans, norm) 68 | } 69 | 70 | // Test MaxRowSum norm. 71 | norm = impl.Dlange(lapack.MaxRowSum, m, n, a, lda, work) 72 | ans = 0 73 | for i := 0; i < m; i++ { 74 | sum := blas64.Asum(n, blas64.Vector{Inc: 1, Data: aCopy[i*lda:]}) 75 | ans = math.Max(ans, sum) 76 | } 77 | if math.Abs(norm-ans) > 1e-14 { 78 | t.Errorf("MaxRowSum mismatch. Want %v, got %v.", ans, norm) 79 | } 80 | 81 | // Test Frobenius norm 82 | norm = impl.Dlange(lapack.NormFrob, m, n, a, lda, work) 83 | ans = 0 84 | for i := 0; i < m; i++ { 85 | sum := blas64.Nrm2(n, blas64.Vector{Inc: 1, Data: aCopy[i*lda:]}) 86 | ans += sum * sum 87 | } 88 | ans = math.Sqrt(ans) 89 | if math.Abs(norm-ans) > 1e-14 { 90 | t.Errorf("NormFrob mismatch. Want %v, got %v.", ans, norm) 91 | } 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /testlapack/dlanst.go: -------------------------------------------------------------------------------- 1 | // Copyright ©2016 The gonum Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package testlapack 6 | 7 | import ( 8 | "math" 9 | "math/rand" 10 | "testing" 11 | 12 | "github.com/gonum/lapack" 13 | ) 14 | 15 | type Dlanster interface { 16 | Dlanst(norm lapack.MatrixNorm, n int, d, e []float64) float64 17 | Dlanger 18 | } 19 | 20 | func DlanstTest(t *testing.T, impl Dlanster) { 21 | rnd := rand.New(rand.NewSource(1)) 22 | for _, norm := range []lapack.MatrixNorm{lapack.MaxAbs, lapack.MaxColumnSum, lapack.MaxRowSum, lapack.NormFrob} { 23 | for _, n := range []int{1, 3, 10, 100} { 24 | for cas := 0; cas < 100; cas++ { 25 | d := make([]float64, n) 26 | for i := range d { 27 | d[i] = rnd.NormFloat64() 28 | } 29 | e := make([]float64, n-1) 30 | for i := range e { 31 | e[i] = rnd.NormFloat64() 32 | } 33 | 34 | m := n 35 | lda := n 36 | a := make([]float64, m*lda) 37 | for i := 0; i < n; i++ { 38 | a[i*lda+i] = d[i] 39 | } 40 | for i := 0; i < n-1; i++ { 41 | a[i*lda+i+1] = e[i] 42 | a[(i+1)*lda+i] = e[i] 43 | } 44 | work := make([]float64, n) 45 | syNorm := impl.Dlanst(norm, n, d, e) 46 | geNorm := impl.Dlange(norm, m, n, a, lda, work) 47 | if math.Abs(syNorm-geNorm) > 1e-12 { 48 | t.Errorf("Norm mismatch: norm = %v, cas = %v, n = %v. Want %v, got %v.", string(norm), cas, n, geNorm, syNorm) 49 | } 50 | } 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /testlapack/dlansy.go: -------------------------------------------------------------------------------- 1 | // Copyright ©2015 The gonum Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package testlapack 6 | 7 | import ( 8 | "math" 9 | "math/rand" 10 | "testing" 11 | 12 | "github.com/gonum/blas" 13 | "github.com/gonum/lapack" 14 | ) 15 | 16 | type Dlansyer interface { 17 | Dlanger 18 | Dlansy(norm lapack.MatrixNorm, uplo blas.Uplo, n int, a []float64, lda int, work []float64) float64 19 | } 20 | 21 | func DlansyTest(t *testing.T, impl Dlansyer) { 22 | rnd := rand.New(rand.NewSource(1)) 23 | for _, norm := range []lapack.MatrixNorm{lapack.MaxAbs, lapack.MaxColumnSum, lapack.MaxRowSum, lapack.NormFrob} { 24 | for _, uplo := range []blas.Uplo{blas.Lower, blas.Upper} { 25 | for _, test := range []struct { 26 | n, lda int 27 | }{ 28 | {1, 0}, 29 | {3, 0}, 30 | 31 | {1, 10}, 32 | {3, 10}, 33 | } { 34 | for trial := 0; trial < 100; trial++ { 35 | n := test.n 36 | lda := test.lda 37 | if lda == 0 { 38 | lda = n 39 | } 40 | a := make([]float64, lda*n) 41 | if trial == 0 { 42 | for i := range a { 43 | a[i] = float64(i) 44 | } 45 | } else { 46 | for i := range a { 47 | a[i] = rnd.NormFloat64() 48 | } 49 | } 50 | 51 | aDense := make([]float64, n*n) 52 | if uplo == blas.Upper { 53 | for i := 0; i < n; i++ { 54 | for j := i; j < n; j++ { 55 | v := a[i*lda+j] 56 | aDense[i*n+j] = v 57 | aDense[j*n+i] = v 58 | } 59 | } 60 | } else { 61 | for i := 0; i < n; i++ { 62 | for j := 0; j <= i; j++ { 63 | v := a[i*lda+j] 64 | aDense[i*n+j] = v 65 | aDense[j*n+i] = v 66 | } 67 | } 68 | } 69 | work := make([]float64, n) 70 | got := impl.Dlansy(norm, uplo, n, a, lda, work) 71 | want := impl.Dlange(norm, n, n, aDense, n, work) 72 | if math.Abs(want-got) > 1e-14 { 73 | t.Errorf("Norm mismatch. norm = %c, upper = %v, n = %v, lda = %v, want %v, got %v.", 74 | norm, uplo == blas.Upper, n, lda, got, want) 75 | } 76 | } 77 | } 78 | } 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /testlapack/dlantr.go: -------------------------------------------------------------------------------- 1 | // Copyright ©2015 The gonum Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package testlapack 6 | 7 | import ( 8 | "math" 9 | "math/rand" 10 | "testing" 11 | 12 | "github.com/gonum/blas" 13 | "github.com/gonum/lapack" 14 | ) 15 | 16 | type Dlantrer interface { 17 | Dlanger 18 | Dlantr(norm lapack.MatrixNorm, uplo blas.Uplo, diag blas.Diag, m, n int, a []float64, lda int, work []float64) float64 19 | } 20 | 21 | func DlantrTest(t *testing.T, impl Dlantrer) { 22 | rnd := rand.New(rand.NewSource(1)) 23 | for _, norm := range []lapack.MatrixNorm{lapack.MaxAbs, lapack.MaxColumnSum, lapack.MaxRowSum, lapack.NormFrob} { 24 | for _, diag := range []blas.Diag{blas.NonUnit, blas.Unit} { 25 | for _, uplo := range []blas.Uplo{blas.Lower, blas.Upper} { 26 | for _, test := range []struct { 27 | m, n, lda int 28 | }{ 29 | {3, 3, 0}, 30 | {3, 5, 0}, 31 | {10, 5, 0}, 32 | 33 | {5, 5, 11}, 34 | {5, 10, 11}, 35 | {10, 5, 11}, 36 | } { 37 | // Do a couple of random trials since the values change. 38 | for trial := 0; trial < 100; trial++ { 39 | m := test.m 40 | n := test.n 41 | lda := test.lda 42 | if lda == 0 { 43 | lda = n 44 | } 45 | a := make([]float64, m*lda) 46 | if trial == 0 { 47 | for i := range a { 48 | a[i] = float64(i) 49 | } 50 | } else { 51 | for i := range a { 52 | a[i] = rnd.NormFloat64() 53 | } 54 | } 55 | aDense := make([]float64, len(a)) 56 | if uplo == blas.Lower { 57 | for i := 0; i < m; i++ { 58 | for j := 0; j <= min(i, n-1); j++ { 59 | aDense[i*lda+j] = a[i*lda+j] 60 | } 61 | } 62 | } else { 63 | for i := 0; i < m; i++ { 64 | for j := i; j < n; j++ { 65 | aDense[i*lda+j] = a[i*lda+j] 66 | } 67 | } 68 | } 69 | if diag == blas.Unit { 70 | for i := 0; i < min(m, n); i++ { 71 | aDense[i*lda+i] = 1 72 | } 73 | } 74 | work := make([]float64, n+6) 75 | for i := range work { 76 | work[i] = rnd.Float64() 77 | } 78 | got := impl.Dlantr(norm, uplo, diag, m, n, a, lda, work) 79 | want := impl.Dlange(norm, m, n, aDense, lda, work) 80 | if math.Abs(got-want) > 1e-13 { 81 | t.Errorf("Norm mismatch. norm = %c, unitdiag = %v, upper = %v, m = %v, n = %v, lda = %v, Want %v, got %v.", 82 | norm, diag == blas.Unit, uplo == blas.Upper, m, n, lda, got, want) 83 | } 84 | } 85 | } 86 | } 87 | } 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /testlapack/dlanv2.go: -------------------------------------------------------------------------------- 1 | // Copyright ©2016 The gonum Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package testlapack 6 | 7 | import ( 8 | "fmt" 9 | "math" 10 | "math/rand" 11 | "testing" 12 | ) 13 | 14 | type Dlanv2er interface { 15 | Dlanv2(a, b, c, d float64) (aa, bb, cc, dd float64, rt1r, rt1i, rt2r, rt2i float64, cs, sn float64) 16 | } 17 | 18 | func Dlanv2Test(t *testing.T, impl Dlanv2er) { 19 | rnd := rand.New(rand.NewSource(1)) 20 | for i := 0; i < 1000; i++ { 21 | a := rnd.NormFloat64() 22 | b := rnd.NormFloat64() 23 | c := rnd.NormFloat64() 24 | d := rnd.NormFloat64() 25 | aa, bb, cc, dd, rt1r, rt1i, rt2r, rt2i, cs, sn := impl.Dlanv2(a, b, c, d) 26 | 27 | mat := fmt.Sprintf("[%v %v; %v %v]", a, b, c, d) 28 | if cc == 0 { 29 | if rt1i != 0 || rt2i != 0 { 30 | t.Errorf("Unexpected complex eigenvalues for %v", mat) 31 | } 32 | } else { 33 | if aa != dd { 34 | t.Errorf("Diagonal elements not equal for %v: got [%v %v]", mat, aa, dd) 35 | } 36 | if bb*cc >= 0 { 37 | t.Errorf("Non-diagonal elements have the same sign for %v: got [%v %v]", mat, bb, cc) 38 | } else { 39 | im := math.Sqrt(-bb * cc) 40 | if math.Abs(rt1i-im) > 1e-14 && math.Abs(rt1i+im) > 1e-14 { 41 | t.Errorf("Unexpected imaginary part of eigenvalue for %v: got %v, want %v or %v", mat, rt1i, im, -im) 42 | } 43 | if math.Abs(rt2i-im) > 1e-14 && math.Abs(rt2i+im) > 1e-14 { 44 | t.Errorf("Unexpected imaginary part of eigenvalue for %v: got %v, want %v or %v", mat, rt2i, im, -im) 45 | } 46 | } 47 | } 48 | if rt1r != aa && rt1r != dd { 49 | t.Errorf("Unexpected real part of eigenvalue for %v: got %v, want %v or %v", mat, rt1r, aa, dd) 50 | } 51 | if rt2r != aa && rt2r != dd { 52 | t.Errorf("Unexpected real part of eigenvalue for %v: got %v, want %v or %v", mat, rt2r, aa, dd) 53 | } 54 | if math.Abs(math.Hypot(cs, sn)-1) > 1e-14 { 55 | t.Errorf("Unexpected unitary matrix for %v: got cs %v, sn %v", mat, cs, sn) 56 | } 57 | 58 | gota := cs*(aa*cs-bb*sn) - sn*(cc*cs-dd*sn) 59 | gotb := cs*(aa*sn+bb*cs) - sn*(cc*sn+dd*cs) 60 | gotc := sn*(aa*cs-bb*sn) + cs*(cc*cs-dd*sn) 61 | gotd := sn*(aa*sn+bb*cs) + cs*(cc*sn+dd*cs) 62 | if math.Abs(gota-a) > 1e-14 || 63 | math.Abs(gotb-b) > 1e-14 || 64 | math.Abs(gotc-c) > 1e-14 || 65 | math.Abs(gotd-d) > 1e-14 { 66 | t.Errorf("Unexpected factorization: got [%v %v; %v %v], want [%v %v; %v %v]", gota, gotb, gotc, gotd, a, b, c, d) 67 | } 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /testlapack/dlapll.go: -------------------------------------------------------------------------------- 1 | // Copyright ©2017 The gonum Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package testlapack 6 | 7 | import ( 8 | "math/rand" 9 | "testing" 10 | 11 | "github.com/gonum/floats" 12 | "github.com/gonum/lapack" 13 | ) 14 | 15 | type Dlapller interface { 16 | Dgesvder 17 | Dlapll(n int, x []float64, incX int, y []float64, incY int) float64 18 | } 19 | 20 | func DlapllTest(t *testing.T, impl Dlapller) { 21 | rnd := rand.New(rand.NewSource(1)) 22 | for i, m := range []int{5, 6, 9, 300, 400, 600} { 23 | n := 2 24 | lda := n 25 | a := make([]float64, m*lda) 26 | for i := range a { 27 | a[i] = rnd.NormFloat64() 28 | } 29 | 30 | aCopy := make([]float64, len(a)) 31 | copy(aCopy, a) 32 | 33 | got := impl.Dlapll(m, a[0:], 2, a[1:], 2) 34 | 35 | s := make([]float64, min(m, n)) 36 | work := make([]float64, 1) 37 | impl.Dgesvd(lapack.SVDNone, lapack.SVDNone, m, n, aCopy, lda, s, nil, 0, nil, 0, work, -1) 38 | work = make([]float64, int(work[0])) 39 | impl.Dgesvd(lapack.SVDNone, lapack.SVDNone, m, n, aCopy, lda, s, nil, 0, nil, 0, work, len(work)) 40 | want := s[len(s)-1] 41 | 42 | if !floats.EqualWithinAbsOrRel(got, want, 1e-14, 1e-14) { 43 | t.Errorf("unexpected ssmin for test %d: got:%f want:%f", i, got, want) 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /testlapack/dlapmt.go: -------------------------------------------------------------------------------- 1 | // Copyright ©2017 The gonum Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package testlapack 6 | 7 | import ( 8 | "fmt" 9 | "testing" 10 | 11 | "github.com/gonum/blas/blas64" 12 | ) 13 | 14 | type Dlapmter interface { 15 | Dlapmt(forward bool, m, n int, x []float64, ldx int, k []int) 16 | } 17 | 18 | func DlapmtTest(t *testing.T, impl Dlapmter) { 19 | for ti, test := range []struct { 20 | forward bool 21 | k []int 22 | 23 | want blas64.General 24 | }{ 25 | { 26 | forward: true, k: []int{0, 1, 2}, 27 | want: blas64.General{ 28 | Rows: 4, 29 | Cols: 3, 30 | Stride: 3, 31 | Data: []float64{ 32 | 1, 2, 3, 33 | 4, 5, 6, 34 | 7, 8, 9, 35 | 10, 11, 12, 36 | }, 37 | }, 38 | }, 39 | { 40 | forward: false, k: []int{0, 1, 2}, 41 | want: blas64.General{ 42 | Rows: 4, 43 | Cols: 3, 44 | Stride: 3, 45 | Data: []float64{ 46 | 1, 2, 3, 47 | 4, 5, 6, 48 | 7, 8, 9, 49 | 10, 11, 12, 50 | }, 51 | }, 52 | }, 53 | { 54 | forward: true, k: []int{1, 2, 0}, 55 | want: blas64.General{ 56 | Rows: 4, 57 | Cols: 3, 58 | Stride: 3, 59 | Data: []float64{ 60 | 2, 3, 1, 61 | 5, 6, 4, 62 | 8, 9, 7, 63 | 11, 12, 10, 64 | }, 65 | }, 66 | }, 67 | { 68 | forward: false, k: []int{1, 2, 0}, 69 | want: blas64.General{ 70 | Rows: 4, 71 | Cols: 3, 72 | Stride: 3, 73 | Data: []float64{ 74 | 3, 1, 2, 75 | 6, 4, 5, 76 | 9, 7, 8, 77 | 12, 10, 11, 78 | }, 79 | }, 80 | }, 81 | } { 82 | m := test.want.Rows 83 | n := test.want.Cols 84 | if len(test.k) != n { 85 | panic("bad length of k") 86 | } 87 | 88 | for _, extra := range []int{0, 11} { 89 | x := zeros(m, n, n+extra) 90 | c := 1 91 | for i := 0; i < m; i++ { 92 | for j := 0; j < n; j++ { 93 | x.Data[i*x.Stride+j] = float64(c) 94 | c++ 95 | } 96 | } 97 | 98 | k := make([]int, len(test.k)) 99 | copy(k, test.k) 100 | 101 | impl.Dlapmt(test.forward, m, n, x.Data, x.Stride, k) 102 | 103 | prefix := fmt.Sprintf("Case %v (forward=%t,m=%v,n=%v,extra=%v)", ti, test.forward, m, n, extra) 104 | if !generalOutsideAllNaN(x) { 105 | t.Errorf("%v: out-of-range write to X", prefix) 106 | } 107 | 108 | if !equalApproxGeneral(x, test.want, 0) { 109 | t.Errorf("%v: unexpected X\n%v\n%v", prefix, x, test.want) 110 | } 111 | } 112 | } 113 | } 114 | -------------------------------------------------------------------------------- /testlapack/dlapy2.go: -------------------------------------------------------------------------------- 1 | // Copyright ©2016 The gonum Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package testlapack 6 | 7 | import ( 8 | "math" 9 | "math/rand" 10 | "testing" 11 | 12 | "github.com/gonum/floats" 13 | ) 14 | 15 | type Dlapy2er interface { 16 | Dlapy2(float64, float64) float64 17 | } 18 | 19 | func Dlapy2Test(t *testing.T, impl Dlapy2er) { 20 | rnd := rand.New(rand.NewSource(1)) 21 | for i := 0; i < 10; i++ { 22 | x := math.Abs(1e200 * rnd.NormFloat64()) 23 | y := math.Abs(1e200 * rnd.NormFloat64()) 24 | got := impl.Dlapy2(x, y) 25 | want := math.Hypot(x, y) 26 | if !floats.EqualWithinRel(got, want, 1e-16) { 27 | t.Errorf("Dlapy2(%g, %g) = %g, want %g", x, y, got, want) 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /testlapack/dlaqr1.go: -------------------------------------------------------------------------------- 1 | // Copyright ©2016 The gonum Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package testlapack 6 | 7 | import ( 8 | "math" 9 | "math/rand" 10 | "testing" 11 | 12 | "github.com/gonum/floats" 13 | ) 14 | 15 | type Dlaqr1er interface { 16 | Dlaqr1(n int, h []float64, ldh int, sr1, si1, sr2, si2 float64, v []float64) 17 | } 18 | 19 | func Dlaqr1Test(t *testing.T, impl Dlaqr1er) { 20 | rnd := rand.New(rand.NewSource(1)) 21 | 22 | for _, n := range []int{2, 3} { 23 | for _, ldh := range []int{n, n + 1, n + 10} { 24 | for _, cas := range []int{1, 2} { 25 | for k := 0; k < 100; k++ { 26 | v := make([]float64, n) 27 | for i := range v { 28 | v[i] = math.NaN() 29 | } 30 | h := make([]float64, n*(n-1)*ldh) 31 | for i := range h { 32 | h[i] = math.NaN() 33 | } 34 | for i := 0; i < n; i++ { 35 | for j := 0; j < n; j++ { 36 | h[i*ldh+j] = rnd.NormFloat64() 37 | } 38 | } 39 | var sr1, sr2, si1, si2 float64 40 | if cas == 1 { 41 | sr1 = rnd.NormFloat64() 42 | sr2 = sr1 43 | si1 = rnd.NormFloat64() 44 | si2 = -si1 45 | } else { 46 | sr1 = rnd.NormFloat64() 47 | sr2 = rnd.NormFloat64() 48 | si1 = 0 49 | si2 = 0 50 | } 51 | impl.Dlaqr1(n, h, ldh, sr1, si1, sr2, si2, v) 52 | 53 | // Matrix H - s1*I. 54 | h1 := make([]complex128, n*n) 55 | for i := 0; i < n; i++ { 56 | for j := 0; j < n; j++ { 57 | h1[i*n+j] = complex(h[i*ldh+j], 0) 58 | if i == j { 59 | h1[i*n+j] -= complex(sr1, si1) 60 | } 61 | } 62 | } 63 | // First column of H - s2*I. 64 | h2 := make([]complex128, n) 65 | for i := 0; i < n; i++ { 66 | h2[i] = complex(h[i*ldh], 0) 67 | } 68 | h2[0] -= complex(sr2, si2) 69 | 70 | wantv := make([]float64, n) 71 | // Multiply (H-s1*I)*(H-s2*I) to get a tentative 72 | // wantv. 73 | for i := 0; i < n; i++ { 74 | for j := 0; j < n; j++ { 75 | wantv[i] += real(h1[i*n+j] * h2[j]) 76 | } 77 | } 78 | // Get the unknown scale. 79 | scale := v[0] / wantv[0] 80 | // Compute the actual wantv. 81 | floats.Scale(scale, wantv) 82 | 83 | // The scale must be the same for all elements. 84 | if floats.Distance(wantv, v, math.Inf(1)) > 1e-13 { 85 | t.Errorf("n = %v, ldh = %v, case = %v: Unexpected value of v: got %v, want %v", n, ldh, cas, v, wantv) 86 | } 87 | } 88 | } 89 | } 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /testlapack/dlarfx.go: -------------------------------------------------------------------------------- 1 | // Copyright ©2016 The gonum Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package testlapack 6 | 7 | import ( 8 | "fmt" 9 | "math/rand" 10 | "testing" 11 | 12 | "github.com/gonum/blas" 13 | "github.com/gonum/blas/blas64" 14 | ) 15 | 16 | type Dlarfxer interface { 17 | Dlarfx(side blas.Side, m, n int, v []float64, tau float64, c []float64, ldc int, work []float64) 18 | } 19 | 20 | func DlarfxTest(t *testing.T, impl Dlarfxer) { 21 | rnd := rand.New(rand.NewSource(1)) 22 | for _, side := range []blas.Side{blas.Right, blas.Left} { 23 | for m := 1; m < 12; m++ { 24 | for n := 1; n < 12; n++ { 25 | for _, extra := range []int{0, 1, 11} { 26 | for cas := 0; cas < 10; cas++ { 27 | testDlarfx(t, impl, side, m, n, extra, rnd) 28 | } 29 | } 30 | } 31 | } 32 | } 33 | } 34 | 35 | func testDlarfx(t *testing.T, impl Dlarfxer, side blas.Side, m, n, extra int, rnd *rand.Rand) { 36 | const tol = 1e-13 37 | 38 | c := randomGeneral(m, n, n+extra, rnd) 39 | cWant := randomGeneral(m, n, n+extra, rnd) 40 | tau := rnd.NormFloat64() 41 | 42 | var ( 43 | v []float64 44 | h blas64.General 45 | ) 46 | if side == blas.Left { 47 | v = randomSlice(m, rnd) 48 | h = eye(m, m+extra) 49 | } else { 50 | v = randomSlice(n, rnd) 51 | h = eye(n, n+extra) 52 | } 53 | blas64.Ger(-tau, blas64.Vector{Inc: 1, Data: v}, blas64.Vector{Inc: 1, Data: v}, h) 54 | if side == blas.Left { 55 | blas64.Gemm(blas.NoTrans, blas.NoTrans, 1, h, c, 0, cWant) 56 | } else { 57 | blas64.Gemm(blas.NoTrans, blas.NoTrans, 1, c, h, 0, cWant) 58 | } 59 | 60 | var work []float64 61 | if h.Rows > 10 { 62 | // Allocate work only if H has order > 10. 63 | if side == blas.Left { 64 | work = make([]float64, n) 65 | } else { 66 | work = make([]float64, m) 67 | } 68 | } 69 | 70 | impl.Dlarfx(side, m, n, v, tau, c.Data, c.Stride, work) 71 | 72 | prefix := fmt.Sprintf("Case side=%v, m=%v, n=%v, extra=%v", side, m, n, extra) 73 | 74 | // Check any invalid modifications of c. 75 | if !generalOutsideAllNaN(c) { 76 | t.Errorf("%v: out-of-range write to C\n%v", prefix, c.Data) 77 | } 78 | 79 | if !equalApproxGeneral(c, cWant, tol) { 80 | t.Errorf("%v: unexpected C\n%v", prefix, c.Data) 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /testlapack/dlartg.go: -------------------------------------------------------------------------------- 1 | // Copyright ©2015 The gonum Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package testlapack 6 | 7 | import ( 8 | "math" 9 | "math/rand" 10 | "testing" 11 | 12 | "github.com/gonum/floats" 13 | ) 14 | 15 | type Dlartger interface { 16 | Dlartg(f, g float64) (cs, sn, r float64) 17 | } 18 | 19 | func DlartgTest(t *testing.T, impl Dlartger) { 20 | const tol = 1e-14 21 | // safmn2 and safmx2 are copied from native.Dlartg. 22 | safmn2 := math.Pow(dlamchB, math.Trunc(math.Log(dlamchS/dlamchE)/math.Log(dlamchB)/2)) 23 | safmx2 := 1 / safmn2 24 | rnd := rand.New(rand.NewSource(1)) 25 | for i := 0; i < 1000; i++ { 26 | var f float64 27 | var fHuge bool 28 | switch rnd.Intn(3) { 29 | case 0: 30 | // Huge f. 31 | fHuge = true 32 | f = math.Pow(10, 10-20*rnd.Float64()) * safmx2 33 | case 1: 34 | // Tiny f. 35 | f = math.Pow(10, 10-20*rnd.Float64()) * safmn2 36 | default: 37 | f = rnd.NormFloat64() 38 | } 39 | if rnd.Intn(2) == 0 { 40 | f *= -1 41 | } 42 | 43 | var g float64 44 | var gHuge bool 45 | switch rnd.Intn(3) { 46 | case 0: 47 | // Huge g. 48 | gHuge = true 49 | g = math.Pow(10, 10-20*rnd.Float64()) * safmx2 50 | case 1: 51 | // Tiny g. 52 | g = math.Pow(10, 10-20*rnd.Float64()) * safmn2 53 | default: 54 | g = rnd.NormFloat64() 55 | } 56 | if rnd.Intn(2) == 0 { 57 | g *= -1 58 | } 59 | 60 | cs, sn, r := impl.Dlartg(f, g) 61 | 62 | rWant := cs*f + sn*g 63 | if !floats.EqualWithinAbsOrRel(math.Abs(rWant), math.Abs(r), tol, tol) { 64 | t.Errorf("Case f=%v,g=%v: unexpected r. Want %v, got %v", f, g, rWant, r) 65 | } 66 | oneTest := cs*cs + sn*sn 67 | if math.Abs(oneTest-1) > tol { 68 | t.Errorf("Case f=%v,g=%v: expected cs^2+sn^2==1, got %v", f, g, oneTest) 69 | } 70 | if !fHuge && !gHuge { 71 | zeroTest := -sn*f + cs*g 72 | if math.Abs(zeroTest) > tol { 73 | t.Errorf("Case f=%v,g=%v: expected zero, got %v", f, g, zeroTest) 74 | } 75 | } 76 | if math.Abs(f) > math.Abs(g) && cs < 0 { 77 | t.Errorf("Case f=%v,g=%v: unexpected negative cs %v", f, g, cs) 78 | } 79 | } 80 | for i := 0; i < 100; i++ { 81 | cs, sn, _ := impl.Dlartg(rnd.NormFloat64(), 0) 82 | if cs != 1 { 83 | t.Errorf("Unexpected cs for g=0. Want 1, got %v", cs) 84 | } 85 | if sn != 0 { 86 | t.Errorf("Unexpected sn for g=0. Want 0, got %v", sn) 87 | } 88 | } 89 | for i := 0; i < 100; i++ { 90 | cs, sn, _ := impl.Dlartg(0, rnd.NormFloat64()) 91 | if cs != 0 { 92 | t.Errorf("Unexpected cs for f=0. Want 0, got %v", cs) 93 | } 94 | if sn != 1 { 95 | t.Errorf("Unexpected sn for f=0. Want 1, got %v", sn) 96 | } 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /testlapack/dlas2.go: -------------------------------------------------------------------------------- 1 | // Copyright ©2015 The gonum Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package testlapack 6 | 7 | import ( 8 | "math" 9 | "testing" 10 | ) 11 | 12 | type Dlas2er interface { 13 | Dlas2(f, g, h float64) (min, max float64) 14 | } 15 | 16 | func Dlas2Test(t *testing.T, impl Dlas2er) { 17 | for i, test := range []struct { 18 | f, g, h, ssmin, ssmax float64 19 | }{ 20 | // Singular values computed from Octave. 21 | {10, 30, 12, 3.567778859365365, 33.634371616111189}, 22 | {10, 30, -12, 3.567778859365365, 33.634371616111189}, 23 | {2, 30, -12, 0.741557056404952, 32.364333658088754}, 24 | {-2, 5, 12, 1.842864429909778, 13.023204317408728}, 25 | } { 26 | ssmin, ssmax := impl.Dlas2(test.f, test.g, test.h) 27 | if math.Abs(ssmin-test.ssmin) > 1e-12 { 28 | t.Errorf("Case %d, minimal singular value mismatch. Want %v, got %v", i, test.ssmin, ssmin) 29 | } 30 | if math.Abs(ssmax-test.ssmax) > 1e-12 { 31 | t.Errorf("Case %d, minimal singular value mismatch. Want %v, got %v", i, test.ssmin, ssmin) 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /testlapack/dlaset.go: -------------------------------------------------------------------------------- 1 | // Copyright ©2015 The gonum Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package testlapack 6 | 7 | import ( 8 | "fmt" 9 | "math/rand" 10 | "testing" 11 | 12 | "github.com/gonum/blas" 13 | ) 14 | 15 | type Dlaseter interface { 16 | Dlaset(uplo blas.Uplo, m, n int, alpha, beta float64, a []float64, lda int) 17 | } 18 | 19 | func DlasetTest(t *testing.T, impl Dlaseter) { 20 | rnd := rand.New(rand.NewSource(1)) 21 | for ti, test := range []struct { 22 | m, n int 23 | }{ 24 | {0, 0}, 25 | {1, 1}, 26 | {1, 10}, 27 | {10, 1}, 28 | {2, 2}, 29 | {2, 10}, 30 | {10, 2}, 31 | {11, 11}, 32 | {11, 100}, 33 | {100, 11}, 34 | } { 35 | m := test.m 36 | n := test.n 37 | for _, uplo := range []blas.Uplo{blas.Upper, blas.Lower, blas.All} { 38 | for _, extra := range []int{0, 10} { 39 | a := randomGeneral(m, n, n+extra, rnd) 40 | alpha := 1.0 41 | beta := 2.0 42 | 43 | impl.Dlaset(uplo, m, n, alpha, beta, a.Data, a.Stride) 44 | 45 | prefix := fmt.Sprintf("Case #%v: m=%v,n=%v,uplo=%v,extra=%v", 46 | ti, m, n, uplo, extra) 47 | if !generalOutsideAllNaN(a) { 48 | t.Errorf("%v: out-of-range write to A", prefix) 49 | } 50 | for i := 0; i < min(m, n); i++ { 51 | if a.Data[i*a.Stride+i] != beta { 52 | t.Errorf("%v: unexpected diagonal of A") 53 | } 54 | } 55 | if uplo == blas.Upper || uplo == blas.All { 56 | for i := 0; i < m; i++ { 57 | for j := i + 1; j < n; j++ { 58 | if a.Data[i*a.Stride+j] != alpha { 59 | t.Errorf("%v: unexpected upper triangle of A") 60 | } 61 | } 62 | } 63 | } 64 | if uplo == blas.Lower || uplo == blas.All { 65 | for i := 1; i < m; i++ { 66 | for j := 0; j < min(i, n); j++ { 67 | if a.Data[i*a.Stride+j] != alpha { 68 | t.Errorf("%v: unexpected lower triangle of A") 69 | } 70 | } 71 | } 72 | } 73 | } 74 | } 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /testlapack/dlasq1.go: -------------------------------------------------------------------------------- 1 | // Copyright ©2015 The gonum Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package testlapack 6 | 7 | import ( 8 | "fmt" 9 | "math" 10 | "math/rand" 11 | "testing" 12 | 13 | "github.com/gonum/blas" 14 | "github.com/gonum/blas/blas64" 15 | ) 16 | 17 | func printDlasq1FortranInput(d, e, work []float64, n int) { 18 | printFortranArray(d, "d") 19 | printFortranArray(e, "e") 20 | printFortranArray(work, "work") 21 | fmt.Println("n = ", n) 22 | fmt.Println("info = 0") 23 | } 24 | 25 | type Dlasq1er interface { 26 | Dlasq1(n int, d, e, work []float64) int 27 | Dgetrfer 28 | } 29 | 30 | func Dlasq1Test(t *testing.T, impl Dlasq1er) { 31 | rnd := rand.New(rand.NewSource(1)) 32 | bi := blas64.Implementation() 33 | // TODO(btracey): Increase the size of this test when we have a more numerically 34 | // stable way to test the singular values. 35 | for _, n := range []int{1, 2, 5, 8} { 36 | work := make([]float64, 4*n) 37 | d := make([]float64, n) 38 | e := make([]float64, n-1) 39 | for cas := 0; cas < 1; cas++ { 40 | for i := range work { 41 | work[i] = rnd.Float64() 42 | } 43 | for i := range d { 44 | d[i] = rnd.NormFloat64() + 10 45 | } 46 | for i := range e { 47 | e[i] = rnd.NormFloat64() 48 | } 49 | ldm := n 50 | m := make([]float64, n*ldm) 51 | // Set up the matrix 52 | for i := 0; i < n; i++ { 53 | m[i*ldm+i] = d[i] 54 | if i != n-1 { 55 | m[(i+1)*ldm+i] = e[i] 56 | } 57 | } 58 | 59 | ldmm := n 60 | mm := make([]float64, n*ldmm) 61 | bi.Dgemm(blas.Trans, blas.NoTrans, n, n, n, 1, m, ldm, m, ldm, 0, mm, ldmm) 62 | 63 | impl.Dlasq1(n, d, e, work) 64 | 65 | // Check that they are singular values. The 66 | // singular values are the square roots of the 67 | // eigenvalues of X^T * X 68 | mmCopy := make([]float64, len(mm)) 69 | copy(mmCopy, mm) 70 | ipiv := make([]int, n) 71 | for elem, sv := range d[0:n] { 72 | copy(mm, mmCopy) 73 | lambda := sv * sv 74 | for i := 0; i < n; i++ { 75 | mm[i*ldm+i] -= lambda 76 | } 77 | 78 | // Compute LU. 79 | ok := impl.Dgetrf(n, n, mm, ldmm, ipiv) 80 | if !ok { 81 | // Definitely singular. 82 | continue 83 | } 84 | // Compute determinant 85 | var logdet float64 86 | for i := 0; i < n; i++ { 87 | v := mm[i*ldm+i] 88 | logdet += math.Log(math.Abs(v)) 89 | } 90 | if math.Exp(logdet) > 2 { 91 | t.Errorf("Incorrect singular value. n = %d, cas = %d, elem = %d, det = %v", n, cas, elem, math.Exp(logdet)) 92 | } 93 | } 94 | } 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /testlapack/dlasrt.go: -------------------------------------------------------------------------------- 1 | // Copyright ©2016 The gonum Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package testlapack 6 | 7 | import ( 8 | "testing" 9 | 10 | "github.com/gonum/floats" 11 | "github.com/gonum/lapack" 12 | ) 13 | 14 | type Dlasrter interface { 15 | Dlasrt(s lapack.Sort, n int, d []float64) 16 | } 17 | 18 | func DlasrtTest(t *testing.T, impl Dlasrter) { 19 | for ti, test := range []struct { 20 | data []float64 21 | wantInc []float64 22 | wantDec []float64 23 | }{ 24 | { 25 | data: nil, 26 | wantInc: nil, 27 | wantDec: nil, 28 | }, 29 | { 30 | data: []float64{}, 31 | wantInc: []float64{}, 32 | wantDec: []float64{}, 33 | }, 34 | { 35 | data: []float64{1}, 36 | wantInc: []float64{1}, 37 | wantDec: []float64{1}, 38 | }, 39 | { 40 | data: []float64{1, 2}, 41 | wantInc: []float64{1, 2}, 42 | wantDec: []float64{2, 1}, 43 | }, 44 | { 45 | data: []float64{1, 2, -3}, 46 | wantInc: []float64{-3, 1, 2}, 47 | wantDec: []float64{2, 1, -3}, 48 | }, 49 | { 50 | data: []float64{-5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5}, 51 | wantInc: []float64{-5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5}, 52 | wantDec: []float64{5, 4, 3, 2, 1, 0, -1, -2, -3, -4, -5}, 53 | }, 54 | { 55 | data: []float64{5, 4, 3, 2, 1, 0, -1, -2, -3, -4, -5}, 56 | wantInc: []float64{-5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5}, 57 | wantDec: []float64{5, 4, 3, 2, 1, 0, -1, -2, -3, -4, -5}, 58 | }, 59 | { 60 | data: []float64{-2, 4, -1, 2, -4, 0, 3, 5, -5, 1, -3}, 61 | wantInc: []float64{-5, -4, -3, -2, -1, 0, 1, 2, 3, 4, 5}, 62 | wantDec: []float64{5, 4, 3, 2, 1, 0, -1, -2, -3, -4, -5}, 63 | }, 64 | } { 65 | n := len(test.data) 66 | ds := make([]float64, n) 67 | 68 | copy(ds, test.data) 69 | impl.Dlasrt(lapack.SortIncreasing, n, ds) 70 | if !floats.Equal(ds, test.wantInc) { 71 | t.Errorf("Case #%v: unexpected result of SortIncreasing", ti) 72 | } 73 | 74 | copy(ds, test.data) 75 | impl.Dlasrt(lapack.SortDecreasing, n, ds) 76 | if !floats.Equal(ds, test.wantDec) { 77 | t.Errorf("Case #%v: unexpected result of SortIncreasing", ti) 78 | } 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /testlapack/dlasv2.go: -------------------------------------------------------------------------------- 1 | // Copyright ©2015 The gonum Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package testlapack 6 | 7 | import ( 8 | "math/rand" 9 | "testing" 10 | 11 | "github.com/gonum/floats" 12 | ) 13 | 14 | type Dlasv2er interface { 15 | Dlasv2(f, g, h float64) (ssmin, ssmax, snr, csr, snl, csl float64) 16 | } 17 | 18 | func Dlasv2Test(t *testing.T, impl Dlasv2er) { 19 | rnd := rand.New(rand.NewSource(1)) 20 | for i := 0; i < 100; i++ { 21 | f := rnd.NormFloat64() 22 | g := rnd.NormFloat64() 23 | h := rnd.NormFloat64() 24 | 25 | ssmin, ssmax, snr, csr, snl, csl := impl.Dlasv2(f, g, h) 26 | 27 | // tmp = 28 | // [ csl snl] [f g] 29 | // [-snl csl] [0 h] 30 | tmp11 := csl * f 31 | tmp12 := csl*g + snl*h 32 | tmp21 := -snl * f 33 | tmp22 := -snl*g + csl*h 34 | // lhs = 35 | // [tmp11 tmp12] [csr -snr] 36 | // [tmp21 tmp22] [snr csr] 37 | ans11 := tmp11*csr + tmp12*snr 38 | ans12 := tmp11*-snr + tmp12*csr 39 | ans21 := tmp21*csr + tmp22*snr 40 | ans22 := tmp21*-snr + tmp22*csr 41 | 42 | lhs := []float64{ans11, ans12, ans21, ans22} 43 | rhs := []float64{ssmax, 0, 0, ssmin} 44 | if !floats.EqualApprox(rhs, lhs, 1e-12) { 45 | t.Errorf("SVD mismatch. f = %v, g = %v, h = %v.\nLHS: %v\nRHS: %v", f, g, h, lhs, rhs) 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /testlapack/dlaswp.go: -------------------------------------------------------------------------------- 1 | // Copyright ©2016 The gonum Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package testlapack 6 | 7 | import ( 8 | "fmt" 9 | "testing" 10 | 11 | "github.com/gonum/blas/blas64" 12 | ) 13 | 14 | type Dlaswper interface { 15 | Dlaswp(n int, a []float64, lda, k1, k2 int, ipiv []int, incX int) 16 | } 17 | 18 | func DlaswpTest(t *testing.T, impl Dlaswper) { 19 | for ti, test := range []struct { 20 | k1, k2 int 21 | ipiv []int 22 | incX int 23 | 24 | want blas64.General 25 | }{ 26 | { 27 | k1: 0, 28 | k2: 2, 29 | ipiv: []int{0, 1, 2}, 30 | incX: 1, 31 | want: blas64.General{ 32 | Rows: 4, 33 | Cols: 3, 34 | Stride: 3, 35 | Data: []float64{ 36 | 1, 2, 3, 37 | 4, 5, 6, 38 | 7, 8, 9, 39 | 10, 11, 12, 40 | }, 41 | }, 42 | }, 43 | { 44 | k1: 0, 45 | k2: 2, 46 | ipiv: []int{0, 1, 2}, 47 | incX: -1, 48 | want: blas64.General{ 49 | Rows: 4, 50 | Cols: 3, 51 | Stride: 3, 52 | Data: []float64{ 53 | 1, 2, 3, 54 | 4, 5, 6, 55 | 7, 8, 9, 56 | 10, 11, 12, 57 | }, 58 | }, 59 | }, 60 | { 61 | k1: 0, 62 | k2: 2, 63 | ipiv: []int{1, 2, 3}, 64 | incX: 1, 65 | want: blas64.General{ 66 | Rows: 5, 67 | Cols: 3, 68 | Stride: 3, 69 | Data: []float64{ 70 | 4, 5, 6, 71 | 7, 8, 9, 72 | 10, 11, 12, 73 | 1, 2, 3, 74 | 13, 14, 15, 75 | }, 76 | }, 77 | }, 78 | { 79 | k1: 0, 80 | k2: 2, 81 | ipiv: []int{1, 2, 3}, 82 | incX: -1, 83 | want: blas64.General{ 84 | Rows: 5, 85 | Cols: 3, 86 | Stride: 3, 87 | Data: []float64{ 88 | 10, 11, 12, 89 | 1, 2, 3, 90 | 4, 5, 6, 91 | 7, 8, 9, 92 | 13, 14, 15, 93 | }, 94 | }, 95 | }, 96 | } { 97 | m := test.want.Rows 98 | n := test.want.Cols 99 | k1 := test.k1 100 | k2 := test.k2 101 | if len(test.ipiv) != k2+1 { 102 | panic("bad length of ipiv") 103 | } 104 | incX := test.incX 105 | for _, extra := range []int{0, 11} { 106 | a := zeros(m, n, n+extra) 107 | c := 1 108 | for i := 0; i < m; i++ { 109 | for j := 0; j < n; j++ { 110 | a.Data[i*a.Stride+j] = float64(c) 111 | c++ 112 | } 113 | } 114 | 115 | ipiv := make([]int, len(test.ipiv)) 116 | copy(ipiv, test.ipiv) 117 | 118 | impl.Dlaswp(n, a.Data, a.Stride, k1, k2, ipiv, incX) 119 | 120 | prefix := fmt.Sprintf("Case %v (m=%v,n=%v,k1=%v,k2=%v,extra=%v)", ti, m, n, k1, k2, extra) 121 | if !generalOutsideAllNaN(a) { 122 | t.Errorf("%v: out-of-range write to A", prefix) 123 | } 124 | 125 | if !equalApproxGeneral(a, test.want, 0) { 126 | t.Errorf("%v: unexpected A\n%v\n%v", prefix, a, test.want) 127 | } 128 | } 129 | } 130 | } 131 | -------------------------------------------------------------------------------- /testlapack/dorg2l.go: -------------------------------------------------------------------------------- 1 | // Copyright ©2016 The gonum Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package testlapack 6 | 7 | import ( 8 | "math" 9 | "math/rand" 10 | "testing" 11 | 12 | "github.com/gonum/blas/blas64" 13 | ) 14 | 15 | type Dorg2ler interface { 16 | Dorg2l(m, n, k int, a []float64, lda int, tau, work []float64) 17 | Dgeql2er 18 | } 19 | 20 | func Dorg2lTest(t *testing.T, impl Dorg2ler) { 21 | rnd := rand.New(rand.NewSource(1)) 22 | for _, test := range []struct { 23 | m, n, k, lda int 24 | }{ 25 | {5, 4, 3, 0}, 26 | {5, 4, 4, 0}, 27 | {3, 3, 2, 0}, 28 | {5, 5, 5, 0}, 29 | } { 30 | m := test.m 31 | n := test.n 32 | k := test.k 33 | lda := test.lda 34 | if lda == 0 { 35 | lda = n 36 | } 37 | 38 | a := make([]float64, m*lda) 39 | for i := range a { 40 | a[i] = rnd.NormFloat64() 41 | } 42 | tau := nanSlice(max(m, n)) 43 | work := make([]float64, n) 44 | impl.Dgeql2(m, n, a, lda, tau, work) 45 | 46 | aCopy := make([]float64, len(a)) 47 | copy(aCopy, a) 48 | impl.Dorg2l(m, n, k, a, lda, tau[n-k:], work) 49 | if !hasOrthonormalColumns(m, n, a, lda) { 50 | t.Errorf("Q is not orthonormal. m = %v, n = %v, k = %v", m, n, k) 51 | } 52 | } 53 | } 54 | 55 | // hasOrthornormalColumns checks that the columns of a are orthonormal. 56 | func hasOrthonormalColumns(m, n int, a []float64, lda int) bool { 57 | for i := 0; i < n; i++ { 58 | for j := i; j < n; j++ { 59 | dot := blas64.Dot(m, 60 | blas64.Vector{Inc: lda, Data: a[i:]}, 61 | blas64.Vector{Inc: lda, Data: a[j:]}, 62 | ) 63 | if i == j { 64 | if math.Abs(dot-1) > 1e-10 { 65 | return false 66 | } 67 | } else { 68 | if math.Abs(dot) > 1e-10 { 69 | return false 70 | } 71 | } 72 | } 73 | } 74 | return true 75 | } 76 | -------------------------------------------------------------------------------- /testlapack/dorg2r.go: -------------------------------------------------------------------------------- 1 | // Copyright ©2015 The gonum Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package testlapack 6 | 7 | import ( 8 | "fmt" 9 | "math/rand" 10 | "testing" 11 | 12 | "github.com/gonum/floats" 13 | ) 14 | 15 | type Dorg2rer interface { 16 | Dgeqrfer 17 | Dorg2r(m, n, k int, a []float64, lda int, tau []float64, work []float64) 18 | } 19 | 20 | func Dorg2rTest(t *testing.T, impl Dorg2rer) { 21 | rnd := rand.New(rand.NewSource(1)) 22 | for _, test := range []struct { 23 | m, n, k, lda int 24 | }{ 25 | {3, 3, 0, 0}, 26 | {4, 3, 0, 0}, 27 | {3, 3, 2, 0}, 28 | {4, 3, 2, 0}, 29 | 30 | {5, 5, 0, 20}, 31 | {5, 5, 3, 20}, 32 | {10, 5, 0, 20}, 33 | {10, 5, 2, 20}, 34 | } { 35 | m := test.m 36 | n := test.n 37 | lda := test.lda 38 | if lda == 0 { 39 | lda = test.n 40 | } 41 | a := make([]float64, m*lda) 42 | for i := range a { 43 | a[i] = rnd.NormFloat64() 44 | } 45 | k := min(m, n) 46 | tau := make([]float64, k) 47 | work := make([]float64, 1) 48 | impl.Dgeqrf(m, n, a, lda, tau, work, -1) 49 | work = make([]float64, int(work[0])) 50 | impl.Dgeqrf(m, n, a, lda, tau, work, len(work)) 51 | 52 | k = test.k 53 | if k == 0 { 54 | k = n 55 | } 56 | q := constructQK("QR", m, n, k, a, lda, tau) 57 | 58 | impl.Dorg2r(m, n, k, a, lda, tau, work) 59 | 60 | // Check that the first n columns match. 61 | same := true 62 | for i := 0; i < m; i++ { 63 | for j := 0; j < n; j++ { 64 | if !floats.EqualWithinAbsOrRel(q.Data[i*q.Stride+j], a[i*lda+j], 1e-12, 1e-12) { 65 | same = false 66 | break 67 | } 68 | } 69 | } 70 | if !same { 71 | fmt.Println() 72 | fmt.Println("a =") 73 | printRowise(a, m, n, lda, false) 74 | fmt.Println("q =") 75 | printRowise(q.Data, q.Rows, q.Cols, q.Stride, false) 76 | t.Errorf("Q mismatch") 77 | } 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /testlapack/dorgl2.go: -------------------------------------------------------------------------------- 1 | // Copyright ©2015 The gonum Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package testlapack 6 | 7 | import ( 8 | "math/rand" 9 | "testing" 10 | 11 | "github.com/gonum/floats" 12 | ) 13 | 14 | type Dorgl2er interface { 15 | Dgelqfer 16 | Dorgl2(m, n, k int, a []float64, lda int, tau []float64, work []float64) 17 | } 18 | 19 | func Dorgl2Test(t *testing.T, impl Dorgl2er) { 20 | rnd := rand.New(rand.NewSource(1)) 21 | for _, test := range []struct { 22 | m, n, lda int 23 | }{ 24 | {3, 3, 0}, 25 | {3, 4, 0}, 26 | 27 | {5, 5, 20}, 28 | {5, 10, 20}, 29 | } { 30 | m := test.m 31 | n := test.n 32 | lda := test.lda 33 | if lda == 0 { 34 | lda = test.n 35 | } 36 | a := make([]float64, m*lda) 37 | for i := range a { 38 | a[i] = rnd.NormFloat64() 39 | } 40 | k := min(m, n) 41 | tau := make([]float64, k) 42 | work := make([]float64, 1) 43 | impl.Dgelqf(m, n, a, lda, tau, work, -1) 44 | work = make([]float64, int(work[0])) 45 | impl.Dgelqf(m, n, a, lda, tau, work, len(work)) 46 | 47 | q := constructQ("LQ", m, n, a, lda, tau) 48 | 49 | impl.Dorgl2(m, n, k, a, lda, tau, work) 50 | 51 | // Check that the first m rows match. 52 | same := true 53 | for i := 0; i < m; i++ { 54 | for j := 0; j < n; j++ { 55 | if !floats.EqualWithinAbsOrRel(q.Data[i*q.Stride+j], a[i*lda+j], 1e-12, 1e-12) { 56 | same = false 57 | break 58 | } 59 | } 60 | } 61 | if !same { 62 | t.Errorf("Q mismatch") 63 | } 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /testlapack/dorglq.go: -------------------------------------------------------------------------------- 1 | // Copyright ©2015 The gonum Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package testlapack 6 | 7 | import ( 8 | "math" 9 | "math/rand" 10 | "testing" 11 | 12 | "github.com/gonum/floats" 13 | ) 14 | 15 | type Dorglqer interface { 16 | Dorgl2er 17 | Dorglq(m, n, k int, a []float64, lda int, tau, work []float64, lwork int) 18 | } 19 | 20 | func DorglqTest(t *testing.T, impl Dorglqer) { 21 | rnd := rand.New(rand.NewSource(1)) 22 | // TODO(btracey): Base tests off of nb and nx. 23 | for _, test := range []struct{ m, n, k, lda int }{ 24 | {10, 10, 10, 0}, 25 | {10, 10, 10, 20}, 26 | {10, 30, 10, 0}, 27 | {20, 30, 10, 0}, 28 | 29 | {100, 100, 100, 0}, 30 | {100, 100, 50, 0}, 31 | {100, 130, 100, 0}, 32 | {100, 130, 50, 0}, 33 | {100, 100, 100, 150}, 34 | {100, 100, 50, 150}, 35 | {100, 130, 100, 150}, 36 | {100, 130, 50, 150}, 37 | 38 | {200, 200, 200, 0}, 39 | {200, 200, 150, 0}, 40 | {200, 230, 200, 0}, 41 | {200, 230, 150, 0}, 42 | {200, 200, 200, 250}, 43 | {200, 200, 150, 250}, 44 | {200, 230, 200, 250}, 45 | {200, 230, 150, 250}, 46 | } { 47 | m := test.m 48 | n := test.n 49 | k := test.k 50 | lda := test.lda 51 | if lda == 0 { 52 | lda = n 53 | } 54 | a := make([]float64, m*lda) 55 | for i := range a { 56 | a[i] = rnd.Float64() 57 | } 58 | work := make([]float64, 1) 59 | tau := make([]float64, m) 60 | for i := range tau { 61 | tau[i] = math.NaN() 62 | } 63 | // Compute LQ factorization. 64 | impl.Dgelqf(m, n, a, lda, tau, work, -1) 65 | work = make([]float64, int(work[0])) 66 | impl.Dgelqf(m, n, a, lda, tau, work, len(work)) 67 | 68 | aUnblocked := make([]float64, len(a)) 69 | copy(aUnblocked, a) 70 | for i := range work { 71 | work[i] = math.NaN() 72 | } 73 | impl.Dorgl2(m, n, k, aUnblocked, lda, tau, work) 74 | // make sure work isn't used before initialized 75 | for i := range work { 76 | work[i] = math.NaN() 77 | } 78 | impl.Dorglq(m, n, k, a, lda, tau, work, len(work)) 79 | if !floats.EqualApprox(a, aUnblocked, 1e-10) { 80 | t.Errorf("Q Mismatch. m = %d, n = %d, k = %d, lda = %d", m, n, k, lda) 81 | } 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /testlapack/dorgqr.go: -------------------------------------------------------------------------------- 1 | // Copyright ©2015 The gonum Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package testlapack 6 | 7 | import ( 8 | "math" 9 | "math/rand" 10 | "testing" 11 | 12 | "github.com/gonum/floats" 13 | ) 14 | 15 | type Dorgqrer interface { 16 | Dorg2rer 17 | Dorgqr(m, n, k int, a []float64, lda int, tau, work []float64, lwork int) 18 | } 19 | 20 | func DorgqrTest(t *testing.T, impl Dorgqrer) { 21 | rnd := rand.New(rand.NewSource(1)) 22 | // TODO(btracey): Base tests off of nb and nx. 23 | for _, test := range []struct{ m, n, k, lda int }{ 24 | {10, 10, 10, 0}, 25 | {10, 10, 10, 20}, 26 | {30, 10, 10, 0}, 27 | {30, 20, 10, 20}, 28 | 29 | {100, 100, 100, 0}, 30 | {100, 100, 50, 0}, 31 | {130, 100, 100, 0}, 32 | {130, 100, 50, 0}, 33 | {100, 100, 100, 150}, 34 | {100, 100, 50, 150}, 35 | {130, 100, 100, 150}, 36 | {130, 100, 50, 150}, 37 | 38 | {200, 200, 200, 0}, 39 | {200, 200, 150, 0}, 40 | {230, 200, 200, 0}, 41 | {230, 200, 150, 0}, 42 | {200, 200, 200, 250}, 43 | {200, 200, 150, 250}, 44 | {230, 200, 200, 250}, 45 | {230, 200, 150, 250}, 46 | } { 47 | m := test.m 48 | n := test.n 49 | k := test.k 50 | lda := test.lda 51 | if lda == 0 { 52 | lda = n 53 | } 54 | a := make([]float64, m*lda) 55 | for i := range a { 56 | a[i] = rnd.Float64() 57 | } 58 | work := make([]float64, 1) 59 | tau := make([]float64, n) 60 | for i := range tau { 61 | tau[i] = math.NaN() 62 | } 63 | // Compute QR factorization. 64 | impl.Dgeqrf(m, n, a, lda, tau, work, -1) 65 | work = make([]float64, int(work[0])) 66 | impl.Dgeqrf(m, n, a, lda, tau, work, len(work)) 67 | 68 | aUnblocked := make([]float64, len(a)) 69 | copy(aUnblocked, a) 70 | for i := range work { 71 | work[i] = math.NaN() 72 | } 73 | impl.Dorg2r(m, n, k, aUnblocked, lda, tau, work) 74 | // make sure work isn't used before initialized 75 | for i := range work { 76 | work[i] = math.NaN() 77 | } 78 | impl.Dorgqr(m, n, k, a, lda, tau, work, len(work)) 79 | if !floats.EqualApprox(a, aUnblocked, 1e-10) { 80 | t.Errorf("Q Mismatch. m = %d, n = %d, k = %d, lda = %d", m, n, k, lda) 81 | } 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /testlapack/drscl.go: -------------------------------------------------------------------------------- 1 | // Copyright ©2015 The gonum Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package testlapack 6 | 7 | import ( 8 | "math" 9 | "testing" 10 | 11 | "github.com/gonum/floats" 12 | ) 13 | 14 | type Drscler interface { 15 | Drscl(n int, a float64, x []float64, incX int) 16 | } 17 | 18 | func DrsclTest(t *testing.T, impl Drscler) { 19 | for _, test := range []struct { 20 | x []float64 21 | a float64 22 | }{ 23 | { 24 | x: []float64{1, 2, 3, 4, 5}, 25 | a: 4, 26 | }, 27 | { 28 | x: []float64{1, 2, 3, 4, 5}, 29 | a: math.MaxFloat64, 30 | }, 31 | { 32 | x: []float64{1, 2, 3, 4, 5}, 33 | a: 1e-307, 34 | }, 35 | } { 36 | xcopy := make([]float64, len(test.x)) 37 | copy(xcopy, test.x) 38 | 39 | // Cannot test the scaling directly because of floating point scaling issues 40 | // (the purpose of Drscl). Instead, check that scaling and scaling back 41 | // yeilds approximately x. If overflow or underflow occurs then the scaling 42 | // won't match. 43 | impl.Drscl(len(test.x), test.a, xcopy, 1) 44 | if floats.Equal(xcopy, test.x) { 45 | t.Errorf("x unchanged during call to drscl. a = %v, x = %v.", test.a, test.x) 46 | } 47 | impl.Drscl(len(test.x), 1/test.a, xcopy, 1) 48 | if !floats.EqualApprox(xcopy, test.x, 1e-14) { 49 | t.Errorf("x not equal after scaling and unscaling. a = %v, x = %v.", test.a, test.x) 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /testlapack/dtrtri.go: -------------------------------------------------------------------------------- 1 | // Copyright ©2015 The gonum Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package testlapack 6 | 7 | import ( 8 | "math" 9 | "math/rand" 10 | "testing" 11 | 12 | "github.com/gonum/blas" 13 | "github.com/gonum/blas/blas64" 14 | ) 15 | 16 | type Dtrtrier interface { 17 | Dtrconer 18 | Dtrtri(uplo blas.Uplo, diag blas.Diag, n int, a []float64, lda int) bool 19 | } 20 | 21 | func DtrtriTest(t *testing.T, impl Dtrtrier) { 22 | const tol = 1e-6 23 | rnd := rand.New(rand.NewSource(1)) 24 | bi := blas64.Implementation() 25 | for _, uplo := range []blas.Uplo{blas.Upper, blas.Lower} { 26 | for _, diag := range []blas.Diag{blas.NonUnit, blas.Unit} { 27 | for _, test := range []struct { 28 | n, lda int 29 | }{ 30 | {3, 0}, 31 | {70, 0}, 32 | {200, 0}, 33 | {3, 5}, 34 | {70, 92}, 35 | {200, 205}, 36 | } { 37 | n := test.n 38 | lda := test.lda 39 | if lda == 0 { 40 | lda = n 41 | } 42 | a := make([]float64, n*lda) 43 | for i := range a { 44 | a[i] = rnd.Float64() + 1 // This keeps the matrices well conditioned. 45 | } 46 | aCopy := make([]float64, len(a)) 47 | copy(aCopy, a) 48 | impl.Dtrtri(uplo, diag, n, a, lda) 49 | if uplo == blas.Upper { 50 | for i := 1; i < n; i++ { 51 | for j := 0; j < i; j++ { 52 | aCopy[i*lda+j] = 0 53 | a[i*lda+j] = 0 54 | } 55 | } 56 | } else { 57 | for i := 0; i < n; i++ { 58 | for j := i + 1; j < n; j++ { 59 | aCopy[i*lda+j] = 0 60 | a[i*lda+j] = 0 61 | } 62 | } 63 | } 64 | if diag == blas.Unit { 65 | for i := 0; i < n; i++ { 66 | a[i*lda+i] = 1 67 | aCopy[i*lda+i] = 1 68 | } 69 | } 70 | ans := make([]float64, len(a)) 71 | bi.Dgemm(blas.NoTrans, blas.NoTrans, n, n, n, 1, a, lda, aCopy, lda, 0, ans, lda) 72 | iseye := true 73 | for i := 0; i < n; i++ { 74 | for j := 0; j < n; j++ { 75 | if i == j { 76 | if math.Abs(ans[i*lda+i]-1) > tol { 77 | iseye = false 78 | break 79 | } 80 | } else { 81 | if math.Abs(ans[i*lda+j]) > tol { 82 | iseye = false 83 | break 84 | } 85 | } 86 | } 87 | } 88 | if !iseye { 89 | t.Errorf("inv(A) * A != I. Upper = %v, unit = %v, n = %v, lda = %v", 90 | uplo == blas.Upper, diag == blas.Unit, n, lda) 91 | } 92 | } 93 | } 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /testlapack/fortran.go: -------------------------------------------------------------------------------- 1 | // Copyright ©2015 The gonum Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package testlapack 6 | 7 | import ( 8 | "fmt" 9 | "strings" 10 | ) 11 | 12 | // This file implements types for helping to convert to Fortran testing capabilities. 13 | 14 | // fortran64 is a float64 type that prints as a double precision constant in 15 | // Fortran format. 16 | type fortran64 float64 17 | 18 | func (f fortran64) String() string { 19 | // Replace exponent with D 20 | s := fmt.Sprintf("%0.16E", f) 21 | s = strings.Replace(s, "E", "D", 1) 22 | return s 23 | } 24 | 25 | // printFortranArray prints a Go slice as an array that can be copied into a 26 | // fortran script. 27 | func printFortranArray(z []float64, name string) { 28 | fmt.Printf("%s(1:%d) = (/%v, &\n", name, len(z), fortran64(z[0])) 29 | for i := 1; i < len(z)-1; i++ { 30 | fmt.Printf("%v, &\n", fortran64(z[i])) 31 | } 32 | fmt.Printf("%s/)\n", fortran64(z[len(z)-1])) 33 | } 34 | -------------------------------------------------------------------------------- /testlapack/iladlc.go: -------------------------------------------------------------------------------- 1 | // Copyright ©2015 The gonum Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package testlapack 6 | 7 | import "testing" 8 | 9 | type Iladlcer interface { 10 | Iladlc(m, n int, a []float64, lda int) int 11 | } 12 | 13 | func IladlcTest(t *testing.T, impl Iladlcer) { 14 | for i, test := range []struct { 15 | a []float64 16 | m, n, lda int 17 | ans int 18 | }{ 19 | { 20 | a: []float64{0, 0, 0, 0}, 21 | m: 1, 22 | n: 1, 23 | lda: 2, 24 | ans: -1, 25 | }, 26 | { 27 | a: []float64{0, 0, 0, 0}, 28 | m: 2, 29 | n: 2, 30 | lda: 2, 31 | ans: -1, 32 | }, 33 | { 34 | a: []float64{0, 0, 0, 0}, 35 | m: 4, 36 | n: 1, 37 | lda: 1, 38 | ans: -1, 39 | }, 40 | { 41 | a: []float64{0, 0, 0, 0}, 42 | m: 1, 43 | n: 4, 44 | lda: 4, 45 | ans: -1, 46 | }, 47 | { 48 | a: []float64{ 49 | 1, 2, 3, 4, 50 | 5, 6, 7, 8, 51 | }, 52 | m: 2, 53 | n: 4, 54 | lda: 4, 55 | ans: 3, 56 | }, 57 | { 58 | a: []float64{ 59 | 1, 2, 3, 0, 60 | 0, 0, 0, 0, 61 | }, 62 | m: 2, 63 | n: 4, 64 | lda: 4, 65 | ans: 2, 66 | }, 67 | { 68 | a: []float64{ 69 | 0, 0, 3, 4, 70 | 0, 0, 0, 0, 71 | }, 72 | m: 2, 73 | n: 2, 74 | lda: 4, 75 | ans: -1, 76 | }, 77 | } { 78 | ans := impl.Iladlc(test.m, test.n, test.a, test.lda) 79 | if ans != test.ans { 80 | t.Errorf("Column mismatch case %v. Want: %v, got: %v", i, test.ans, ans) 81 | } 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /testlapack/iladlr.go: -------------------------------------------------------------------------------- 1 | // Copyright ©2015 The gonum Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package testlapack 6 | 7 | import "testing" 8 | 9 | type Iladlrer interface { 10 | Iladlr(m, n int, a []float64, lda int) int 11 | } 12 | 13 | func IladlrTest(t *testing.T, impl Iladlrer) { 14 | for i, test := range []struct { 15 | a []float64 16 | m, n, lda int 17 | ans int 18 | }{ 19 | { 20 | a: []float64{0, 0, 0, 0}, 21 | m: 1, 22 | n: 1, 23 | lda: 2, 24 | ans: -1, 25 | }, 26 | { 27 | a: []float64{0, 0, 0, 0}, 28 | m: 2, 29 | n: 2, 30 | lda: 2, 31 | ans: -1, 32 | }, 33 | { 34 | a: []float64{0, 0, 0, 0}, 35 | m: 4, 36 | n: 1, 37 | lda: 1, 38 | ans: -1, 39 | }, 40 | { 41 | a: []float64{0, 0, 0, 0}, 42 | m: 1, 43 | n: 4, 44 | lda: 4, 45 | ans: -1, 46 | }, 47 | { 48 | a: []float64{ 49 | 1, 2, 3, 4, 50 | 5, 6, 7, 8, 51 | }, 52 | m: 2, 53 | n: 4, 54 | lda: 4, 55 | ans: 1, 56 | }, 57 | { 58 | a: []float64{ 59 | 1, 2, 3, 0, 60 | 0, 0, 0, 0, 61 | }, 62 | m: 2, 63 | n: 4, 64 | lda: 4, 65 | ans: 0, 66 | }, 67 | { 68 | a: []float64{ 69 | 0, 0, 3, 4, 70 | 0, 0, 0, 0, 71 | }, 72 | m: 2, 73 | n: 2, 74 | lda: 4, 75 | ans: -1, 76 | }, 77 | } { 78 | ans := impl.Iladlr(test.m, test.n, test.a, test.lda) 79 | if ans != test.ans { 80 | t.Errorf("Column mismatch case %v. Want: %v, got: %v", i, test.ans, ans) 81 | } 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /testlapack/matgen_test.go: -------------------------------------------------------------------------------- 1 | // Copyright ©2017 The gonum Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | package testlapack 6 | 7 | import ( 8 | "math" 9 | "math/rand" 10 | "testing" 11 | 12 | "github.com/gonum/blas/blas64" 13 | ) 14 | 15 | func TestDlagsy(t *testing.T) { 16 | const tol = 1e-14 17 | rnd := rand.New(rand.NewSource(1)) 18 | for _, n := range []int{0, 1, 2, 3, 4, 5, 10, 50} { 19 | for _, lda := range []int{0, 2*n + 1} { 20 | if lda == 0 { 21 | lda = max(1, n) 22 | } 23 | d := make([]float64, n) 24 | for i := range d { 25 | d[i] = 1 26 | } 27 | a := blas64.General{ 28 | Rows: n, 29 | Cols: n, 30 | Stride: lda, 31 | Data: nanSlice(n * lda), 32 | } 33 | work := make([]float64, a.Rows+a.Cols) 34 | 35 | Dlagsy(a.Rows, 0, d, a.Data, a.Stride, rnd, work) 36 | 37 | isIdentity := true 38 | identityLoop: 39 | for i := 0; i < n; i++ { 40 | for j := 0; j < n; j++ { 41 | aij := a.Data[i*a.Stride+j] 42 | if math.IsNaN(aij) { 43 | isIdentity = false 44 | } 45 | if i == j && math.Abs(aij-1) > tol { 46 | isIdentity = false 47 | } 48 | if i != j && math.Abs(aij) > tol { 49 | isIdentity = false 50 | } 51 | if !isIdentity { 52 | break identityLoop 53 | } 54 | } 55 | } 56 | if !isIdentity { 57 | t.Errorf("Case n=%v,lda=%v: unexpected result", n, lda) 58 | } 59 | } 60 | } 61 | } 62 | 63 | func TestDlagge(t *testing.T) { 64 | rnd := rand.New(rand.NewSource(1)) 65 | for _, n := range []int{0, 1, 2, 3, 4, 5, 10, 50} { 66 | for _, lda := range []int{0, 2*n + 1} { 67 | if lda == 0 { 68 | lda = max(1, n) 69 | } 70 | d := make([]float64, n) 71 | for i := range d { 72 | d[i] = 1 73 | } 74 | a := blas64.General{ 75 | Rows: n, 76 | Cols: n, 77 | Stride: lda, 78 | Data: nanSlice(n * lda), 79 | } 80 | work := make([]float64, a.Rows+a.Cols) 81 | 82 | Dlagge(a.Rows, a.Cols, 0, 0, d, a.Data, a.Stride, rnd, work) 83 | 84 | if !isOrthonormal(a) { 85 | t.Errorf("Case n=%v,lda=%v: unexpected result", n, lda) 86 | } 87 | } 88 | } 89 | 90 | } 91 | -------------------------------------------------------------------------------- /testlapack/testdata/dlahr2data.json.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gonum/lapack/e4cdc5a0bff924bb10be88482e635bd40429f65e/testlapack/testdata/dlahr2data.json.gz -------------------------------------------------------------------------------- /testlapack/testdata/dlaqr5data.json.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gonum/lapack/e4cdc5a0bff924bb10be88482e635bd40429f65e/testlapack/testdata/dlaqr5data.json.gz --------------------------------------------------------------------------------