├── .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 [](https://travis-ci.org/gonum/lapack) [](https://coveralls.io/github/gonum/lapack?branch=master) [](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
--------------------------------------------------------------------------------